Better goto for imports, which helps usages.

This commit is contained in:
Dave Halter
2014-12-03 16:15:31 +01:00
parent 536c188192
commit 6bf154de5e
5 changed files with 27 additions and 16 deletions

View File

@@ -503,7 +503,7 @@ class Script(object):
import_name = user_stmt.get_defined_names()
# imports have only one name
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)
else:
# The Evaluator.goto function checks for definitions, but since we
@@ -549,12 +549,7 @@ class Script(object):
names = usages.usages(self._evaluator, definitions, module)
for d in set(definitions):
try:
name_part = d.names[-1]
except AttributeError:
names.append(classes.Definition(self._evaluator, d))
else:
names.append(classes.Definition(self._evaluator, name_part))
names.append(classes.Definition(self._evaluator, d))
finally:
settings.dynamic_flow_information = temp

View File

@@ -1,5 +1,4 @@
from jedi._compatibility import u, unicode
from jedi import common
from jedi.api import classes
from jedi.parser import tree as pr
from jedi.evaluate import imports
@@ -101,7 +100,6 @@ def usages_add_import_modules(evaluator, definitions):
for d in definitions:
imp_or_stmt = d.get_definition()
if isinstance(imp_or_stmt, pr.Import):
s = imports.ImportWrapper(evaluator, imp_or_stmt, nested_resolve=True)
with common.ignored(IndexError):
new.add(s.follow(is_goto=True)[0])
s = imports.ImportWrapper(evaluator, d)
new |= s.follow(is_goto=True)
return set(definitions) | new

View File

@@ -85,6 +85,7 @@ from jedi.evaluate import finder
from jedi.evaluate import compiled
from jedi.evaluate import precedence
from jedi.evaluate import param
from jedi.evaluate import helpers
from jedi.evaluate.helpers import FakeStatement, deep_ast_copy, call_of_name
@@ -455,21 +456,37 @@ class Evaluator(object):
return self.eval_element(call)
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
if isinstance(stmt, pr.ExprStmt) and name in stmt.get_defined_names():
# TODO remove? I think this is never called.
return [name]
elif isinstance(stmt, (pr.Param, pr.Function, pr.Class)) and stmt.name is name:
return [name]
elif isinstance(imp, pr.Import):
return imports.ImportWrapper(self, name).follow(is_goto=True)
scope = name.get_parent_scope()
if pr.is_node(name.parent, 'trailer'):
call = call_of_name(name, cut_own_trailer=True)
types = self.eval_element(call)
return iterable.unite(self.find_types(typ, name, is_goto=True)
for typ in types)
return resolve_implicit_imports(iterable.unite(
self.find_types(typ, name, is_goto=True) for typ in types
))
else:
return self.find_types(scope, name, name.start_pos,
search_global=True, is_goto=True)
if isinstance(stmt, pr.Import):
# Nowhere to goto for aliases
if stmt.alias == call_path[0]:

View File

@@ -768,7 +768,7 @@ class ModuleWrapper(use_metaclass(CachedMetaClass, pr.Module, Wrapper)):
@property
@memoize_default()
def name(self):
return helpers.FakeName(unicode(self.base.name), self)
return helpers.FakeName(unicode(self.base.name), self, (1, 0))
@memoize_default()
def _sub_modules(self):

View File

@@ -49,11 +49,12 @@ class Abc():
Abc.d.Abc
#< 4 (0,4), (4,1)
#< 4 (0,4), (5,1)
def blubi():
pass
#< (-4,4), (0,1)
#< (-5,4), (0,1)
@blubi
def a(): pass