diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 9cc256a6..47c15797 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -284,7 +284,7 @@ class Completion: cls = tree.search_ancestor(leaf, 'classdef') if isinstance(cls, (tree.Class, tree.Function)): # Complete the methods that are defined in the super classes. - random_value = self._module_context.create_context( + random_context = self._module_context.create_context( cls, node_is_value=True ) @@ -294,7 +294,8 @@ class Completion: if cls.start_pos[1] >= leaf.start_pos[1]: return - filters = random_value.get_filters(is_instance=True) + # TODO _value private access! + filters = random_context._value.get_filters(is_instance=True) # The first dict is the dictionary of class itself. next(filters) for filter in filters: diff --git a/jedi/inference/__init__.py b/jedi/inference/__init__.py index d94763a7..d1d1a7f1 100644 --- a/jedi/inference/__init__.py +++ b/jedi/inference/__init__.py @@ -349,13 +349,13 @@ class InferenceState(object): new_dotted.children[index - 1:] = [] values = context.infer_node(new_dotted) return unite( - value.py__getattribute__(name, name_value=value, is_goto=True) + value.goto(name, name_value=value) for value in values ) if node_type == 'trailer' and par.children[0] == '.': values = helpers.infer_call_of_leaf(context, name, cut_own_trailer=True) - return values.py__getattribute__(name, name_context=context, is_goto=True) + return values.goto(name, name_context=context) else: stmt = tree.search_ancestor( name, 'expr_stmt', 'lambdef' @@ -391,8 +391,9 @@ class InferenceState(object): 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) + self, parent_context.parent_context, parent_context._value) func = BoundMethod( instance=instance, function=func @@ -402,7 +403,7 @@ class InferenceState(object): return func.get_function_execution() return func elif scope_node.type == 'classdef': - return ClassValue(self, parent_context, scope_node) + 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 diff --git a/jedi/inference/base_value.py b/jedi/inference/base_value.py index b666f99b..a95babf4 100644 --- a/jedi/inference/base_value.py +++ b/jedi/inference/base_value.py @@ -71,6 +71,18 @@ class HelperValueMixin(object): filters = f.get_value_filters() return f.find(filters, attribute_lookup=True) + def goto(self, name_or_str, name_context=None, analysis_errors=True): + """ + :param position: Position of the last statement -> tuple of line, column + """ + if name_context is None: + name_context = self + from jedi.inference import finder + f = finder.NameFinder(self.inference_state, self, name_context, name_or_str, + analysis_errors=analysis_errors) + filters = f.get_value_filters() + return f.filter_name(filters) + def py__await__(self): await_value_set = self.py__getattribute__(u"__await__") if not await_value_set: @@ -403,9 +415,10 @@ class ValueSet(BaseValueSet): def execute_with_values(self, *args, **kwargs): return ValueSet.from_sets(c.execute_with_values(*args, **kwargs) for c in self._set) + def goto(self, *args, **kwargs): + return reduce(add, [c.goto(*args, **kwargs) for c in self._set], []) + def py__getattribute__(self, *args, **kwargs): - if kwargs.get('is_goto'): - return reduce(add, [c.py__getattribute__(*args, **kwargs) for c in self._set], []) return ValueSet.from_sets(c.py__getattribute__(*args, **kwargs) for c in self._set) def get_item(self, *args, **kwargs): @@ -422,9 +435,6 @@ class ValueSet(BaseValueSet): value_set |= method() return value_set - def as_context(self): - return [v.as_context() for v in self._set] - def gather_annotation_classes(self): return ValueSet.from_sets([c.gather_annotation_classes() for c in self._set]) diff --git a/jedi/inference/context.py b/jedi/inference/context.py index fdf32e88..97f894a8 100644 --- a/jedi/inference/context.py +++ b/jedi/inference/context.py @@ -72,6 +72,9 @@ class AbstractContext(object): def py__name__(self): return self._value.py__name__() + def get_qualified_names(self): + return self._value.get_qualified_names() + def py__doc__(self): return self._value.py__doc__() @@ -103,6 +106,7 @@ class ModuleContext(AbstractContext): def get_filters(self, until_position=None, origin_scope=None): filters = self._value.get_filters(origin_scope) # Skip the first filter and replace it. + next(filters) yield MergedFilter( ParserTreeFilter( context=self, diff --git a/jedi/inference/gradual/annotation.py b/jedi/inference/gradual/annotation.py index 32861be2..fd6c71b9 100644 --- a/jedi/inference/gradual/annotation.py +++ b/jedi/inference/gradual/annotation.py @@ -169,11 +169,11 @@ def _infer_param(execution_context, param): param_comment = params_comments[index] return _infer_annotation_string( - execution_context.function_value.get_default_param_value(), + execution_context.function_value.get_default_param_context(), param_comment ) # Annotations are like default params and resolve in the same way. - value = execution_context.function_value.get_default_param_value() + value = execution_context.function_value.get_default_param_context() return infer_annotation(value, annotation) @@ -210,13 +210,13 @@ def infer_return_types(function_execution_context): return NO_VALUES return _infer_annotation_string( - function_execution_context.function_value.get_default_param_value(), + function_execution_context.function_value.get_default_param_context(), match.group(1).strip() ).execute_annotation() if annotation is None: return NO_VALUES - value = function_execution_context.function_value.get_default_param_value() + value = function_execution_context.function_value.get_default_param_context() unknown_type_vars = list(find_unknown_type_vars(value, annotation)) annotation_values = infer_annotation(value, annotation) if not unknown_type_vars: @@ -241,7 +241,7 @@ def infer_type_vars_for_execution(execution_context, annotation_dict): 2. Infer type vars with the execution state we have. 3. Return the union of all type vars that have been found. """ - value = execution_context.function_value.get_default_param_value() + value = execution_context.function_value.get_default_param_context() annotation_variable_results = {} executed_params, _ = execution_context.get_executed_params_and_issues() diff --git a/jedi/inference/gradual/conversion.py b/jedi/inference/gradual/conversion.py index a0a86e54..7226f749 100644 --- a/jedi/inference/gradual/conversion.py +++ b/jedi/inference/gradual/conversion.py @@ -69,7 +69,7 @@ def _try_stub_to_python_names(names, prefer_stub_to_compiled=False): ignore_compiled=prefer_stub_to_compiled, ) if values and name_list: - new_names = values.py__getattribute__(name_list[-1], is_goto=True) + new_names = values.goto(name_list[-1]) for new_name in new_names: yield new_name if new_names: @@ -121,7 +121,7 @@ def _python_to_stub_names(names, fallback_to_python=False): for name in name_list[:-1]: stubs = stubs.py__getattribute__(name) if stubs and name_list: - new_names = stubs.py__getattribute__(name_list[-1], is_goto=True) + new_names = stubs.goto(name_list[-1]) for new_name in new_names: yield new_name if new_names: diff --git a/jedi/inference/param.py b/jedi/inference/param.py index e2703103..6749d9e0 100644 --- a/jedi/inference/param.py +++ b/jedi/inference/param.py @@ -89,7 +89,7 @@ def get_executed_params_and_issues(execution_context, arguments): # Default params are part of the value where the function was defined. # This means that they might have access on class variables that the # function itself doesn't have. - default_param_value = execution_context.function_value.get_default_param_value() + default_param_context = execution_context.function_value.get_default_param_context() for param in funcdef.get_params(): param_dict[param.name.value] = param @@ -172,7 +172,7 @@ def get_executed_params_and_issues(execution_context, arguments): ) ) else: - result_arg = LazyTreeValue(default_param_value, param.default) + result_arg = LazyTreeValue(default_param_context, param.default) is_default = True else: result_arg = argument diff --git a/jedi/inference/value/function.py b/jedi/inference/value/function.py index f5a9a23a..3b8dae01 100644 --- a/jedi/inference/value/function.py +++ b/jedi/inference/value/function.py @@ -93,6 +93,9 @@ class FunctionMixin(object): return FunctionExecutionContext(self, arguments) + def as_context(self): + return self.get_function_execution() + def get_signatures(self): return [TreeSignature(f) for f in self.get_signature_functions()] @@ -137,7 +140,7 @@ class FunctionValue(use_metaclass(CachedMetaClass, FunctionMixin, FunctionAndCla c, = values_from_qualified_names(self.inference_state, u'types', u'FunctionType') return c - def get_default_param_value(self): + def get_default_param_context(self): return self.parent_context def get_signature_functions(self): @@ -145,17 +148,17 @@ class FunctionValue(use_metaclass(CachedMetaClass, FunctionMixin, FunctionAndCla class MethodValue(FunctionValue): - def __init__(self, inference_state, class_value, *args, **kwargs): + def __init__(self, inference_state, class_context, *args, **kwargs): super(MethodValue, self).__init__(inference_state, *args, **kwargs) - self.class_value = class_value + self.class_context = class_context - def get_default_param_value(self): - return self.class_value + def get_default_param_context(self): + return self.class_context def get_qualified_names(self): # Need to implement this, because the parent value of a method # value is not the class value but the module. - names = self.class_value.get_qualified_names() + names = self.class_context.get_qualified_names() if names is None: return None return names + (self.py__name__(),) diff --git a/jedi/inference/value/klass.py b/jedi/inference/value/klass.py index 6f64909e..1be50f87 100644 --- a/jedi/inference/value/klass.py +++ b/jedi/inference/value/klass.py @@ -106,7 +106,7 @@ class ClassFilter(ParserTreeFilter): def _equals_origin_scope(self): node = self._origin_scope while node is not None: - if node == self._parser_scope or node == self.value: + if node == self._parser_scope or node == self.context: return True node = get_cached_parent_scope(self._used_names, node) return False diff --git a/jedi/plugins/stdlib.py b/jedi/plugins/stdlib.py index d92b518e..5e3fc310 100644 --- a/jedi/plugins/stdlib.py +++ b/jedi/plugins/stdlib.py @@ -158,7 +158,7 @@ def _follow_param(inference_state, arguments, index): return lazy_value.infer() -def argument_clinic(string, want_obj=False, want_value=False, +def argument_clinic(string, want_obj=False, want_context=False, want_arguments=False, want_inference_state=False, want_callback=False): """ @@ -174,8 +174,8 @@ def argument_clinic(string, want_obj=False, want_value=False, assert not kwargs # Python 2... debug.dbg('builtin start %s' % obj, color='MAGENTA') result = NO_VALUES - if want_value: - kwargs['value'] = arguments.value + if want_context: + kwargs['context'] = arguments.context if want_obj: kwargs['obj'] = obj if want_inference_state: @@ -268,11 +268,11 @@ class SuperInstance(LazyValueWrapper): yield f -@argument_clinic('[type[, obj]], /', want_value=True) -def builtins_super(types, objects, value): - if isinstance(value, FunctionExecutionContext): - if isinstance(value.var_args, InstanceArguments): - instance = value.var_args.instance +@argument_clinic('[type[, obj]], /', want_context=True) +def builtins_super(types, objects, context): + if isinstance(context, FunctionExecutionContext): + if isinstance(context.var_args, InstanceArguments): + instance = context.var_args.instance # TODO if a class is given it doesn't have to be the direct super # class, it can be an anecestor from long ago. return ValueSet({SuperInstance(instance.inference_state, instance)}) diff --git a/test/run.py b/test/run.py index 0c29fea3..8ceeb19f 100755 --- a/test/run.py +++ b/test/run.py @@ -231,9 +231,7 @@ class IntegrationTestCase(object): #if user_context._value.api_type == 'function': # user_context = user_context.get_function_execution() node.parent = user_context.tree_node - results = convert_values( - user_context.infer_node(node), - ) + results = convert_values(user_context.infer_node(node)) if not results: raise Exception('Could not resolve %s on line %s' % (match.string, self.line_nr - 1))