forked from VimPlug/jedi
Get an example running: 'import json; json.dump'.
This commit is contained in:
@@ -82,7 +82,7 @@ class NameFinder(object):
|
|||||||
name_list = sorted(name_list, key=lambda n: n.start_pos, reverse=True)
|
name_list = sorted(name_list, key=lambda n: n.start_pos, reverse=True)
|
||||||
|
|
||||||
for name in name_list:
|
for name in name_list:
|
||||||
if unicode(self.name_str) != name.get_code():
|
if unicode(self.name_str) != unicode(name):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
stmt = name.get_definition()
|
stmt = name.get_definition()
|
||||||
@@ -233,6 +233,7 @@ class NameFinder(object):
|
|||||||
|
|
||||||
for name in names:
|
for name in names:
|
||||||
typ = name.get_definition()
|
typ = name.get_definition()
|
||||||
|
print(typ)
|
||||||
if typ.isinstance(pr.ForFlow):
|
if typ.isinstance(pr.ForFlow):
|
||||||
types += self._handle_for_loops(typ)
|
types += self._handle_for_loops(typ)
|
||||||
elif isinstance(typ, pr.Param):
|
elif isinstance(typ, pr.Param):
|
||||||
@@ -243,6 +244,8 @@ class NameFinder(object):
|
|||||||
types += evaluator.find_types(typ.parent.parent, str(name))
|
types += evaluator.find_types(typ.parent.parent, str(name))
|
||||||
else:
|
else:
|
||||||
types += self._remove_statements(typ, name)
|
types += self._remove_statements(typ, name)
|
||||||
|
elif isinstance(typ, pr.Import):
|
||||||
|
types += imports.ImportWrapper(self._evaluator, name).follow()
|
||||||
else:
|
else:
|
||||||
if typ.isinstance(er.Function) and resolve_decorator:
|
if typ.isinstance(er.Function) and resolve_decorator:
|
||||||
typ = typ.get_decorated_func()
|
typ = typ.get_decorated_func()
|
||||||
|
|||||||
@@ -38,7 +38,73 @@ class ModuleNotFound(Exception):
|
|||||||
self.name_part = name_part
|
self.name_part = name_part
|
||||||
|
|
||||||
|
|
||||||
class ImportWrapper(pr.Base):
|
class ImportWrapper():
|
||||||
|
def __init__(self, evaluator, name):
|
||||||
|
self._evaluator = evaluator
|
||||||
|
self._name = name
|
||||||
|
|
||||||
|
self._import = name.get_parent_until(pr.Import)
|
||||||
|
|
||||||
|
@memoize_default()
|
||||||
|
def follow(self, is_goto=False):
|
||||||
|
if self._evaluator.recursion_detector.push_stmt(self._import):
|
||||||
|
# check recursion
|
||||||
|
return []
|
||||||
|
|
||||||
|
try:
|
||||||
|
module = self._import.get_parent_until()
|
||||||
|
import_path = self._import.path_for_name(self._name)
|
||||||
|
importer = get_importer(self._evaluator, tuple(import_path), module, level=0)
|
||||||
|
try:
|
||||||
|
module, rest = importer.follow_file_system()
|
||||||
|
except ModuleNotFound as e:
|
||||||
|
analysis.add(self._evaluator, 'import-error', e.name_part)
|
||||||
|
return []
|
||||||
|
|
||||||
|
if module is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
if self._import.is_nested() and not self.nested_resolve:
|
||||||
|
scopes = [NestedImportModule(module, self._import)]
|
||||||
|
else:
|
||||||
|
scopes = [module]
|
||||||
|
|
||||||
|
star_imports = remove_star_imports(self._evaluator, module)
|
||||||
|
if star_imports:
|
||||||
|
scopes = [StarImportModule(scopes[0], star_imports)]
|
||||||
|
|
||||||
|
# goto only accepts `Name`
|
||||||
|
if is_goto and not rest:
|
||||||
|
scopes = [s.name for s in scopes]
|
||||||
|
|
||||||
|
# follow the rest of the import (not FS -> classes, functions)
|
||||||
|
if len(rest) > 1 or rest and self.is_like_search:
|
||||||
|
scopes = []
|
||||||
|
if ('os', 'path') == self.import_path[:2] \
|
||||||
|
and not self._is_relative_import():
|
||||||
|
# This is a huge exception, we follow a nested import
|
||||||
|
# ``os.path``, because it's a very important one in Python
|
||||||
|
# that is being achieved by messing with ``sys.modules`` in
|
||||||
|
# ``os``.
|
||||||
|
scopes = self._evaluator.follow_path(iter(rest), [module], module)
|
||||||
|
elif rest:
|
||||||
|
if is_goto:
|
||||||
|
scopes = list(chain.from_iterable(
|
||||||
|
self._evaluator.find_types(s, rest[0], is_goto=True)
|
||||||
|
for s in scopes))
|
||||||
|
else:
|
||||||
|
scopes = list(chain.from_iterable(
|
||||||
|
self._evaluator.follow_path(iter(rest), [s], s)
|
||||||
|
for s in scopes))
|
||||||
|
debug.dbg('after import: %s', scopes)
|
||||||
|
if not scopes:
|
||||||
|
analysis.add(self._evaluator, 'import-error',
|
||||||
|
self._importer.import_path[-1])
|
||||||
|
finally:
|
||||||
|
self._evaluator.recursion_detector.pop_stmt()
|
||||||
|
return scopes
|
||||||
|
|
||||||
|
class ImportWrapper2(pr.Base):
|
||||||
"""
|
"""
|
||||||
An ImportWrapper is the path of a `pr.Import` object.
|
An ImportWrapper is the path of a `pr.Import` object.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ class Name(_Leaf):
|
|||||||
self.start_pos[0], self.start_pos[1])
|
self.start_pos[0], self.start_pos[1])
|
||||||
|
|
||||||
def get_definition(self):
|
def get_definition(self):
|
||||||
return self.get_parent_until((ArrayStmt, StatementElement), reverse=True)
|
return self.parent.get_parent_until((ArrayStmt, StatementElement), reverse=True)
|
||||||
|
|
||||||
|
|
||||||
class Literal(_Leaf):
|
class Literal(_Leaf):
|
||||||
@@ -416,6 +416,8 @@ class Scope(Simple, DocstringMixin):
|
|||||||
for c in self.children:
|
for c in self.children:
|
||||||
if isinstance(c, ExprStmt):
|
if isinstance(c, ExprStmt):
|
||||||
names += c.get_defined_names()
|
names += c.get_defined_names()
|
||||||
|
elif isinstance(c, (Function, Class)):
|
||||||
|
names.append(c.name)
|
||||||
return names
|
return names
|
||||||
|
|
||||||
@Python3Method
|
@Python3Method
|
||||||
@@ -844,7 +846,8 @@ class Import(Simple):
|
|||||||
if self.children[0] == 'import':
|
if self.children[0] == 'import':
|
||||||
return self.children[1:]
|
return self.children[1:]
|
||||||
else: # from
|
else: # from
|
||||||
raise NotImplementedError
|
# <Operator: '.'>, <Name: decoder@110,6>, <Keyword: 'import'>, <Name: JSONDecoder@110,21>
|
||||||
|
return [self.children[-1]]
|
||||||
|
|
||||||
# TODO remove
|
# TODO remove
|
||||||
if self.defunct:
|
if self.defunct:
|
||||||
@@ -868,6 +871,23 @@ class Import(Simple):
|
|||||||
n.append(self.alias)
|
n.append(self.alias)
|
||||||
return n
|
return n
|
||||||
|
|
||||||
|
def _paths(self):
|
||||||
|
if self.children[0] == 'import':
|
||||||
|
return [self.children[1:]]
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def path_for_name(self, name):
|
||||||
|
for path in self._paths():
|
||||||
|
if name in path:
|
||||||
|
return path
|
||||||
|
|
||||||
|
@property
|
||||||
|
def level(self):
|
||||||
|
"""The level parameter of ``__import__``."""
|
||||||
|
# TODO implement
|
||||||
|
return 0
|
||||||
|
|
||||||
def is_nested(self):
|
def is_nested(self):
|
||||||
"""
|
"""
|
||||||
This checks for the special case of nested imports, without aliases and
|
This checks for the special case of nested imports, without aliases and
|
||||||
@@ -875,6 +895,8 @@ class Import(Simple):
|
|||||||
|
|
||||||
import foo.bar
|
import foo.bar
|
||||||
"""
|
"""
|
||||||
|
return False
|
||||||
|
# TODO use this check differently?
|
||||||
return not self.alias and not self.from_names \
|
return not self.alias and not self.from_names \
|
||||||
and len(self.namespace_names) > 1
|
and len(self.namespace_names) > 1
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user