diff --git a/jedi/api/classes.py b/jedi/api/classes.py index 6440c24b..c5ade9f9 100644 --- a/jedi/api/classes.py +++ b/jedi/api/classes.py @@ -14,7 +14,7 @@ from jedi.evaluate import imports from jedi.evaluate import compiled from jedi.evaluate.imports import ImportName from jedi.evaluate.filters import ParamName -from jedi.evaluate.context import FunctionExecutionContext +from jedi.evaluate.context import FunctionExecutionContext, MethodContext from jedi.evaluate.gradual.typeshed import StubOnlyModuleContext from jedi.api.keywords import KeywordName @@ -318,7 +318,16 @@ class BaseDefinition(object): if self._name.tree_name is None: return self - names = self._evaluator.goto(self._name.parent_context, self._name.tree_name) + # TODO remove this paragraph, it's ugly and shouldn't be needed + inferred = self._name.infer() + if not inferred: + return None + inferred = next(iter(inferred)) + if isinstance(inferred, MethodContext): + c = inferred.class_context + else: + c = self._name.parent_context + names = self._evaluator.goto(c, self._name.tree_name) return [Definition(self._evaluator, n) for n in names] def infer(self): diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index fcc29cfa..e402a8aa 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -85,7 +85,8 @@ from jedi.evaluate.context.iterable import CompForContext from jedi.evaluate.syntax_tree import eval_trailer, eval_expr_stmt, \ eval_node, check_tuple_assignments from jedi.evaluate.gradual.stub_context import with_stub_context_if_possible, \ - stub_to_actual_context_set, goto_with_stubs_if_possible, goto_non_stub + stub_to_actual_context_set, goto_with_stubs_if_possible, goto_non_stub, \ + stubify def _execute(context, arguments): @@ -443,6 +444,7 @@ class Evaluator(object): cls = FunctionContext func = cls.from_context(parent_context, scope_node) + func = next(iter(stubify(func))) if parent_was_class: func = BoundMethod( @@ -453,7 +455,10 @@ class Evaluator(object): return func.get_function_execution() return func elif scope_node.type == 'classdef': - return ClassContext(self, parent_context, scope_node) + return next(iter(stubify( + parent_context, + ClassContext(self, parent_context, scope_node) + ))) elif scope_node.type == 'comp_for': if node.start_pos >= scope_node.children[-1].start_pos: return parent_context diff --git a/jedi/evaluate/gradual/stub_context.py b/jedi/evaluate/gradual/stub_context.py index 5a5201ae..f73eefbe 100644 --- a/jedi/evaluate/gradual/stub_context.py +++ b/jedi/evaluate/gradual/stub_context.py @@ -315,12 +315,23 @@ def stub_to_actual_context_set(stub_context): stub_only_module = stub_context.get_root_context() assert isinstance(stub_only_module, StubOnlyModuleContext), stub_only_module - non_stubs = stub_only_module.non_stub_context_set + non_stubs = stub_only_module.get_stub_contexts() for name in qualified_names: non_stubs = non_stubs.py__getattribute__(name) return non_stubs +def stubify(parent_context, context): + if parent_context.is_stub(): + return ContextSet( + c.stub_context + for c in stub_to_actual_context_set(context) + if c.stub_context is not None + ) or ContextSet([context]) + else: + return with_stub_context_if_possible(context) + + class CompiledStubName(NameWrapper): def __init__(self, parent_context, compiled_name, stub_name): super(CompiledStubName, self).__init__(stub_name) diff --git a/test/test_evaluate/test_gradual/test_typeshed.py b/test/test_evaluate/test_gradual/test_typeshed.py index 58700598..76b816f4 100644 --- a/test/test_evaluate/test_gradual/test_typeshed.py +++ b/test/test_evaluate/test_gradual/test_typeshed.py @@ -197,7 +197,7 @@ def _assert_is_same(d1, d2): 'code', [ 'import os; os.walk', 'from collections import Counter; Counter', - #'from collections import Counter; Counter.most_common', + 'from collections import Counter; Counter.most_common', ]) def test_goto_stubs_on_itself(Script, code, type_): """