diff --git a/jedi/evaluate/context.py b/jedi/evaluate/context.py index 0364c34e..2dc129f4 100644 --- a/jedi/evaluate/context.py +++ b/jedi/evaluate/context.py @@ -52,7 +52,7 @@ class AbstractLazyContext(object): class LazyKnownContext(AbstractLazyContext): """data is a context.""" def infer(self): - return set([self._data]) + yield self._data class LazyKnownContexts(AbstractLazyContext): diff --git a/jedi/evaluate/instance.py b/jedi/evaluate/instance.py index 88e2064c..097de2b0 100644 --- a/jedi/evaluate/instance.py +++ b/jedi/evaluate/instance.py @@ -160,16 +160,16 @@ class TreeInstance(AbstractInstanceContext): parent_context = self.create_instance_context(class_context, scope) if scope.type == 'funcdef': if scope.name.value == '__init__' and parent_context == self: - return er.FunctionExecutionContext( - self.evaluator, - self.parent_context, + return InstanceFunctionExecution( + self, + class_context.parent_context, scope, self.var_args ) else: return er.AnonymousFunctionExecution( self.evaluator, - self.parent_context, + class_context.parent_context, scope, ) else: @@ -193,26 +193,29 @@ class CompiledInstanceClassFilter(compiled.CompiledObjectFilter): class BoundMethod(object): - def __init__(self, function): + def __init__(self, instance, class_context, function): + self._instance = instance + self._class_context = class_context self._function = function def __getattr__(self, name): return getattr(self._function, name) + def py__call__(self, var_args): + function_execution = InstanceFunctionExecution( + self._instance, + self._class_context.parent_context, + self._function.funcdef, + var_args + ) + return self._function.infer_function_execution(function_execution) + class InstanceNameDefinition(TreeNameDefinition): - @to_list def infer(self): contexts = super(InstanceNameDefinition, self).infer() - from jedi.evaluate.representation import FunctionContext for context in contexts: - """ - if isinstance(contexts, FunctionContext): - # TODO what about compiled objects? - yield BoundMethod(context) - else: - """ - yield context + yield context class InstanceClassFilter(ParserTreeFilter): name_class = InstanceNameDefinition @@ -287,3 +290,30 @@ class LazyInstanceName(TreeNameDefinition): @property def parent_context(self): return self._instance.create_instance_context(self._class_context, self.name) + + def infer(self): + values = super(LazyInstanceName, self).infer() + for v in values: + if isinstance(v, er.FunctionContext): + yield BoundMethod(self._instance, self._class_context, v) + else: + yield v + + +class InstanceVarArgs(object): + def __init__(self, instance, var_args): + self._instance = instance + self._var_args = var_args + + def unpack(self, func=None): + yield None, self._instance + for values in self._var_args.unpack(func): + yield values + + +class InstanceFunctionExecution(er.FunctionExecutionContext): + def __init__(self, instance, parent_context, funcdef, var_args): + var_args = InstanceVarArgs(instance, var_args) + + super(InstanceFunctionExecution, self).__init__( + instance.evaluator, parent_context, funcdef, var_args) diff --git a/jedi/evaluate/param.py b/jedi/evaluate/param.py index b965cfda..0f32e4ee 100644 --- a/jedi/evaluate/param.py +++ b/jedi/evaluate/param.py @@ -244,10 +244,6 @@ def get_params(evaluator, parent_context, func, var_args): for param in func.params: param_dict[str(param.name)] = param unpacked_va = list(var_args.unpack(func)) - from jedi.evaluate.instance import TreeInstance - if isinstance(parent_context, TreeInstance): - # Include the self parameter here. - unpacked_va.insert(0, (None, context.LazyKnownContext(parent_context))) var_arg_iterator = common.PushBackIterator(iter(unpacked_va)) non_matching_keys = defaultdict(lambda: []) diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index bec9ad32..d2e7a397 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -541,6 +541,15 @@ class FunctionContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrappe for filter in scope.get_filters(search_global=False, origin_scope=origin_scope): yield filter + def infer_function_execution(self, function_execution): + """ + Created to be used by inheritance. + """ + if self.base.is_generator(): + return set([iterable.Generator(self.evaluator, function_execution)]) + else: + return function_execution.get_return_values() + @Python3Method def py__call__(self, params): function_execution = FunctionExecutionContext( @@ -549,10 +558,7 @@ class FunctionContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrappe self.base, params ) - if self.base.is_generator(): - return set([iterable.Generator(self.evaluator, function_execution)]) - else: - return function_execution.get_return_values() + return self.execute_function_(function_execution) def py__class__(self): # This differentiation is only necessary for Python2. Python3 does not