forked from VimPlug/jedi
Better goto for imports, which helps usages.
This commit is contained in:
@@ -503,7 +503,7 @@ class Script(object):
|
|||||||
import_name = user_stmt.get_defined_names()
|
import_name = user_stmt.get_defined_names()
|
||||||
# imports have only one name
|
# imports have only one name
|
||||||
np = import_name[0]
|
np = import_name[0]
|
||||||
if not user_stmt.star and unicode(name_part) == unicode(np):
|
if not user_stmt.is_star_import() and unicode(name_part) == unicode(np):
|
||||||
definitions.append(np)
|
definitions.append(np)
|
||||||
else:
|
else:
|
||||||
# The Evaluator.goto function checks for definitions, but since we
|
# The Evaluator.goto function checks for definitions, but since we
|
||||||
@@ -549,12 +549,7 @@ class Script(object):
|
|||||||
names = usages.usages(self._evaluator, definitions, module)
|
names = usages.usages(self._evaluator, definitions, module)
|
||||||
|
|
||||||
for d in set(definitions):
|
for d in set(definitions):
|
||||||
try:
|
names.append(classes.Definition(self._evaluator, d))
|
||||||
name_part = d.names[-1]
|
|
||||||
except AttributeError:
|
|
||||||
names.append(classes.Definition(self._evaluator, d))
|
|
||||||
else:
|
|
||||||
names.append(classes.Definition(self._evaluator, name_part))
|
|
||||||
finally:
|
finally:
|
||||||
settings.dynamic_flow_information = temp
|
settings.dynamic_flow_information = temp
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
from jedi._compatibility import u, unicode
|
from jedi._compatibility import u, unicode
|
||||||
from jedi import common
|
|
||||||
from jedi.api import classes
|
from jedi.api import classes
|
||||||
from jedi.parser import tree as pr
|
from jedi.parser import tree as pr
|
||||||
from jedi.evaluate import imports
|
from jedi.evaluate import imports
|
||||||
@@ -101,7 +100,6 @@ def usages_add_import_modules(evaluator, definitions):
|
|||||||
for d in definitions:
|
for d in definitions:
|
||||||
imp_or_stmt = d.get_definition()
|
imp_or_stmt = d.get_definition()
|
||||||
if isinstance(imp_or_stmt, pr.Import):
|
if isinstance(imp_or_stmt, pr.Import):
|
||||||
s = imports.ImportWrapper(evaluator, imp_or_stmt, nested_resolve=True)
|
s = imports.ImportWrapper(evaluator, d)
|
||||||
with common.ignored(IndexError):
|
new |= s.follow(is_goto=True)
|
||||||
new.add(s.follow(is_goto=True)[0])
|
|
||||||
return set(definitions) | new
|
return set(definitions) | new
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ from jedi.evaluate import finder
|
|||||||
from jedi.evaluate import compiled
|
from jedi.evaluate import compiled
|
||||||
from jedi.evaluate import precedence
|
from jedi.evaluate import precedence
|
||||||
from jedi.evaluate import param
|
from jedi.evaluate import param
|
||||||
|
from jedi.evaluate import helpers
|
||||||
from jedi.evaluate.helpers import FakeStatement, deep_ast_copy, call_of_name
|
from jedi.evaluate.helpers import FakeStatement, deep_ast_copy, call_of_name
|
||||||
|
|
||||||
|
|
||||||
@@ -455,21 +456,37 @@ class Evaluator(object):
|
|||||||
return self.eval_element(call)
|
return self.eval_element(call)
|
||||||
|
|
||||||
def goto(self, name):
|
def goto(self, name):
|
||||||
|
def resolve_implicit_imports(names):
|
||||||
|
for name in names:
|
||||||
|
if isinstance(name, helpers.FakeName):
|
||||||
|
# Those are implicit imports.
|
||||||
|
s = imports.ImportWrapper(self, name)
|
||||||
|
for n in s.follow(is_goto=True):
|
||||||
|
yield n
|
||||||
|
yield name
|
||||||
|
|
||||||
|
imp = name.get_definition()
|
||||||
stmt = name.parent
|
stmt = name.parent
|
||||||
if isinstance(stmt, pr.ExprStmt) and name in stmt.get_defined_names():
|
if isinstance(stmt, pr.ExprStmt) and name in stmt.get_defined_names():
|
||||||
|
# TODO remove? I think this is never called.
|
||||||
return [name]
|
return [name]
|
||||||
elif isinstance(stmt, (pr.Param, pr.Function, pr.Class)) and stmt.name is name:
|
elif isinstance(stmt, (pr.Param, pr.Function, pr.Class)) and stmt.name is name:
|
||||||
return [name]
|
return [name]
|
||||||
|
elif isinstance(imp, pr.Import):
|
||||||
|
return imports.ImportWrapper(self, name).follow(is_goto=True)
|
||||||
|
|
||||||
scope = name.get_parent_scope()
|
scope = name.get_parent_scope()
|
||||||
if pr.is_node(name.parent, 'trailer'):
|
if pr.is_node(name.parent, 'trailer'):
|
||||||
call = call_of_name(name, cut_own_trailer=True)
|
call = call_of_name(name, cut_own_trailer=True)
|
||||||
types = self.eval_element(call)
|
types = self.eval_element(call)
|
||||||
return iterable.unite(self.find_types(typ, name, is_goto=True)
|
return resolve_implicit_imports(iterable.unite(
|
||||||
for typ in types)
|
self.find_types(typ, name, is_goto=True) for typ in types
|
||||||
|
))
|
||||||
else:
|
else:
|
||||||
return self.find_types(scope, name, name.start_pos,
|
return self.find_types(scope, name, name.start_pos,
|
||||||
search_global=True, is_goto=True)
|
search_global=True, is_goto=True)
|
||||||
|
|
||||||
|
|
||||||
if isinstance(stmt, pr.Import):
|
if isinstance(stmt, pr.Import):
|
||||||
# Nowhere to goto for aliases
|
# Nowhere to goto for aliases
|
||||||
if stmt.alias == call_path[0]:
|
if stmt.alias == call_path[0]:
|
||||||
|
|||||||
@@ -768,7 +768,7 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, pr.Module, Wrapper)):
|
|||||||
@property
|
@property
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def name(self):
|
def name(self):
|
||||||
return helpers.FakeName(unicode(self.base.name), self)
|
return helpers.FakeName(unicode(self.base.name), self, (1, 0))
|
||||||
|
|
||||||
@memoize_default()
|
@memoize_default()
|
||||||
def _sub_modules(self):
|
def _sub_modules(self):
|
||||||
|
|||||||
@@ -49,11 +49,12 @@ class Abc():
|
|||||||
Abc.d.Abc
|
Abc.d.Abc
|
||||||
|
|
||||||
|
|
||||||
#< 4 (0,4), (4,1)
|
#< 4 (0,4), (5,1)
|
||||||
def blubi():
|
def blubi():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
#< (-4,4), (0,1)
|
#< (-5,4), (0,1)
|
||||||
@blubi
|
@blubi
|
||||||
def a(): pass
|
def a(): pass
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user