diff --git a/jedi/evaluate/arguments.py b/jedi/evaluate/arguments.py index 075ce50a..d0a06224 100644 --- a/jedi/evaluate/arguments.py +++ b/jedi/evaluate/arguments.py @@ -64,7 +64,7 @@ class AbstractArguments(object): try_iter_content(types) def get_calling_nodes(self): - raise NotImplementedError + return [] def unpack(self, funcdef=None): raise NotImplementedError @@ -218,9 +218,6 @@ class ValuesArguments(AbstractArguments): for values in self._values_list: yield None, LazyKnownContexts(values) - def get_calling_nodes(self): - return [] - def __repr__(self): return '<%s: %s>' % (self.__class__.__name__, self._values_list) diff --git a/jedi/evaluate/context/function.py b/jedi/evaluate/context/function.py index c982f055..cfd10ab4 100644 --- a/jedi/evaluate/context/function.py +++ b/jedi/evaluate/context/function.py @@ -94,6 +94,9 @@ class AbstractFunction(TreeContext): else: return function_execution.get_return_values() + def py__name__(self): + return self.name.string_name + class FunctionContext(use_metaclass(CachedMetaClass, AbstractFunction)): """ diff --git a/jedi/evaluate/context/instance.py b/jedi/evaluate/context/instance.py index dc2c0f52..b5fa0970 100644 --- a/jedi/evaluate/context/instance.py +++ b/jedi/evaluate/context/instance.py @@ -1,7 +1,5 @@ from abc import abstractproperty -from parso.tree import search_ancestor - from jedi import debug from jedi import settings from jedi.evaluate import compiled @@ -13,36 +11,32 @@ from jedi.evaluate.cache import evaluator_method_cache from jedi.evaluate.arguments import AbstractArguments, AnonymousArguments from jedi.evaluate.context.function import FunctionExecutionContext, \ FunctionContext, AbstractFunction -from jedi.evaluate.filters import FunctionExecutionFilter, ParamName from jedi.evaluate.context.klass import ClassContext, apply_py__get__, ClassFilter from jedi.evaluate.context import iterable from jedi.parser_utils import get_parent_scope -class _AnonymousInstanceParamName(ParamName): +class InstanceExecutedParam(object): + def __init__(self, instance): + self._instance = instance + def infer(self): - param_node = search_ancestor(self.tree_name, 'param') - # TODO I think this should not belong here. It's not even really true, - # because classmethod and other descriptors can change it. - if param_node.position_index == 0: - # This is a speed optimization, to return the self param (because - # it's known). This only affects anonymous instances. - return ContextSet(self.parent_context.instance) - else: - return self.get_param().infer() + return ContextSet(self._instance) -class _AnonymousInstanceFunctionExecutionFilter(FunctionExecutionFilter): - param_name = _AnonymousInstanceParamName +class AnonymousInstanceArguments(AnonymousArguments): + def __init__(self, instance): + self._instance = instance - -class AnonymousInstanceFunctionExecution(FunctionExecutionContext): - function_execution_filter = _AnonymousInstanceFunctionExecutionFilter - - def __init__(self, instance, *args, **kwargs): - self.instance = instance - super(AnonymousInstanceFunctionExecution, self).__init__( - instance.evaluator, *args, **kwargs) + def get_executed_params(self, execution_context): + from jedi.evaluate.dynamic import search_params + executed_params = list(search_params( + execution_context.evaluator, + execution_context, + execution_context.tree_node + )) + executed_params[0] = InstanceExecutedParam(self._instance) + return executed_params class AbstractInstanceContext(Context): @@ -260,15 +254,7 @@ class AnonymousInstance(TreeInstance): evaluator, parent_context, class_context, - var_args=AnonymousArguments(), - ) - - def _create_init_execution(self, class_context, bound_method): - return AnonymousInstanceFunctionExecution( - self, - class_context.parent_context, - bound_method, - self.var_args + var_args=AnonymousInstanceArguments(self), ) @@ -335,16 +321,14 @@ class BoundMethod(AbstractFunction): def get_function_execution(self, arguments=None): if arguments is None: - arguments = AnonymousArguments() - return AnonymousInstanceFunctionExecution( - self._instance, self.parent_context, self, arguments) - else: - return FunctionExecutionContext( - self.evaluator, - self.parent_context, - self, - InstanceArguments(self._instance, arguments) - ) + arguments = AnonymousInstanceArguments(self._instance) + + return FunctionExecutionContext( + self.evaluator, + self.parent_context, + self, + InstanceArguments(self._instance, arguments) + ) def __repr__(self): return '<%s: %s>' % (self.__class__.__name__, self._function) @@ -481,3 +465,9 @@ class InstanceArguments(AbstractArguments): def get_calling_nodes(self): return self._var_args.get_calling_nodes() + + def get_executed_params(self, execution_context): + if isinstance(self._var_args, AnonymousInstanceArguments): + return self._var_args.get_executed_params(execution_context) + + return super(InstanceArguments, self).get_executed_params(execution_context) diff --git a/jedi/evaluate/docstrings.py b/jedi/evaluate/docstrings.py index 6fac8b9f..aaef8ea8 100644 --- a/jedi/evaluate/docstrings.py +++ b/jedi/evaluate/docstrings.py @@ -266,7 +266,8 @@ def _execute_array_values(evaluator, array): @evaluator_method_cache() def infer_param(execution_context, param): - from jedi.evaluate.context.instance import AnonymousInstanceFunctionExecution + from jedi.evaluate.context.instance import InstanceArguments + from jedi.evaluate.context import FunctionExecutionContext def eval_docstring(docstring): return ContextSet.from_iterable( @@ -280,9 +281,10 @@ def infer_param(execution_context, param): return NO_CONTEXTS types = eval_docstring(execution_context.py__doc__()) - if isinstance(execution_context, AnonymousInstanceFunctionExecution) and \ - execution_context.function_context.name.string_name == '__init__': - class_context = execution_context.instance.class_context + if isinstance(execution_context, FunctionExecutionContext) \ + and isinstance(execution_context.var_args, InstanceArguments) \ + and execution_context.function_context.py__name__() == '__init__': + class_context = execution_context.var_args.instance.class_context types |= eval_docstring(class_context.py__doc__()) return types diff --git a/jedi/evaluate/stdlib.py b/jedi/evaluate/stdlib.py index 93977189..3ca38322 100644 --- a/jedi/evaluate/stdlib.py +++ b/jedi/evaluate/stdlib.py @@ -19,8 +19,7 @@ from jedi.evaluate.arguments import ValuesArguments from jedi.evaluate import analysis from jedi.evaluate import compiled from jedi.evaluate.context.instance import \ - AbstractInstanceContext, CompiledInstance, BoundMethod, \ - AnonymousInstanceFunctionExecution, InstanceArguments + AbstractInstanceContext, CompiledInstance, BoundMethod, InstanceArguments from jedi.evaluate.base_context import ContextualizedNode, \ NO_CONTEXTS, ContextSet from jedi.evaluate.context import ClassContext, ModuleContext, FunctionExecutionContext @@ -192,10 +191,6 @@ def builtins_super(evaluator, types, objects, context): su = context.var_args.instance.py__class__().py__bases__() return su[0].infer().execute_evaluated() - if isinstance(context, AnonymousInstanceFunctionExecution): - su = context.instance.py__class__().py__bases__() - return su[0].infer().execute_evaluated() - return NO_CONTEXTS