1
0
forked from VimPlug/jedi

Move is_scope and get_parent_scope out of the parser.

This commit is contained in:
Dave Halter
2017-05-07 14:58:53 +02:00
parent 0882849e65
commit 536e62e67d
10 changed files with 44 additions and 42 deletions

View File

@@ -194,7 +194,7 @@ class Evaluator(object):
if_stmt = if_stmt.parent
if if_stmt.type in ('if_stmt', 'for_stmt'):
break
if if_stmt.is_scope():
if parser_utils.is_scope(if_stmt):
if_stmt = None
break
predefined_if_name_dict = context.predefined_names.get(if_stmt)
@@ -537,7 +537,7 @@ class Evaluator(object):
while True:
node = node.parent
if node.is_scope():
if parser_utils.is_scope(node):
return node
elif node.type in ('argument', 'testlist_comp'):
if node.children[1].type == 'comp_for':
@@ -553,7 +553,7 @@ class Evaluator(object):
return base_context
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)
if is_funcdef:
@@ -586,7 +586,7 @@ class Evaluator(object):
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
else:
if node.parent.type in ('funcdef', 'classdef'):

View File

@@ -24,6 +24,7 @@ from jedi.evaluate.cache import memoize_default
from jedi.evaluate import imports
from jedi.evaluate.param import TreeArguments, create_default_param
from jedi.common import to_list, unite
from jedi.parser_utils import get_parent_scope
MAX_PARAM_SEARCHES = 20
@@ -103,7 +104,7 @@ def _search_function_executions(evaluator, module_context, funcdef):
func_string_name = funcdef.name.value
compare_node = funcdef
if func_string_name == '__init__':
cls = funcdef.get_parent_scope()
cls = get_parent_scope(funcdef)
if isinstance(cls, tree.Class):
func_string_name = cls.name.value
compare_node = cls

View File

@@ -7,6 +7,7 @@ from abc import abstractmethod
from jedi.parser.tree import search_ancestor
from jedi.evaluate import flow_analysis
from jedi.common import to_list, unite
from jedi.parser_utils import get_parent_scope
class AbstractNameDefinition(object):
@@ -189,7 +190,7 @@ class ParserTreeFilter(AbstractUsedNamesFilter):
if parent.type == 'trailer':
return False
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):
for name in sorted(names, key=lambda name: name.start_pos, reverse=True):

View File

@@ -32,6 +32,7 @@ from jedi.evaluate import param
from jedi.evaluate import helpers
from jedi.evaluate.filters import get_global_filters
from jedi.evaluate.context import ContextualizedName, ContextualizedNode
from jedi.parser_utils import is_scope, get_parent_scope
class NameFinder(object):
@@ -106,7 +107,7 @@ class NameFinder(object):
if self._context.predefined_names:
# TODO is this ok? node might not always be a tree.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
if node.type in ("if_stmt", "for_stmt", "comp_for"):
try:
@@ -160,7 +161,7 @@ class NameFinder(object):
if base_node.type == 'comp_for':
return types
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,
self._name, self._position)
if n is not None:
@@ -298,7 +299,7 @@ def _check_flow_information(context, flow, search_name, pos):
return None
result = None
if flow.is_scope():
if is_scope(flow):
# Check for asserts.
module_node = flow.get_root_node()
try:

View File

@@ -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):
lookup_table = {}
@@ -32,14 +34,14 @@ UNSURE = Status(None, 'unsure')
def _get_flow_scopes(node):
while True:
node = node.get_parent_scope(include_flows=True)
if node is None or node.is_scope():
node = get_parent_scope(node, include_flows=True)
if node is None or is_scope(node):
return
yield node
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:
origin_flow_scopes = list(_get_flow_scopes(origin_scope))
node_flow_scopes = list(_get_flow_scopes(node))
@@ -95,7 +97,7 @@ def _break_check(context, context_scope, flow_scope, node):
return reachable
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)
else:
return reachable

View File

@@ -3,6 +3,7 @@ from itertools import chain
from contextlib import contextmanager
from jedi.parser.python import tree
from jedi.parser_utils import get_parent_scope
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
# node have the parent module and not suite as all the others.
# 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

View File

@@ -11,6 +11,7 @@ from jedi.cache import memoize_method
from jedi.evaluate import representation as er
from jedi.evaluate.dynamic import search_params
from jedi.evaluate import iterable
from jedi.parser_utils import get_parent_scope
class AbstractInstanceContext(Context):
@@ -151,7 +152,7 @@ class AbstractInstanceContext(Context):
def create_instance_context(self, class_context, node):
if node.parent.type in ('funcdef', 'classdef'):
node = node.parent
scope = node.get_parent_scope()
scope = get_parent_scope(node)
if scope == class_context.tree_node:
return class_context
else:
@@ -189,7 +190,7 @@ class CompiledInstance(AbstractInstanceContext):
return compiled.CompiledContextName(self, self.class_context.name.string_name)
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
else:
return super(CompiledInstance, self).create_instance_context(class_context, node)
@@ -332,7 +333,7 @@ class InstanceClassFilter(filters.ParserTreeFilter):
while node is not None:
if node == self._parser_scope or node == self.context:
return True
node = node.get_parent_scope()
node = get_parent_scope(node)
return False
def _access_possible(self, name):

View File

@@ -276,7 +276,7 @@ class FunctionContext(use_metaclass(CachedMetaClass, context.TreeContext)):
def py__class__(self):
# This differentiation is only necessary for Python2. Python3 does not
# 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'
else:
name = 'FUNCTION_CLASS'

View File

@@ -59,19 +59,6 @@ class DocstringMixin(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):
if self.type in ('newline', 'endmarker'):
raise ValueError('Cannot get the indentation of whitespace or indentation.')
@@ -90,10 +77,6 @@ class PythonMixin(object):
break
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):
for c in self.children:
if isinstance(c, Leaf):
@@ -267,9 +250,6 @@ class Scope(PythonBaseNode, DocstringMixin):
return scan(self.children)
def is_scope(self):
return True
def get_suite(self):
"""
Returns the part that is executed by the function.
@@ -1057,9 +1037,6 @@ class CompFor(PythonBaseNode):
type = 'comp_for'
__slots__ = ()
def is_scope(self):
return True
def get_defined_names(self):
"""
Returns the a list of `Name` that the comprehension defines.

View File

@@ -217,3 +217,21 @@ def get_following_comment_same_line(node):
comment = comment[:comment.index("\n")]
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