1
0
forked from VimPlug/jedi

Use a different function signature instead of a separate goto_stubs function

This commit is contained in:
Dave Halter
2019-06-10 02:27:22 +02:00
parent 827a79861d
commit a555def6ca
7 changed files with 86 additions and 53 deletions

View File

@@ -9,6 +9,7 @@ import warnings
from parso.python.tree import search_ancestor from parso.python.tree import search_ancestor
from jedi import settings from jedi import settings
from jedi import debug
from jedi.evaluate.utils import unite from jedi.evaluate.utils import unite
from jedi.cache import memoize_method from jedi.cache import memoize_method
from jedi.evaluate import imports from jedi.evaluate import imports
@@ -16,8 +17,8 @@ from jedi.evaluate import compiled
from jedi.evaluate.imports import ImportName from jedi.evaluate.imports import ImportName
from jedi.evaluate.context import FunctionExecutionContext from jedi.evaluate.context import FunctionExecutionContext
from jedi.evaluate.gradual.typeshed import StubModuleContext from jedi.evaluate.gradual.typeshed import StubModuleContext
from jedi.evaluate.gradual.conversion import name_to_stub, \ from jedi.evaluate.gradual.conversion import try_stub_to_actual_names, \
stub_to_actual_context_set, try_stubs_to_actual_context_set stub_to_actual_context_set, try_stubs_to_actual_context_set, actual_to_stub_names
from jedi.api.keywords import KeywordName from jedi.api.keywords import KeywordName
@@ -280,26 +281,30 @@ class BaseDefinition(object):
return False return False
return all(c.is_stub() for c in self._name.infer()) return all(c.is_stub() for c in self._name.infer())
def goto_stubs(self): def goto_assignments(self, **kwargs): # Python 2...
return self._goto_assignments(**kwargs)
def _goto_assignments(self, only_stubs=False, prefer_stubs=False):
assert not (only_stubs and prefer_stubs)
if not self._name.is_context_name: if not self._name.is_context_name:
return [] return []
if self.is_stub(): names = self._name.goto()
return [self] if only_stubs or prefer_stubs:
names = actual_to_stub_names(names, fallback_to_actual=prefer_stubs)
return [ else:
Definition(self._evaluator, stub_def.name) names = try_stub_to_actual_names(names, prefer_stub_to_compiled=True)
for stub_def in name_to_stub(self._name)
]
def goto_assignments(self):
if not self._name.is_context_name:
return []
return [self if n == self._name else Definition(self._evaluator, n) return [self if n == self._name else Definition(self._evaluator, n)
for n in self._name.goto()] for n in names]
def infer(self, **kwargs): # Python 2...
return self._infer(**kwargs)
def _infer(self, only_stubs=False, prefer_stubs=False):
assert not (only_stubs and prefer_stubs)
def infer(self):
if not self._name.is_context_name: if not self._name.is_context_name:
return [] return []

View File

@@ -85,7 +85,7 @@ from jedi.evaluate.context.iterable import CompForContext
from jedi.evaluate.syntax_tree import eval_trailer, eval_expr_stmt, \ from jedi.evaluate.syntax_tree import eval_trailer, eval_expr_stmt, \
eval_node, check_tuple_assignments eval_node, check_tuple_assignments
from jedi.evaluate.gradual.conversion import try_stub_to_actual_names, \ from jedi.evaluate.gradual.conversion import try_stub_to_actual_names, \
try_stubs_to_actual_context_set actual_to_stub_names, try_stubs_to_actual_context_set
def _execute(context, arguments): def _execute(context, arguments):
@@ -322,11 +322,6 @@ class Evaluator(object):
return None return None
def goto(self, context, name): def goto(self, context, name):
names = self._goto(context, name)
names = try_stub_to_actual_names(names, prefer_stub_to_compiled=True)
return names
def _goto(self, context, name):
definition = name.get_definition(import_name_always=True) definition = name.get_definition(import_name_always=True)
if definition is not None: if definition is not None:
type_ = definition.type type_ = definition.type

View File

@@ -263,6 +263,10 @@ class CompiledName(AbstractNameDefinition):
self.parent_context = parent_context self.parent_context = parent_context
self.string_name = name self.string_name = name
def _get_qualified_names(self):
parent_qualified_names = self.parent_context.get_qualified_names()
return parent_qualified_names + (self.string_name,)
def __repr__(self): def __repr__(self):
try: try:
name = self.parent_context.name # __name__ is not defined all the time name = self.parent_context.name # __name__ is not defined all the time

View File

@@ -104,8 +104,36 @@ def _load_stub_module(module):
) )
def name_to_stub(name): @to_list
return ContextSet.from_sets(to_stub(c) for c in name.infer()) def actual_to_stub_names(names, fallback_to_actual=False):
for name in names:
module = name.get_root_context()
if module.is_stub():
yield name
continue
name_list = name.get_qualified_names()
stubs = NO_CONTEXTS
if name_list is not None:
stub_module = _load_stub_module(module)
if stub_module is not None:
stubs = ContextSet({stub_module})
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)
for new_name in new_names:
yield new_name
if new_names:
continue
elif stubs:
for c in stubs:
yield c.name
continue
if fallback_to_actual:
# This is the part where if we haven't found anything, just return
# the stub name.
yield name
def to_stub(context): def to_stub(context):

View File

@@ -27,8 +27,18 @@ class AbstractNameDefinition(object):
# name will always result on itself. # name will always result on itself.
return {self} return {self}
@abstractmethod
def get_qualified_names(self, include_module_names=False): def get_qualified_names(self, include_module_names=False):
qualified_names = self._get_qualified_names()
if qualified_names is None or not include_module_names:
return qualified_names
module_names = self.get_root_context().string_names
if module_names is None:
return None
return module_names + qualified_names
@abstractmethod
def _get_qualified_names(self):
raise NotImplementedError raise NotImplementedError
def get_root_context(self): def get_root_context(self):
@@ -56,21 +66,20 @@ class AbstractTreeName(AbstractNameDefinition):
def get_qualified_names(self, include_module_names=False): def get_qualified_names(self, include_module_names=False):
import_node = search_ancestor(self.tree_name, 'import_name', 'import_from') import_node = search_ancestor(self.tree_name, 'import_name', 'import_from')
if import_node is not None: if import_node is not None:
return tuple(n.value for n in import_node.get_path_for_name(self.tree_name)) if include_module_names:
return tuple(n.value for n in import_node.get_path_for_name(self.tree_name))
else:
return ()
return super(AbstractTreeName, self).get_qualified_names(include_module_names)
def _get_qualified_names(self):
parent_names = self.parent_context.get_qualified_names() parent_names = self.parent_context.get_qualified_names()
if parent_names is None: if parent_names is None:
return None return None
parent_names += (self.tree_name.value,) return parent_names + (self.tree_name.value,)
if include_module_names:
module_names = self.get_root_context().string_names
if module_names is None:
return None
return module_names + parent_names
return parent_names
def goto(self): def goto(self, **kwargs):
return self.parent_context.evaluator.goto(self.parent_context, self.tree_name) return self.parent_context.evaluator.goto(self.parent_context, self.tree_name, **kwargs)
def is_import(self): def is_import(self):
imp = search_ancestor(self.tree_name, 'import_from', 'import_name') imp = search_ancestor(self.tree_name, 'import_from', 'import_name')
@@ -89,15 +98,8 @@ class ContextNameMixin(object):
def infer(self): def infer(self):
return ContextSet([self._context]) return ContextSet([self._context])
def get_qualified_names(self, include_module_names=False): def _get_qualified_names(self):
qualified_names = self._context.get_qualified_names() return self._context.get_qualified_names()
if qualified_names is None or not include_module_names:
return qualified_names
module_names = self.get_root_context().string_names
if module_names is None:
return None
return module_names + qualified_names
def get_root_context(self): def get_root_context(self):
if self.parent_context is None: # A module if self.parent_context is None: # A module
@@ -115,8 +117,7 @@ class ContextName(ContextNameMixin, AbstractTreeName):
self._context = context self._context = context
def goto(self): def goto(self):
from jedi.evaluate.gradual.conversion import try_stub_to_actual_names return ContextSet([self._context.name])
return try_stub_to_actual_names([self._context.name])
class TreeNameDefinition(AbstractTreeName): class TreeNameDefinition(AbstractTreeName):

View File

@@ -35,7 +35,7 @@ def test_keyword_attributes(Script):
assert def_.complete == '' assert def_.complete == ''
assert def_.is_keyword is True assert def_.is_keyword is True
assert def_.is_stub() is False assert def_.is_stub() is False
assert def_.goto_stubs() == [] assert def_.goto_assignments(only_stubs=True) == []
assert def_.goto_assignments() == [] assert def_.goto_assignments() == []
assert def_.infer() == [] assert def_.infer() == []
assert def_.parent() is None assert def_.parent() is None

View File

@@ -63,7 +63,7 @@ def test_keywords_variable(Script):
for seq in Script(code).goto_definitions(): for seq in Script(code).goto_definitions():
assert seq.name == 'Sequence' assert seq.name == 'Sequence'
# This points towards the typeshed implementation # This points towards the typeshed implementation
stub_seq, = seq.goto_stubs() stub_seq, = seq.goto_assignments(only_stubs=True)
assert typeshed.TYPESHED_PATH in stub_seq.module_path assert typeshed.TYPESHED_PATH in stub_seq.module_path
@@ -156,12 +156,12 @@ def test_math_is_stub(Script, code, full_name):
wanted = os.path.join('typeshed', 'stdlib', '2and3', 'math.pyi') wanted = os.path.join('typeshed', 'stdlib', '2and3', 'math.pyi')
assert cos.module_path.endswith(wanted) assert cos.module_path.endswith(wanted)
assert cos.is_stub() is True assert cos.is_stub() is True
assert cos.goto_stubs() == [cos] assert cos.goto_assignments(only_stubs=True) == [cos]
assert cos.full_name == full_name assert cos.full_name == full_name
cos, = s.goto_assignments() cos, = s.goto_assignments()
assert cos.module_path.endswith(wanted) assert cos.module_path.endswith(wanted)
assert cos.goto_stubs() == [cos] assert cos.goto_assignments(only_stubs=True) == [cos]
assert cos.is_stub() is True assert cos.is_stub() is True
assert cos.full_name == full_name assert cos.full_name == full_name
@@ -171,7 +171,7 @@ def test_goto_stubs(Script):
os_module, = s.goto_definitions() os_module, = s.goto_definitions()
assert os_module.full_name == 'os' assert os_module.full_name == 'os'
assert os_module.is_stub() is False assert os_module.is_stub() is False
stub, = os_module.goto_stubs() stub, = os_module.goto_assignments(only_stubs=True)
assert stub.is_stub() is True assert stub.is_stub() is True
os_module, = s.goto_assignments() os_module, = s.goto_assignments()
@@ -202,7 +202,7 @@ def test_goto_stubs_on_itself(Script, code, type_):
def_, = s.goto_definitions() def_, = s.goto_definitions()
else: else:
def_, = s.goto_assignments(follow_imports=True) def_, = s.goto_assignments(follow_imports=True)
stub, = def_.goto_stubs() stub, = def_.goto_assignments(only_stubs=True)
script_on_source = Script( script_on_source = Script(
path=def_.module_path, path=def_.module_path,
@@ -213,7 +213,7 @@ def test_goto_stubs_on_itself(Script, code, type_):
definition, = script_on_source.goto_definitions() definition, = script_on_source.goto_definitions()
else: else:
definition, = script_on_source.goto_assignments() definition, = script_on_source.goto_assignments()
same_stub, = definition.goto_stubs() same_stub, = definition.goto_assignments(only_stubs=True)
_assert_is_same(same_stub, stub) _assert_is_same(same_stub, stub)
_assert_is_same(definition, def_) _assert_is_same(definition, def_)
assert same_stub.module_path != def_.module_path assert same_stub.module_path != def_.module_path