forked from VimPlug/jedi
ImportPath has now also an _evaluator
This commit is contained in:
@@ -413,7 +413,7 @@ class Script(object):
|
|||||||
for d in defs:
|
for d in defs:
|
||||||
if isinstance(d.parent, pr.Import) \
|
if isinstance(d.parent, pr.Import) \
|
||||||
and d.start_pos == (0, 0):
|
and d.start_pos == (0, 0):
|
||||||
i = imports.ImportPath(d.parent).follow(is_goto=True)
|
i = imports.ImportPath(self._evaluator, d.parent).follow(is_goto=True)
|
||||||
definitions.remove(d)
|
definitions.remove(d)
|
||||||
definitions |= follow_inexistent_imports(i)
|
definitions |= follow_inexistent_imports(i)
|
||||||
return definitions
|
return definitions
|
||||||
@@ -556,7 +556,7 @@ class Script(object):
|
|||||||
context = self._module.get_context()
|
context = self._module.get_context()
|
||||||
just_from = next(context) == 'from'
|
just_from = next(context) == 'from'
|
||||||
|
|
||||||
i = imports.ImportPath(user_stmt, is_like_search,
|
i = imports.ImportPath(self._evaluator, user_stmt, is_like_search,
|
||||||
kill_count=kill_count, direct_resolve=True,
|
kill_count=kill_count, direct_resolve=True,
|
||||||
is_just_from=just_from)
|
is_just_from=just_from)
|
||||||
return i, cur_name_part
|
return i, cur_name_part
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ class Completion(BaseDefinition):
|
|||||||
if self._definition.isinstance(pr.Statement):
|
if self._definition.isinstance(pr.Statement):
|
||||||
defs = evaluate.follow_statement(self._definition)
|
defs = evaluate.follow_statement(self._definition)
|
||||||
elif self._definition.isinstance(pr.Import):
|
elif self._definition.isinstance(pr.Import):
|
||||||
defs = imports.strip_imports([self._definition])
|
defs = imports.strip_imports(self._evaluator, [self._definition])
|
||||||
else:
|
else:
|
||||||
return [self]
|
return [self]
|
||||||
|
|
||||||
|
|||||||
@@ -504,7 +504,7 @@ def usages(definitions, search_name, mods):
|
|||||||
imps.append((count, name_part))
|
imps.append((count, name_part))
|
||||||
|
|
||||||
for used_count, name_part in imps:
|
for used_count, name_part in imps:
|
||||||
i = imports.ImportPath(stmt, kill_count=count - used_count,
|
i = imports.ImportPath(_evaluator, stmt, kill_count=count - used_count,
|
||||||
direct_resolve=True)
|
direct_resolve=True)
|
||||||
f = i.follow(is_goto=True)
|
f = i.follow(is_goto=True)
|
||||||
if set(f) & set(definitions):
|
if set(f) & set(definitions):
|
||||||
@@ -521,7 +521,7 @@ def usages_add_import_modules(definitions, search_name):
|
|||||||
new = set()
|
new = set()
|
||||||
for d in definitions:
|
for d in definitions:
|
||||||
if isinstance(d.parent, pr.Import):
|
if isinstance(d.parent, pr.Import):
|
||||||
s = imports.ImportPath(d.parent, direct_resolve=True)
|
s = imports.ImportPath(_evaluator, d.parent, direct_resolve=True)
|
||||||
with common.ignored(IndexError):
|
with common.ignored(IndexError):
|
||||||
new.add(s.follow(is_goto=True)[0])
|
new.add(s.follow(is_goto=True)[0])
|
||||||
return set(definitions) | new
|
return set(definitions) | new
|
||||||
|
|||||||
@@ -115,97 +115,96 @@ def get_defined_names_for_position(scope, position=None, start_scope=None):
|
|||||||
return names_new
|
return names_new
|
||||||
|
|
||||||
|
|
||||||
def get_names_of_scope(scope, position=None, star_search=True,
|
|
||||||
include_builtin=True):
|
|
||||||
"""
|
|
||||||
Get all completions (names) possible for the current scope.
|
|
||||||
The star search option is only here to provide an optimization. Otherwise
|
|
||||||
the whole thing would probably start a little recursive madness.
|
|
||||||
|
|
||||||
This function is used to include names from outer scopes. For example,
|
|
||||||
when the current scope is function:
|
|
||||||
|
|
||||||
>>> from jedi.parser import Parser
|
|
||||||
>>> parser = Parser('''
|
|
||||||
... x = ['a', 'b', 'c']
|
|
||||||
... def func():
|
|
||||||
... y = None
|
|
||||||
... ''')
|
|
||||||
>>> scope = parser.module.subscopes[0]
|
|
||||||
>>> scope
|
|
||||||
<Function: func@3-4>
|
|
||||||
|
|
||||||
`get_names_of_scope` is a generator. First it yields names from
|
|
||||||
most inner scope.
|
|
||||||
|
|
||||||
>>> pairs = list(get_names_of_scope(scope))
|
|
||||||
>>> pairs[0]
|
|
||||||
(<Function: func@3-4>, [<Name: y@4,4>])
|
|
||||||
|
|
||||||
Then it yield the names from one level outer scope. For this
|
|
||||||
example, this is the most outer scope.
|
|
||||||
|
|
||||||
>>> pairs[1]
|
|
||||||
(<SubModule: None@1-4>, [<Name: x@2,0>, <Name: func@3,4>])
|
|
||||||
|
|
||||||
Finally, it yields names from builtin, if `include_builtin` is
|
|
||||||
true (default).
|
|
||||||
|
|
||||||
>>> pairs[2] #doctest: +ELLIPSIS
|
|
||||||
(<Module: ...builtin...>, [<Name: ...>, ...])
|
|
||||||
|
|
||||||
:rtype: [(pr.Scope, [pr.Name])]
|
|
||||||
:return: Return an generator that yields a pair of scope and names.
|
|
||||||
"""
|
|
||||||
in_func_scope = scope
|
|
||||||
non_flow = scope.get_parent_until(pr.Flow, reverse=True)
|
|
||||||
while scope:
|
|
||||||
if isinstance(scope, pr.SubModule) and scope.parent:
|
|
||||||
# we don't want submodules to report if we have modules.
|
|
||||||
scope = scope.parent
|
|
||||||
continue
|
|
||||||
# `pr.Class` is used, because the parent is never `Class`.
|
|
||||||
# Ignore the Flows, because the classes and functions care for that.
|
|
||||||
# InstanceElement of Class is ignored, if it is not the start scope.
|
|
||||||
if not (scope != non_flow and scope.isinstance(pr.Class)
|
|
||||||
or scope.isinstance(pr.Flow)
|
|
||||||
or scope.isinstance(er.Instance)
|
|
||||||
and non_flow.isinstance(er.Function)):
|
|
||||||
try:
|
|
||||||
if isinstance(scope, er.Instance):
|
|
||||||
for g in scope.scope_generator():
|
|
||||||
yield g
|
|
||||||
else:
|
|
||||||
yield scope, get_defined_names_for_position(scope,
|
|
||||||
position, in_func_scope)
|
|
||||||
except StopIteration:
|
|
||||||
reraise(common.MultiLevelStopIteration, sys.exc_info()[2])
|
|
||||||
if scope.isinstance(pr.ForFlow) and scope.is_list_comp:
|
|
||||||
# is a list comprehension
|
|
||||||
yield scope, scope.get_set_vars(is_internal_call=True)
|
|
||||||
|
|
||||||
scope = scope.parent
|
|
||||||
# This is used, because subscopes (Flow scopes) would distort the
|
|
||||||
# results.
|
|
||||||
if scope and scope.isinstance(er.Function, pr.Function, er.Execution):
|
|
||||||
in_func_scope = scope
|
|
||||||
|
|
||||||
# Add star imports.
|
|
||||||
if star_search:
|
|
||||||
for s in imports.remove_star_imports(non_flow.get_parent_until()):
|
|
||||||
for g in get_names_of_scope(s, star_search=False):
|
|
||||||
yield g
|
|
||||||
|
|
||||||
# Add builtins to the global scope.
|
|
||||||
if include_builtin:
|
|
||||||
builtin_scope = builtin.Builtin.scope
|
|
||||||
yield builtin_scope, builtin_scope.get_defined_names()
|
|
||||||
|
|
||||||
|
|
||||||
class Evaluator(object):
|
class Evaluator(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.cache = None
|
self.cache = None
|
||||||
|
|
||||||
|
def get_names_of_scope(self, scope, position=None, star_search=True,
|
||||||
|
include_builtin=True):
|
||||||
|
"""
|
||||||
|
Get all completions (names) possible for the current scope.
|
||||||
|
The star search option is only here to provide an optimization. Otherwise
|
||||||
|
the whole thing would probably start a little recursive madness.
|
||||||
|
|
||||||
|
This function is used to include names from outer scopes. For example,
|
||||||
|
when the current scope is function:
|
||||||
|
|
||||||
|
>>> from jedi.parser import Parser
|
||||||
|
>>> parser = Parser('''
|
||||||
|
... x = ['a', 'b', 'c']
|
||||||
|
... def func():
|
||||||
|
... y = None
|
||||||
|
... ''')
|
||||||
|
>>> scope = parser.module.subscopes[0]
|
||||||
|
>>> scope
|
||||||
|
<Function: func@3-4>
|
||||||
|
|
||||||
|
`get_names_of_scope` is a generator. First it yields names from
|
||||||
|
most inner scope.
|
||||||
|
|
||||||
|
>>> pairs = list(Evaluator().get_names_of_scope(scope))
|
||||||
|
>>> pairs[0]
|
||||||
|
(<Function: func@3-4>, [<Name: y@4,4>])
|
||||||
|
|
||||||
|
Then it yield the names from one level outer scope. For this
|
||||||
|
example, this is the most outer scope.
|
||||||
|
|
||||||
|
>>> pairs[1]
|
||||||
|
(<SubModule: None@1-4>, [<Name: x@2,0>, <Name: func@3,4>])
|
||||||
|
|
||||||
|
Finally, it yields names from builtin, if `include_builtin` is
|
||||||
|
true (default).
|
||||||
|
|
||||||
|
>>> pairs[2] #doctest: +ELLIPSIS
|
||||||
|
(<Module: ...builtin...>, [<Name: ...>, ...])
|
||||||
|
|
||||||
|
:rtype: [(pr.Scope, [pr.Name])]
|
||||||
|
:return: Return an generator that yields a pair of scope and names.
|
||||||
|
"""
|
||||||
|
in_func_scope = scope
|
||||||
|
non_flow = scope.get_parent_until(pr.Flow, reverse=True)
|
||||||
|
while scope:
|
||||||
|
if isinstance(scope, pr.SubModule) and scope.parent:
|
||||||
|
# we don't want submodules to report if we have modules.
|
||||||
|
scope = scope.parent
|
||||||
|
continue
|
||||||
|
# `pr.Class` is used, because the parent is never `Class`.
|
||||||
|
# Ignore the Flows, because the classes and functions care for that.
|
||||||
|
# InstanceElement of Class is ignored, if it is not the start scope.
|
||||||
|
if not (scope != non_flow and scope.isinstance(pr.Class)
|
||||||
|
or scope.isinstance(pr.Flow)
|
||||||
|
or scope.isinstance(er.Instance)
|
||||||
|
and non_flow.isinstance(er.Function)):
|
||||||
|
try:
|
||||||
|
if isinstance(scope, er.Instance):
|
||||||
|
for g in scope.scope_generator():
|
||||||
|
yield g
|
||||||
|
else:
|
||||||
|
yield scope, get_defined_names_for_position(scope,
|
||||||
|
position, in_func_scope)
|
||||||
|
except StopIteration:
|
||||||
|
reraise(common.MultiLevelStopIteration, sys.exc_info()[2])
|
||||||
|
if scope.isinstance(pr.ForFlow) and scope.is_list_comp:
|
||||||
|
# is a list comprehension
|
||||||
|
yield scope, scope.get_set_vars(is_internal_call=True)
|
||||||
|
|
||||||
|
scope = scope.parent
|
||||||
|
# This is used, because subscopes (Flow scopes) would distort the
|
||||||
|
# results.
|
||||||
|
if scope and scope.isinstance(er.Function, pr.Function, er.Execution):
|
||||||
|
in_func_scope = scope
|
||||||
|
|
||||||
|
# Add star imports.
|
||||||
|
if star_search:
|
||||||
|
for s in imports.remove_star_imports(self, non_flow.get_parent_until()):
|
||||||
|
for g in self.get_names_of_scope(s, star_search=False):
|
||||||
|
yield g
|
||||||
|
|
||||||
|
# Add builtins to the global scope.
|
||||||
|
if include_builtin:
|
||||||
|
builtin_scope = builtin.Builtin.scope
|
||||||
|
yield builtin_scope, builtin_scope.get_defined_names()
|
||||||
|
|
||||||
def find_name(self, scope, name_str, position=None, search_global=False,
|
def find_name(self, scope, name_str, position=None, search_global=False,
|
||||||
is_goto=False, resolve_decorator=True):
|
is_goto=False, resolve_decorator=True):
|
||||||
"""
|
"""
|
||||||
@@ -458,7 +457,7 @@ class Evaluator(object):
|
|||||||
return res_new
|
return res_new
|
||||||
|
|
||||||
if search_global:
|
if search_global:
|
||||||
scope_generator = get_names_of_scope(scope, position=position)
|
scope_generator = self.get_names_of_scope(scope, position=position)
|
||||||
else:
|
else:
|
||||||
if isinstance(scope, er.Instance):
|
if isinstance(scope, er.Instance):
|
||||||
scope_generator = scope.scope_generator()
|
scope_generator = scope.scope_generator()
|
||||||
@@ -545,8 +544,8 @@ class Evaluator(object):
|
|||||||
if isinstance(call, pr.Lambda):
|
if isinstance(call, pr.Lambda):
|
||||||
result.append(er.Function(call))
|
result.append(er.Function(call))
|
||||||
# With things like params, these can also be functions...
|
# With things like params, these can also be functions...
|
||||||
elif isinstance(call, pr.Base) and call.isinstance(er.Function,
|
elif isinstance(call, pr.Base) and call.isinstance(
|
||||||
er.Class, er.Instance, dynamic.ArrayInstance):
|
er.Function, er.Class, er.Instance, dynamic.ArrayInstance):
|
||||||
result.append(call)
|
result.append(call)
|
||||||
# The string tokens are just operations (+, -, etc.)
|
# The string tokens are just operations (+, -, etc.)
|
||||||
elif not isinstance(call, (str, unicode)):
|
elif not isinstance(call, (str, unicode)):
|
||||||
@@ -596,7 +595,7 @@ class Evaluator(object):
|
|||||||
scopes = self.find_name(builtin.Builtin.scope, current.type_as_string())
|
scopes = self.find_name(builtin.Builtin.scope, current.type_as_string())
|
||||||
# Make instances of those number/string objects.
|
# Make instances of those number/string objects.
|
||||||
scopes = [er.Instance(s, (current.value,)) for s in scopes]
|
scopes = [er.Instance(s, (current.value,)) for s in scopes]
|
||||||
result = imports.strip_imports(scopes)
|
result = imports.strip_imports(self, scopes)
|
||||||
|
|
||||||
return self.follow_paths(path, result, scope, position=position)
|
return self.follow_paths(path, result, scope, position=position)
|
||||||
|
|
||||||
@@ -657,7 +656,7 @@ class Evaluator(object):
|
|||||||
# This is the typical lookup while chaining things.
|
# This is the typical lookup while chaining things.
|
||||||
if filter_private_variable(scope, call_scope, current):
|
if filter_private_variable(scope, call_scope, current):
|
||||||
return []
|
return []
|
||||||
result = imports.strip_imports(self.find_name(scope, current,
|
result = imports.strip_imports(self, self.find_name(scope, current,
|
||||||
position=position))
|
position=position))
|
||||||
return self.follow_paths(path, set(result), call_scope, position=position)
|
return self.follow_paths(path, set(result), call_scope, position=position)
|
||||||
|
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ class ImportPath(pr.Base):
|
|||||||
|
|
||||||
GlobalNamespace = GlobalNamespace()
|
GlobalNamespace = GlobalNamespace()
|
||||||
|
|
||||||
def __init__(self, import_stmt, is_like_search=False, kill_count=0,
|
def __init__(self, evaluator, import_stmt, is_like_search=False, kill_count=0,
|
||||||
direct_resolve=False, is_just_from=False):
|
direct_resolve=False, is_just_from=False):
|
||||||
|
self._evaluator = evaluator
|
||||||
self.import_stmt = import_stmt
|
self.import_stmt = import_stmt
|
||||||
self.is_like_search = is_like_search
|
self.is_like_search = is_like_search
|
||||||
self.direct_resolve = direct_resolve
|
self.direct_resolve = direct_resolve
|
||||||
@@ -373,7 +374,7 @@ class ImportPath(pr.Base):
|
|||||||
return f.parser.module, rest
|
return f.parser.module, rest
|
||||||
|
|
||||||
|
|
||||||
def strip_imports(scopes):
|
def strip_imports(evaluator, scopes):
|
||||||
"""
|
"""
|
||||||
Here we strip the imports - they don't get resolved necessarily.
|
Here we strip the imports - they don't get resolved necessarily.
|
||||||
Really used anymore? Merge with remove_star_imports?
|
Really used anymore? Merge with remove_star_imports?
|
||||||
@@ -381,25 +382,25 @@ def strip_imports(scopes):
|
|||||||
result = []
|
result = []
|
||||||
for s in scopes:
|
for s in scopes:
|
||||||
if isinstance(s, pr.Import):
|
if isinstance(s, pr.Import):
|
||||||
result += ImportPath(s).follow()
|
result += ImportPath(evaluator, s).follow()
|
||||||
else:
|
else:
|
||||||
result.append(s)
|
result.append(s)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
@cache.cache_star_import
|
@cache.cache_star_import
|
||||||
def remove_star_imports(scope, ignored_modules=()):
|
def remove_star_imports(evaluator, scope, ignored_modules=()):
|
||||||
"""
|
"""
|
||||||
Check a module for star imports:
|
Check a module for star imports:
|
||||||
>>> from module import *
|
>>> from module import *
|
||||||
|
|
||||||
and follow these modules.
|
and follow these modules.
|
||||||
"""
|
"""
|
||||||
modules = strip_imports(i for i in scope.get_imports() if i.star)
|
modules = strip_imports(evaluator, (i for i in scope.get_imports() if i.star))
|
||||||
new = []
|
new = []
|
||||||
for m in modules:
|
for m in modules:
|
||||||
if m not in ignored_modules:
|
if m not in ignored_modules:
|
||||||
new += remove_star_imports(m, modules)
|
new += remove_star_imports(evaluator, m, modules)
|
||||||
modules += new
|
modules += new
|
||||||
|
|
||||||
# Filter duplicate modules.
|
# Filter duplicate modules.
|
||||||
|
|||||||
@@ -498,7 +498,7 @@ class Execution(Executable):
|
|||||||
|
|
||||||
debug.dbg('exec result: %s in %s' % (stmts, self))
|
debug.dbg('exec result: %s in %s' % (stmts, self))
|
||||||
|
|
||||||
return imports.strip_imports(stmts)
|
return imports.strip_imports(self._evaluator, stmts)
|
||||||
|
|
||||||
def _get_function_returns(self, func, evaluate_generator):
|
def _get_function_returns(self, func, evaluate_generator):
|
||||||
""" A normal Function execution """
|
""" A normal Function execution """
|
||||||
|
|||||||
Reference in New Issue
Block a user