forked from VimPlug/jedi
Move is_scope and get_parent_scope out of the parser.
This commit is contained in:
@@ -194,7 +194,7 @@ class Evaluator(object):
|
|||||||
if_stmt = if_stmt.parent
|
if_stmt = if_stmt.parent
|
||||||
if if_stmt.type in ('if_stmt', 'for_stmt'):
|
if if_stmt.type in ('if_stmt', 'for_stmt'):
|
||||||
break
|
break
|
||||||
if if_stmt.is_scope():
|
if parser_utils.is_scope(if_stmt):
|
||||||
if_stmt = None
|
if_stmt = None
|
||||||
break
|
break
|
||||||
predefined_if_name_dict = context.predefined_names.get(if_stmt)
|
predefined_if_name_dict = context.predefined_names.get(if_stmt)
|
||||||
@@ -537,7 +537,7 @@ class Evaluator(object):
|
|||||||
while True:
|
while True:
|
||||||
node = node.parent
|
node = node.parent
|
||||||
|
|
||||||
if node.is_scope():
|
if parser_utils.is_scope(node):
|
||||||
return node
|
return node
|
||||||
elif node.type in ('argument', 'testlist_comp'):
|
elif node.type in ('argument', 'testlist_comp'):
|
||||||
if node.children[1].type == 'comp_for':
|
if node.children[1].type == 'comp_for':
|
||||||
@@ -553,7 +553,7 @@ class Evaluator(object):
|
|||||||
return base_context
|
return base_context
|
||||||
|
|
||||||
is_funcdef = scope_node.type in ('funcdef', 'lambdef')
|
is_funcdef = scope_node.type in ('funcdef', 'lambdef')
|
||||||
parent_scope = scope_node.get_parent_scope()
|
parent_scope = parser_utils.get_parent_scope(scope_node)
|
||||||
parent_context = from_scope_node(parent_scope, child_is_funcdef=is_funcdef)
|
parent_context = from_scope_node(parent_scope, child_is_funcdef=is_funcdef)
|
||||||
|
|
||||||
if is_funcdef:
|
if is_funcdef:
|
||||||
@@ -586,7 +586,7 @@ class Evaluator(object):
|
|||||||
|
|
||||||
base_node = base_context.tree_node
|
base_node = base_context.tree_node
|
||||||
|
|
||||||
if node_is_context and node.is_scope():
|
if node_is_context and parser_utils.is_scope(node):
|
||||||
scope_node = node
|
scope_node = node
|
||||||
else:
|
else:
|
||||||
if node.parent.type in ('funcdef', 'classdef'):
|
if node.parent.type in ('funcdef', 'classdef'):
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ from jedi.evaluate.cache import memoize_default
|
|||||||
from jedi.evaluate import imports
|
from jedi.evaluate import imports
|
||||||
from jedi.evaluate.param import TreeArguments, create_default_param
|
from jedi.evaluate.param import TreeArguments, create_default_param
|
||||||
from jedi.common import to_list, unite
|
from jedi.common import to_list, unite
|
||||||
|
from jedi.parser_utils import get_parent_scope
|
||||||
|
|
||||||
|
|
||||||
MAX_PARAM_SEARCHES = 20
|
MAX_PARAM_SEARCHES = 20
|
||||||
@@ -103,7 +104,7 @@ def _search_function_executions(evaluator, module_context, funcdef):
|
|||||||
func_string_name = funcdef.name.value
|
func_string_name = funcdef.name.value
|
||||||
compare_node = funcdef
|
compare_node = funcdef
|
||||||
if func_string_name == '__init__':
|
if func_string_name == '__init__':
|
||||||
cls = funcdef.get_parent_scope()
|
cls = get_parent_scope(funcdef)
|
||||||
if isinstance(cls, tree.Class):
|
if isinstance(cls, tree.Class):
|
||||||
func_string_name = cls.name.value
|
func_string_name = cls.name.value
|
||||||
compare_node = cls
|
compare_node = cls
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from abc import abstractmethod
|
|||||||
from jedi.parser.tree import search_ancestor
|
from jedi.parser.tree import search_ancestor
|
||||||
from jedi.evaluate import flow_analysis
|
from jedi.evaluate import flow_analysis
|
||||||
from jedi.common import to_list, unite
|
from jedi.common import to_list, unite
|
||||||
|
from jedi.parser_utils import get_parent_scope
|
||||||
|
|
||||||
|
|
||||||
class AbstractNameDefinition(object):
|
class AbstractNameDefinition(object):
|
||||||
@@ -189,7 +190,7 @@ class ParserTreeFilter(AbstractUsedNamesFilter):
|
|||||||
if parent.type == 'trailer':
|
if parent.type == 'trailer':
|
||||||
return False
|
return False
|
||||||
base_node = parent if parent.type in ('classdef', 'funcdef') else name
|
base_node = parent if parent.type in ('classdef', 'funcdef') else name
|
||||||
return base_node.get_parent_scope() == self._parser_scope
|
return get_parent_scope(base_node) == self._parser_scope
|
||||||
|
|
||||||
def _check_flows(self, names):
|
def _check_flows(self, names):
|
||||||
for name in sorted(names, key=lambda name: name.start_pos, reverse=True):
|
for name in sorted(names, key=lambda name: name.start_pos, reverse=True):
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ from jedi.evaluate import param
|
|||||||
from jedi.evaluate import helpers
|
from jedi.evaluate import helpers
|
||||||
from jedi.evaluate.filters import get_global_filters
|
from jedi.evaluate.filters import get_global_filters
|
||||||
from jedi.evaluate.context import ContextualizedName, ContextualizedNode
|
from jedi.evaluate.context import ContextualizedName, ContextualizedNode
|
||||||
|
from jedi.parser_utils import is_scope, get_parent_scope
|
||||||
|
|
||||||
|
|
||||||
class NameFinder(object):
|
class NameFinder(object):
|
||||||
@@ -106,7 +107,7 @@ class NameFinder(object):
|
|||||||
if self._context.predefined_names:
|
if self._context.predefined_names:
|
||||||
# TODO is this ok? node might not always be a tree.Name
|
# TODO is this ok? node might not always be a tree.Name
|
||||||
node = self._name
|
node = self._name
|
||||||
while node is not None and not node.is_scope():
|
while node is not None and not is_scope(node):
|
||||||
node = node.parent
|
node = node.parent
|
||||||
if node.type in ("if_stmt", "for_stmt", "comp_for"):
|
if node.type in ("if_stmt", "for_stmt", "comp_for"):
|
||||||
try:
|
try:
|
||||||
@@ -160,7 +161,7 @@ class NameFinder(object):
|
|||||||
if base_node.type == 'comp_for':
|
if base_node.type == 'comp_for':
|
||||||
return types
|
return types
|
||||||
while True:
|
while True:
|
||||||
flow_scope = flow_scope.get_parent_scope(include_flows=True)
|
flow_scope = get_parent_scope(flow_scope, include_flows=True)
|
||||||
n = _check_flow_information(self._name_context, flow_scope,
|
n = _check_flow_information(self._name_context, flow_scope,
|
||||||
self._name, self._position)
|
self._name, self._position)
|
||||||
if n is not None:
|
if n is not None:
|
||||||
@@ -298,7 +299,7 @@ def _check_flow_information(context, flow, search_name, pos):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
result = None
|
result = None
|
||||||
if flow.is_scope():
|
if is_scope(flow):
|
||||||
# Check for asserts.
|
# Check for asserts.
|
||||||
module_node = flow.get_root_node()
|
module_node = flow.get_root_node()
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
from jedi.parser_utils import get_flow_branch_keyword
|
from jedi.parser_utils import get_flow_branch_keyword, is_scope, get_parent_scope
|
||||||
|
|
||||||
|
|
||||||
class Status(object):
|
class Status(object):
|
||||||
lookup_table = {}
|
lookup_table = {}
|
||||||
|
|
||||||
@@ -32,14 +34,14 @@ UNSURE = Status(None, 'unsure')
|
|||||||
|
|
||||||
def _get_flow_scopes(node):
|
def _get_flow_scopes(node):
|
||||||
while True:
|
while True:
|
||||||
node = node.get_parent_scope(include_flows=True)
|
node = get_parent_scope(node, include_flows=True)
|
||||||
if node is None or node.is_scope():
|
if node is None or is_scope(node):
|
||||||
return
|
return
|
||||||
yield node
|
yield node
|
||||||
|
|
||||||
|
|
||||||
def reachability_check(context, context_scope, node, origin_scope=None):
|
def reachability_check(context, context_scope, node, origin_scope=None):
|
||||||
first_flow_scope = node.get_parent_scope(include_flows=True)
|
first_flow_scope = get_parent_scope(node, include_flows=True)
|
||||||
if origin_scope is not None:
|
if origin_scope is not None:
|
||||||
origin_flow_scopes = list(_get_flow_scopes(origin_scope))
|
origin_flow_scopes = list(_get_flow_scopes(origin_scope))
|
||||||
node_flow_scopes = list(_get_flow_scopes(node))
|
node_flow_scopes = list(_get_flow_scopes(node))
|
||||||
@@ -95,7 +97,7 @@ def _break_check(context, context_scope, flow_scope, node):
|
|||||||
return reachable
|
return reachable
|
||||||
|
|
||||||
if context_scope != flow_scope and context_scope != flow_scope.parent:
|
if context_scope != flow_scope and context_scope != flow_scope.parent:
|
||||||
flow_scope = flow_scope.get_parent_scope(include_flows=True)
|
flow_scope = get_parent_scope(flow_scope, include_flows=True)
|
||||||
return reachable & _break_check(context, context_scope, flow_scope, node)
|
return reachable & _break_check(context, context_scope, flow_scope, node)
|
||||||
else:
|
else:
|
||||||
return reachable
|
return reachable
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from itertools import chain
|
|||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from jedi.parser.python import tree
|
from jedi.parser.python import tree
|
||||||
|
from jedi.parser_utils import get_parent_scope
|
||||||
|
|
||||||
|
|
||||||
def deep_ast_copy(obj):
|
def deep_ast_copy(obj):
|
||||||
@@ -143,7 +144,7 @@ def get_module_names(module, all_scopes):
|
|||||||
# parent_scope. There's None as a parent, because nodes in the module
|
# parent_scope. There's None as a parent, because nodes in the module
|
||||||
# node have the parent module and not suite as all the others.
|
# node have the parent module and not suite as all the others.
|
||||||
# Therefore it's important to catch that case.
|
# Therefore it's important to catch that case.
|
||||||
names = [n for n in names if n.get_parent_scope().parent in (module, None)]
|
names = [n for n in names if get_parent_scope(n).parent in (module, None)]
|
||||||
return names
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from jedi.cache import memoize_method
|
|||||||
from jedi.evaluate import representation as er
|
from jedi.evaluate import representation as er
|
||||||
from jedi.evaluate.dynamic import search_params
|
from jedi.evaluate.dynamic import search_params
|
||||||
from jedi.evaluate import iterable
|
from jedi.evaluate import iterable
|
||||||
|
from jedi.parser_utils import get_parent_scope
|
||||||
|
|
||||||
|
|
||||||
class AbstractInstanceContext(Context):
|
class AbstractInstanceContext(Context):
|
||||||
@@ -151,7 +152,7 @@ class AbstractInstanceContext(Context):
|
|||||||
def create_instance_context(self, class_context, node):
|
def create_instance_context(self, class_context, node):
|
||||||
if node.parent.type in ('funcdef', 'classdef'):
|
if node.parent.type in ('funcdef', 'classdef'):
|
||||||
node = node.parent
|
node = node.parent
|
||||||
scope = node.get_parent_scope()
|
scope = get_parent_scope(node)
|
||||||
if scope == class_context.tree_node:
|
if scope == class_context.tree_node:
|
||||||
return class_context
|
return class_context
|
||||||
else:
|
else:
|
||||||
@@ -189,7 +190,7 @@ class CompiledInstance(AbstractInstanceContext):
|
|||||||
return compiled.CompiledContextName(self, self.class_context.name.string_name)
|
return compiled.CompiledContextName(self, self.class_context.name.string_name)
|
||||||
|
|
||||||
def create_instance_context(self, class_context, node):
|
def create_instance_context(self, class_context, node):
|
||||||
if node.get_parent_scope().type == 'classdef':
|
if get_parent_scope(node).type == 'classdef':
|
||||||
return class_context
|
return class_context
|
||||||
else:
|
else:
|
||||||
return super(CompiledInstance, self).create_instance_context(class_context, node)
|
return super(CompiledInstance, self).create_instance_context(class_context, node)
|
||||||
@@ -332,7 +333,7 @@ class InstanceClassFilter(filters.ParserTreeFilter):
|
|||||||
while node is not None:
|
while node is not None:
|
||||||
if node == self._parser_scope or node == self.context:
|
if node == self._parser_scope or node == self.context:
|
||||||
return True
|
return True
|
||||||
node = node.get_parent_scope()
|
node = get_parent_scope(node)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _access_possible(self, name):
|
def _access_possible(self, name):
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ class FunctionContext(use_metaclass(CachedMetaClass, context.TreeContext)):
|
|||||||
def py__class__(self):
|
def py__class__(self):
|
||||||
# This differentiation is only necessary for Python2. Python3 does not
|
# This differentiation is only necessary for Python2. Python3 does not
|
||||||
# use a different method class.
|
# use a different method class.
|
||||||
if isinstance(self.tree_node.get_parent_scope(), tree.Class):
|
if isinstance(parser_utils.get_parent_scope(self.tree_node), tree.Class):
|
||||||
name = 'METHOD_CLASS'
|
name = 'METHOD_CLASS'
|
||||||
else:
|
else:
|
||||||
name = 'FUNCTION_CLASS'
|
name = 'FUNCTION_CLASS'
|
||||||
|
|||||||
@@ -59,19 +59,6 @@ class DocstringMixin(object):
|
|||||||
|
|
||||||
|
|
||||||
class PythonMixin(object):
|
class PythonMixin(object):
|
||||||
def get_parent_scope(self, include_flows=False):
|
|
||||||
"""
|
|
||||||
Returns the underlying scope.
|
|
||||||
"""
|
|
||||||
scope = self.parent
|
|
||||||
while scope is not None:
|
|
||||||
if include_flows and isinstance(scope, Flow):
|
|
||||||
return scope
|
|
||||||
if scope.is_scope():
|
|
||||||
break
|
|
||||||
scope = scope.parent
|
|
||||||
return scope
|
|
||||||
|
|
||||||
def get_definition(self):
|
def get_definition(self):
|
||||||
if self.type in ('newline', 'endmarker'):
|
if self.type in ('newline', 'endmarker'):
|
||||||
raise ValueError('Cannot get the indentation of whitespace or indentation.')
|
raise ValueError('Cannot get the indentation of whitespace or indentation.')
|
||||||
@@ -90,10 +77,6 @@ class PythonMixin(object):
|
|||||||
break
|
break
|
||||||
return scope
|
return scope
|
||||||
|
|
||||||
def is_scope(self):
|
|
||||||
# Default is not being a scope. Just inherit from Scope.
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_name_of_position(self, position):
|
def get_name_of_position(self, position):
|
||||||
for c in self.children:
|
for c in self.children:
|
||||||
if isinstance(c, Leaf):
|
if isinstance(c, Leaf):
|
||||||
@@ -267,9 +250,6 @@ class Scope(PythonBaseNode, DocstringMixin):
|
|||||||
|
|
||||||
return scan(self.children)
|
return scan(self.children)
|
||||||
|
|
||||||
def is_scope(self):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_suite(self):
|
def get_suite(self):
|
||||||
"""
|
"""
|
||||||
Returns the part that is executed by the function.
|
Returns the part that is executed by the function.
|
||||||
@@ -1057,9 +1037,6 @@ class CompFor(PythonBaseNode):
|
|||||||
type = 'comp_for'
|
type = 'comp_for'
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
def is_scope(self):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_defined_names(self):
|
def get_defined_names(self):
|
||||||
"""
|
"""
|
||||||
Returns the a list of `Name` that the comprehension defines.
|
Returns the a list of `Name` that the comprehension defines.
|
||||||
|
|||||||
@@ -217,3 +217,21 @@ def get_following_comment_same_line(node):
|
|||||||
comment = comment[:comment.index("\n")]
|
comment = comment[:comment.index("\n")]
|
||||||
return comment
|
return comment
|
||||||
|
|
||||||
|
|
||||||
|
def is_scope(node):
|
||||||
|
return node.type in ('file_input', 'classdef', 'funcdef', 'lambdef', 'comp_for')
|
||||||
|
|
||||||
|
|
||||||
|
def get_parent_scope(node, include_flows=False):
|
||||||
|
"""
|
||||||
|
Returns the underlying scope.
|
||||||
|
"""
|
||||||
|
scope = node.parent
|
||||||
|
while scope is not None:
|
||||||
|
if include_flows and isinstance(scope, tree.Flow):
|
||||||
|
return scope
|
||||||
|
if is_scope(scope):
|
||||||
|
break
|
||||||
|
scope = scope.parent
|
||||||
|
return scope
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user