From faf6752ff8bc030778a986d9329692b68e8bcadd Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 22 Aug 2019 22:20:38 +0200 Subject: [PATCH] Move create_context to a context --- jedi/api/__init__.py | 9 ++--- jedi/api/completion.py | 4 +-- jedi/inference/__init__.py | 63 +---------------------------------- jedi/inference/context.py | 63 ++++++++++++++++++++++++++++++++++- jedi/inference/syntax_tree.py | 2 +- 5 files changed, 68 insertions(+), 73 deletions(-) diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index ba74bc87..dcc8bc80 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -242,7 +242,7 @@ class Script(object): if leaf is None: return [] - context = self._inference_state.create_context(self._get_module_context(), leaf) + context = self._get_module_context().create_context(leaf) values = helpers.infer_goto_definition(self._inference_state, context, leaf) values = convert_values( @@ -302,7 +302,7 @@ class Script(object): # Without a name we really just want to jump to the result e.g. # executed by `foo()`, if we the cursor is after `)`. return self.goto_definitions(only_stubs=only_stubs, prefer_stubs=prefer_stubs) - context = self._inference_state.create_context(self._get_module_context(), tree_name) + context = self._get_module_context().create_context(tree_name) names = list(self._inference_state.goto(context, tree_name)) if follow_imports: @@ -371,10 +371,7 @@ class Script(object): if call_details is None: return [] - context = self._inference_state.create_context( - self._get_module_context(), - call_details.bracket_leaf - ) + context = self._get_module_context().create_context(call_details.bracket_leaf) definitions = helpers.cache_call_signatures( self._inference_state, context, diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 72b01f45..c8fc0839 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -254,9 +254,7 @@ class Completion: def _trailer_completions(self, previous_leaf): user_value = get_user_context(self._module_context, self._position) - inferred_context = self._inference_state.create_context( - self._module_context, previous_leaf - ) + inferred_context = self._module_context.create_context(previous_leaf) values = infer_call_of_leaf(inferred_context, previous_leaf) completion_names = [] debug.dbg('trailer completion values: %s', values, color='MAGENTA') diff --git a/jedi/inference/__init__.py b/jedi/inference/__init__.py index 6ef69a24..64ce0be4 100644 --- a/jedi/inference/__init__.py +++ b/jedi/inference/__init__.py @@ -77,8 +77,7 @@ from jedi.inference import helpers from jedi.inference.names import TreeNameDefinition, ParamName from jedi.inference.base_value import ContextualizedName, ContextualizedNode, \ ValueSet, NO_VALUES, iterate_values -from jedi.inference.value import ClassValue, FunctionValue, \ - AnonymousInstance, BoundMethod +from jedi.inference.value import ClassValue, FunctionValue from jedi.inference.context import CompForContext from jedi.inference.syntax_tree import infer_trailer, infer_expr_stmt, \ infer_node, check_tuple_assignments @@ -364,66 +363,6 @@ class InferenceState(object): stmt = name return context.goto(name, position=stmt.start_pos) - def create_context(self, base_context, node, node_is_value=False, node_is_object=False): - def parent_scope(node): - while True: - node = node.parent - - if parser_utils.is_scope(node): - return node - elif node.type in ('argument', 'testlist_comp'): - if node.children[1].type in ('comp_for', 'sync_comp_for'): - return node.children[1] - elif node.type == 'dictorsetmaker': - for n in node.children[1:4]: - # In dictionaries it can be pretty much anything. - if n.type in ('comp_for', 'sync_comp_for'): - return n - - def from_scope_node(scope_node, is_nested=True, node_is_object=False): - if scope_node == base_node: - return base_context - - is_funcdef = scope_node.type in ('funcdef', 'lambdef') - parent_scope = parser_utils.get_parent_scope(scope_node) - parent_context = from_scope_node(parent_scope) - - if is_funcdef: - func = FunctionValue.from_context(parent_context, scope_node) - if parent_context.is_class(): - # TODO _value private access! - instance = AnonymousInstance( - self, parent_context.parent_context, parent_context._value) - func = BoundMethod( - instance=instance, - function=func - ) - - if is_nested and not node_is_object: - return func.get_function_execution() - return func.as_context() - elif scope_node.type == 'classdef': - return ClassValue(self, parent_context, scope_node).as_context() - elif scope_node.type in ('comp_for', 'sync_comp_for'): - if node.start_pos >= scope_node.children[-1].start_pos: - return parent_context - return CompForContext(parent_context, scope_node) - raise Exception("There's a scope that was not managed.") - - base_node = base_context.tree_node - - if node_is_value and parser_utils.is_scope(node): - scope_node = node - else: - scope_node = parent_scope(node) - if scope_node.type in ('funcdef', 'classdef'): - colon = scope_node.children[scope_node.children.index(':')] - if node.start_pos < colon.start_pos: - parent = node.parent - if not (parent.type == 'param' and parent.name == node): - scope_node = parent_scope(scope_node) - return from_scope_node(scope_node, is_nested=True, node_is_object=node_is_object) - def parse_and_get_code(self, code=None, path=None, encoding='utf-8', use_latest_grammar=False, file_io=None, **kwargs): if self.allow_different_encoding: diff --git a/jedi/inference/context.py b/jedi/inference/context.py index a438baf3..78a4470c 100644 --- a/jedi/inference/context.py +++ b/jedi/inference/context.py @@ -2,6 +2,7 @@ from abc import abstractmethod from jedi.inference.filters import ParserTreeFilter, MergedFilter, \ GlobalNameFilter +from jedi import parser_utils class AbstractContext(object): @@ -22,7 +23,67 @@ class AbstractContext(object): return self._value.get_root_context() def create_context(self, node, node_is_value=False, node_is_object=False): - return self.inference_state.create_context(self, node, node_is_value, node_is_object) + from jedi.inference.value import ClassValue, FunctionValue, \ + AnonymousInstance, BoundMethod + + def parent_scope(node): + while True: + node = node.parent + + if parser_utils.is_scope(node): + return node + elif node.type in ('argument', 'testlist_comp'): + if node.children[1].type in ('comp_for', 'sync_comp_for'): + return node.children[1] + elif node.type == 'dictorsetmaker': + for n in node.children[1:4]: + # In dictionaries it can be pretty much anything. + if n.type in ('comp_for', 'sync_comp_for'): + return n + + def from_scope_node(scope_node, is_nested=True, node_is_object=False): + if scope_node == base_node: + return self + + is_funcdef = scope_node.type in ('funcdef', 'lambdef') + parent_scope = parser_utils.get_parent_scope(scope_node) + parent_context = from_scope_node(parent_scope) + + if is_funcdef: + func = FunctionValue.from_context(parent_context, scope_node) + if parent_context.is_class(): + # TODO _value private access! + instance = AnonymousInstance( + self.inference_state, parent_context.parent_context, parent_context._value) + func = BoundMethod( + instance=instance, + function=func + ) + + if is_nested and not node_is_object: + return func.get_function_execution() + return func.as_context() + elif scope_node.type == 'classdef': + return ClassValue(self.inference_state, parent_context, scope_node).as_context() + elif scope_node.type in ('comp_for', 'sync_comp_for'): + if node.start_pos >= scope_node.children[-1].start_pos: + return parent_context + return CompForContext(parent_context, scope_node) + raise Exception("There's a scope that was not managed.") + + base_node = self.tree_node + + if node_is_value and parser_utils.is_scope(node): + scope_node = node + else: + scope_node = parent_scope(node) + if scope_node.type in ('funcdef', 'classdef'): + colon = scope_node.children[scope_node.children.index(':')] + if node.start_pos < colon.start_pos: + parent = node.parent + if not (parent.type == 'param' and parent.name == node): + scope_node = parent_scope(scope_node) + return from_scope_node(scope_node, is_nested=True, node_is_object=node_is_object) def goto(self, name_or_str, position): from jedi.inference import finder diff --git a/jedi/inference/syntax_tree.py b/jedi/inference/syntax_tree.py index d40e90d1..72f43b78 100644 --- a/jedi/inference/syntax_tree.py +++ b/jedi/inference/syntax_tree.py @@ -578,7 +578,7 @@ def tree_name_to_values(inference_state, context, tree_name): filters = [next(filters)] return finder.find(filters, attribute_lookup=False) elif node.type not in ('import_from', 'import_name'): - c = inference_state.create_context(context, tree_name) + c = context.create_context(tree_name) return infer_atom(c, tree_name) typ = node.type