1
0
forked from VimPlug/jedi

Introduce get_qualified_names for names, it's easier to implement goto like this

This commit is contained in:
Dave Halter
2019-05-10 01:07:21 +02:00
parent f8f858216f
commit be6760e427
5 changed files with 59 additions and 18 deletions

View File

@@ -38,7 +38,6 @@ from jedi.evaluate.syntax_tree import tree_name_to_contexts
from jedi.evaluate.context import ModuleContext from jedi.evaluate.context import ModuleContext
from jedi.evaluate.base_context import ContextSet from jedi.evaluate.base_context import ContextSet
from jedi.evaluate.context.iterable import unpack_tuple_to_dict from jedi.evaluate.context.iterable import unpack_tuple_to_dict
#from jedi.evaluate.gradual.typeshed import try_to_merge_with_stub
from jedi.evaluate.gradual.stub_context import try_stubs_to_actual_context_set, \ from jedi.evaluate.gradual.stub_context import try_stubs_to_actual_context_set, \
try_stub_to_actual_names try_stub_to_actual_names
from jedi.evaluate.gradual.utils import load_proper_stub_module from jedi.evaluate.gradual.utils import load_proper_stub_module

View File

@@ -324,12 +324,8 @@ class BaseDefinition(object):
] ]
def goto_assignments(self): def goto_assignments(self):
if self._name.tree_name is None: return [self if n == self._name else Definition(self._evaluator, n)
return self for n in self._name.goto()]
names = self._name.goto()
names = try_stub_to_actual_names(names, prefer_stub_to_compiled=True)
return [Definition(self._evaluator, n) for n in names]
def infer(self): def infer(self):
tree_name = self._name.tree_name tree_name = self._name.tree_name

View File

@@ -85,7 +85,8 @@ 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.stub_context import \ from jedi.evaluate.gradual.stub_context import \
stub_to_actual_context_set, goto_with_stubs_if_possible, goto_non_stub stub_to_actual_context_set, goto_with_stubs_if_possible, \
try_stub_to_actual_names
def _execute(context, arguments): def _execute(context, arguments):
@@ -322,6 +323,11 @@ 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
@@ -334,11 +340,8 @@ class Evaluator(object):
elif type_ == 'param': elif type_ == 'param':
return [ParamName(context, name)] return [ParamName(context, name)]
elif type_ in ('funcdef', 'classdef'): elif type_ in ('funcdef', 'classdef'):
if context.is_stub(): n = TreeNameDefinition(context, name)
return goto_non_stub(context, name) return goto_with_stubs_if_possible(n)
else:
n = TreeNameDefinition(context, name)
return goto_with_stubs_if_possible(n)
elif type_ in ('import_from', 'import_name'): elif type_ in ('import_from', 'import_name'):
module_names = imports.infer_import(context, name, is_goto=True) module_names = imports.infer_import(context, name, is_goto=True)
return module_names return module_names

View File

@@ -113,17 +113,16 @@ def goto_with_stubs_if_possible(name):
] or [name] ] or [name]
def goto_non_stub(parent_context, tree_name):
contexts = stub_to_actual_context_set(parent_context)
return contexts.py__getattribute__(tree_name, is_goto=True)
def stub_to_actual_context_set(stub_context, ignore_compiled=False): def stub_to_actual_context_set(stub_context, ignore_compiled=False):
stub_module = stub_context.get_root_context() stub_module = stub_context.get_root_context()
if not stub_module.is_stub(): if not stub_module.is_stub():
return ContextSet([stub_context]) return ContextSet([stub_context])
qualified_names = stub_context.get_qualified_names() qualified_names = stub_context.get_qualified_names()
return _infer_from_stub(stub_module, qualified_names, ignore_compiled)
def _infer_from_stub(stub_module, qualified_names, ignore_compiled):
if qualified_names is None: if qualified_names is None:
return NO_CONTEXTS return NO_CONTEXTS
@@ -147,6 +146,30 @@ def try_stubs_to_actual_context_set(stub_contexts, prefer_stub_to_compiled=False
@to_list @to_list
def try_stub_to_actual_names(names, prefer_stub_to_compiled=False): def try_stub_to_actual_names(names, prefer_stub_to_compiled=False):
for name in names: for name in names:
module = name.get_root_context()
if not module.is_stub():
yield name
continue
name_list = name.get_qualified_names()
if name_list is None:
contexts = NO_CONTEXTS
else:
contexts = _infer_from_stub(
module,
name_list[:-1],
ignore_compiled=prefer_stub_to_compiled,
)
if contexts:
if name_list:
for new_name in contexts.py__getattribute__(name_list[-1], is_goto=True):
yield new_name
else:
for c in contexts:
yield c.name
else:
yield name
continue # XXX
# Using the tree_name is better, if it's available, becuase no # Using the tree_name is better, if it's available, becuase no
# information is lost. If the name given is defineda as `foo: int` we # information is lost. If the name given is defineda as `foo: int` we
# would otherwise land on int, which is not what we want. We want foo # would otherwise land on int, which is not what we want. We want foo

View File

@@ -23,6 +23,10 @@ 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):
raise NotImplementedError
def get_root_context(self): def get_root_context(self):
return self.parent_context.get_root_context() return self.parent_context.get_root_context()
@@ -44,6 +48,12 @@ class AbstractTreeName(AbstractNameDefinition):
self.parent_context = parent_context self.parent_context = parent_context
self.tree_name = tree_name self.tree_name = tree_name
def get_qualified_names(self):
parent_names = self.parent_context.get_qualified_names()
if parent_names is None:
return None
return parent_names + [self.tree_name.value]
def goto(self): def goto(self):
return self.parent_context.evaluator.goto(self.parent_context, self.tree_name) return self.parent_context.evaluator.goto(self.parent_context, self.tree_name)
@@ -64,6 +74,9 @@ class ContextNameMixin(object):
def infer(self): def infer(self):
return ContextSet([self._context]) return ContextSet([self._context])
def get_qualified_names(self):
return self._context.get_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
return self._context return self._context
@@ -79,6 +92,10 @@ class ContextName(ContextNameMixin, AbstractTreeName):
super(ContextName, self).__init__(context.parent_context, tree_name) super(ContextName, self).__init__(context.parent_context, tree_name)
self._context = context self._context = context
def goto(self):
from jedi.evaluate.gradual.stub_context import try_stub_to_actual_names
return try_stub_to_actual_names([self._context.name])
class TreeNameDefinition(AbstractTreeName): class TreeNameDefinition(AbstractTreeName):
_API_TYPES = dict( _API_TYPES = dict(
@@ -143,6 +160,9 @@ class ImportName(AbstractNameDefinition):
self._from_module_context = parent_context self._from_module_context = parent_context
self.string_name = string_name self.string_name = string_name
def get_qualified_names(self):
return []
@property @property
def parent_context(self): def parent_context(self):
m = self._from_module_context m = self._from_module_context