1
0
forked from VimPlug/jedi

Add only_stubs and prefer_stubs as parameters to goto_assignments/goto_definitions

This commit is contained in:
Dave Halter
2019-06-10 15:59:12 +02:00
parent 49f652a2ad
commit c8937ccdbf
6 changed files with 107 additions and 42 deletions

View File

@@ -39,7 +39,7 @@ from jedi.evaluate.syntax_tree import tree_name_to_contexts
from jedi.evaluate.context import ModuleContext
from jedi.evaluate.base_context import ContextSet
from jedi.evaluate.context.iterable import unpack_tuple_to_dict
from jedi.evaluate.gradual.conversion import try_stub_to_actual_names
from jedi.evaluate.gradual.conversion import convert_names
from jedi.evaluate.gradual.utils import load_proper_stub_module
# Jedi uses lots and lots of recursion. By setting this a little bit higher, we
@@ -235,7 +235,7 @@ class Script(object):
debug.speed('completions end')
return completions
def goto_definitions(self):
def goto_definitions(self, **kwargs):
"""
Return the definitions of a the path under the cursor. goto function!
This follows complicated paths and returns the end, not the first
@@ -245,8 +245,14 @@ class Script(object):
because Python itself is a dynamic language, which means depending on
an option you can have two different versions of a function.
:param only_stubs: Only return stubs for this goto call.
:param prefer_stubs: Prefer stubs to Python obects for this goto call.
:rtype: list of :class:`classes.Definition`
"""
with debug.increase_indent_cm('goto_definitions'):
return self._goto_definitions(**kwargs)
def _goto_definitions(self, only_stubs=False, prefer_stubs=False):
leaf = self._module_node.get_name_of_position(self._pos)
if leaf is None:
leaf = self._module_node.get_leaf_for_position(self._pos)
@@ -256,25 +262,40 @@ class Script(object):
context = self._evaluator.create_context(self._get_module(), leaf)
definitions = helpers.evaluate_goto_definition(self._evaluator, context, leaf)
names = [s.name for s in definitions]
names = convert_names(
[s.name for s in definitions],
only_stubs=only_stubs,
prefer_stubs=prefer_stubs,
)
defs = [classes.Definition(self._evaluator, name) for name in names]
# The additional set here allows the definitions to become unique in an
# API sense. In the internals we want to separate more things than in
# the API.
return helpers.sorted_definitions(set(defs))
def goto_assignments(self, follow_imports=False, follow_builtin_imports=False):
def goto_assignments(self, follow_imports=False, follow_builtin_imports=False, **kwargs):
"""
Return the first definition found, while optionally following imports.
Multiple objects may be returned, because Python itself is a
dynamic language, which means depending on an option you can have two
different versions of a function.
.. note:: It is deprecated to use follow_imports and follow_builtin_imports as
positional arguments. Will be a keyword argument in 0.16.0.
:param follow_imports: The goto call will follow imports.
:param follow_builtin_imports: If follow_imports is True will decide if
it follow builtin imports.
:param only_stubs: Only return stubs for this goto call.
:param prefer_stubs: Prefer stubs to Python obects for this goto call.
:rtype: list of :class:`classes.Definition`
"""
with debug.increase_indent_cm('goto_assignments'):
return self._goto_assignments(follow_imports, follow_builtin_imports, **kwargs)
def _goto_assignments(self, follow_imports, follow_builtin_imports,
only_stubs=False, prefer_stubs=False):
def filter_follow_imports(names, check):
for name in names:
if check(name):
@@ -297,13 +318,17 @@ class Script(object):
if tree_name is None:
# Without a name we really just want to jump to the result e.g.
# executed by `foo()`, if we the cursor is after `)`.
return self.goto_definitions()
return self.goto_definitions(only_stubs=only_stubs, prefer_stubs=prefer_stubs)
context = self._evaluator.create_context(self._get_module(), tree_name)
names = list(self._evaluator.goto(context, tree_name))
if follow_imports:
names = filter_follow_imports(names, lambda name: name.is_import())
names = try_stub_to_actual_names(names, prefer_stub_to_compiled=True)
names = convert_names(
names,
only_stubs=only_stubs,
prefer_stubs=prefer_stubs,
)
defs = [classes.Definition(self._evaluator, d) for d in set(names)]
return helpers.sorted_definitions(defs)

View File

@@ -17,8 +17,8 @@ from jedi.evaluate import compiled
from jedi.evaluate.imports import ImportName
from jedi.evaluate.context import FunctionExecutionContext
from jedi.evaluate.gradual.typeshed import StubModuleContext
from jedi.evaluate.gradual.conversion import try_stub_to_actual_names, \
stub_to_actual_context_set, try_stubs_to_actual_context_set, actual_to_stub_names
from jedi.evaluate.gradual.conversion import convert_names, \
stub_to_actual_context_set
from jedi.api.keywords import KeywordName
@@ -291,12 +291,11 @@ class BaseDefinition(object):
if not self._name.is_context_name:
return []
names = self._name.goto()
if only_stubs or prefer_stubs:
names = actual_to_stub_names(names, fallback_to_actual=prefer_stubs)
else:
names = try_stub_to_actual_names(names, prefer_stub_to_compiled=True)
names = convert_names(
self._name.goto(),
only_stubs=only_stubs,
prefer_stubs=prefer_stubs,
)
return [self if n == self._name else Definition(self._evaluator, n)
for n in names]
@@ -310,13 +309,13 @@ class BaseDefinition(object):
if not self._name.is_context_name:
return []
# Param names are special because they are not handled by
# the evaluator method.
context_set = try_stubs_to_actual_context_set(
self._name.infer(),
prefer_stub_to_compiled=True,
names = convert_names(
[c.name for c in self._name.infer()],
only_stubs=only_stubs,
prefer_stubs=prefer_stubs,
)
return [Definition(self._evaluator, d.name) for d in context_set]
return [self if n == self._name else Definition(self._evaluator, n)
for n in names]
@property
@memoize_method

View File

@@ -137,14 +137,11 @@ def get_stack_at_position(grammar, code_lines, module_node, pos):
)
def evaluate_goto_definition(evaluator, context, leaf, prefer_stubs=False):
def evaluate_goto_definition(evaluator, context, leaf):
if leaf.type == 'name':
# In case of a name we can just use goto_definition which does all the
# magic itself.
if prefer_stubs:
return evaluator.goto_stub_definitions(context, leaf)
else:
return evaluator.goto_definitions(context, leaf)
return evaluator.goto_definitions(context, leaf)
parent = leaf.parent
definitions = NO_CONTEXTS
@@ -156,13 +153,7 @@ def evaluate_goto_definition(evaluator, context, leaf, prefer_stubs=False):
return eval_atom(context, leaf)
elif leaf.type in ('fstring_string', 'fstring_start', 'fstring_end'):
return get_string_context_set(evaluator)
if prefer_stubs:
return definitions
from jedi.evaluate.gradual.conversion import try_stubs_to_actual_context_set
return try_stubs_to_actual_context_set(
definitions,
prefer_stub_to_compiled=True,
)
return definitions
CallSignatureDetails = namedtuple(
@@ -268,5 +259,4 @@ def cache_call_signatures(evaluator, context, bracket_leaf, code_lines, user_pos
evaluator,
context,
bracket_leaf.get_previous_leaf(),
prefer_stubs=True,
)