diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index ab54e72d..d8c6ede1 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -16,7 +16,7 @@ import sys from jedi.parser.python import load_grammar from jedi.parser.python import tree from jedi.parser.python import parse -from jedi.parser_utils import get_executable_nodes +from jedi.parser_utils import get_executable_nodes, get_statement_of_position from jedi import debug from jedi import settings from jedi import common @@ -194,7 +194,7 @@ class Script(object): :rtype: list of :class:`classes.Definition` """ module_node = self._get_module_node() - leaf = module_node.name_for_position(self._pos) + leaf = module_node.get_name_of_position(self._pos) if leaf is None: leaf = module_node.get_leaf_for_position(self._pos) if leaf is None: @@ -238,7 +238,7 @@ class Script(object): """ Used for goto_assignments and usages. """ - name = self._get_module_node().name_for_position(self._pos) + name = self._get_module_node().get_name_of_position(self._pos) if name is None: return [] context = self._evaluator.create_context(self._get_module(), name) @@ -259,13 +259,13 @@ class Script(object): settings.dynamic_flow_information, False try: module_node = self._get_module_node() - user_stmt = module_node.get_statement_for_position(self._pos) + user_stmt = get_statement_of_position(module_node, self._pos) definition_names = self._goto() if not definition_names and isinstance(user_stmt, tree.Import): # For not defined imports (goto doesn't find something, we take # the name as a definition. This is enough, because every name # points to it. - name = user_stmt.name_for_position(self._pos) + name = user_stmt.get_name_of_position(self._pos) if name is None: # Must be syntax return [] diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 6aeaca80..bb6e2e18 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -8,6 +8,7 @@ from jedi.evaluate import imports from jedi.api import keywords from jedi.evaluate.helpers import evaluate_call_of_leaf from jedi.evaluate.filters import get_global_filters +from jedi.parser_utils import get_statement_of_position def get_call_signature_param_names(call_signatures): @@ -51,7 +52,7 @@ def get_user_scope(module_context, position): """ Returns the scope in which the user resides. This includes flows. """ - user_stmt = module_context.tree_node.get_statement_for_position(position) + user_stmt = get_statement_of_position(module_context.tree_node, position) if user_stmt is None: def scan(scope): for s in scope.children: diff --git a/jedi/parser/python/tree.py b/jedi/parser/python/tree.py index e3896cef..1bf77e24 100644 --- a/jedi/parser/python/tree.py +++ b/jedi/parser/python/tree.py @@ -137,30 +137,17 @@ class PythonMixin(object): # Default is not being a scope. Just inherit from Scope. return False - def name_for_position(self, position): + def get_name_of_position(self, position): for c in self.children: if isinstance(c, Leaf): if isinstance(c, Name) and c.start_pos <= position <= c.end_pos: return c else: - result = c.name_for_position(position) + result = c.get_name_of_position(position) if result is not None: return result return None - def get_statement_for_position(self, pos): - for c in self.children: - if c.start_pos <= pos <= c.end_pos: - if c.type not in ('decorated', 'simple_stmt', 'suite') \ - and not isinstance(c, (Flow, ClassOrFunc)): - return c - else: - try: - return c.get_statement_for_position(pos) - except AttributeError: - pass # Must be a non-scope - return None - class PythonLeaf(Leaf, PythonMixin): __slots__ = () diff --git a/jedi/parser_utils.py b/jedi/parser_utils.py index 2a89203c..de1e6652 100644 --- a/jedi/parser_utils.py +++ b/jedi/parser_utils.py @@ -82,3 +82,16 @@ def get_flow_branch_keyword(flow_node, node): if first_leaf in _FLOW_KEYWORDS: keyword = first_leaf return 0 + +def get_statement_of_position(node, pos): + for c in node.children: + if c.start_pos <= pos <= c.end_pos: + if c.type not in ('decorated', 'simple_stmt', 'suite') \ + and not isinstance(c, (tree.Flow, tree.ClassOrFunc)): + return c + else: + try: + return get_statement_of_position(c, pos) + except AttributeError: + pass # Must be a non-scope + return None diff --git a/test/test_parser/test_parser.py b/test/test_parser/test_parser.py index 6d4920f8..61b11f54 100644 --- a/test/test_parser/test_parser.py +++ b/test/test_parser/test_parser.py @@ -9,6 +9,7 @@ from jedi._compatibility import u, is_py3 from jedi.parser.python import parse, load_grammar from jedi.parser.python import tree from jedi.common import splitlines +from jedi.parser_utils import get_statement_of_position def test_user_statement_on_import(): @@ -18,7 +19,7 @@ def test_user_statement_on_import(): for pos in [(2, 1), (2, 4)]: p = parse(s) - stmt = p.get_statement_for_position(pos) + stmt = get_statement_of_position(p, pos) assert isinstance(stmt, tree.Import) assert [n.value for n in stmt.get_defined_names()] == ['time']