forked from VimPlug/jedi
move the usages stuff away from dynamic
This commit is contained in:
80
jedi/api.py
80
jedi/api.py
@@ -700,3 +700,83 @@ def set_debug_function(func_cb=debug.print_to_stdout, warnings=True,
|
|||||||
debug.enable_warning = warnings
|
debug.enable_warning = warnings
|
||||||
debug.enable_notice = notices
|
debug.enable_notice = notices
|
||||||
debug.enable_speed = speed
|
debug.enable_speed = speed
|
||||||
|
|
||||||
|
|
||||||
|
# TODO move to a better place.
|
||||||
|
def usages(definitions, search_name, mods):
|
||||||
|
def compare_array(definitions):
|
||||||
|
""" `definitions` are being compared by module/start_pos, because
|
||||||
|
sometimes the id's of the objects change (e.g. executions).
|
||||||
|
"""
|
||||||
|
result = []
|
||||||
|
for d in definitions:
|
||||||
|
module = d.get_parent_until()
|
||||||
|
result.append((module, d.start_pos))
|
||||||
|
return result
|
||||||
|
|
||||||
|
def check_call(call):
|
||||||
|
result = []
|
||||||
|
follow = [] # There might be multiple search_name's in one call_path
|
||||||
|
call_path = list(call.generate_call_path())
|
||||||
|
for i, name in enumerate(call_path):
|
||||||
|
# name is `pr.NamePart`.
|
||||||
|
if name == search_name:
|
||||||
|
follow.append(call_path[:i + 1])
|
||||||
|
|
||||||
|
for f in follow:
|
||||||
|
follow_res, search = evaluate.goto(call.parent, f)
|
||||||
|
follow_res = usages_add_import_modules(follow_res, search)
|
||||||
|
|
||||||
|
compare_follow_res = compare_array(follow_res)
|
||||||
|
# compare to see if they match
|
||||||
|
if any(r in compare_definitions for r in compare_follow_res):
|
||||||
|
scope = call.parent
|
||||||
|
result.append(api_classes.Usage(search, scope))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
if not definitions:
|
||||||
|
return set()
|
||||||
|
|
||||||
|
compare_definitions = compare_array(definitions)
|
||||||
|
mods |= set([d.get_parent_until() for d in definitions])
|
||||||
|
names = []
|
||||||
|
for m in get_directory_modules_for_name(mods, search_name):
|
||||||
|
try:
|
||||||
|
stmts = m.used_names[search_name]
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
for stmt in stmts:
|
||||||
|
if isinstance(stmt, pr.Import):
|
||||||
|
count = 0
|
||||||
|
imps = []
|
||||||
|
for i in stmt.get_all_import_names():
|
||||||
|
for name_part in i.names:
|
||||||
|
count += 1
|
||||||
|
if name_part == search_name:
|
||||||
|
imps.append((count, name_part))
|
||||||
|
|
||||||
|
for used_count, name_part in imps:
|
||||||
|
i = imports.ImportPath(_evaluator, stmt, kill_count=count - used_count,
|
||||||
|
direct_resolve=True)
|
||||||
|
f = i.follow(is_goto=True)
|
||||||
|
if set(f) & set(definitions):
|
||||||
|
names.append(api_classes.Usage(name_part, stmt))
|
||||||
|
else:
|
||||||
|
for call in _scan_statement(stmt, search_name,
|
||||||
|
assignment_details=True):
|
||||||
|
names += check_call(call)
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
def usages_add_import_modules(definitions, search_name):
|
||||||
|
""" Adds the modules of the imports """
|
||||||
|
new = set()
|
||||||
|
for d in definitions:
|
||||||
|
if isinstance(d.parent, pr.Import):
|
||||||
|
s = imports.ImportPath(_evaluator, d.parent, direct_resolve=True)
|
||||||
|
with common.ignored(IndexError):
|
||||||
|
new.add(s.follow(is_goto=True)[0])
|
||||||
|
return set(definitions) | new
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -57,10 +57,8 @@ from jedi import cache
|
|||||||
from jedi.parser import representation as pr
|
from jedi.parser import representation as pr
|
||||||
from jedi import modules
|
from jedi import modules
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
from jedi import common
|
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
from jedi.parser import fast as fast_parser
|
from jedi.parser import fast as fast_parser
|
||||||
from jedi.evaluate import imports
|
|
||||||
from jedi.evaluate.cache import memoize_default
|
from jedi.evaluate.cache import memoize_default
|
||||||
|
|
||||||
# This is something like the sys.path, but only for searching params. It means
|
# This is something like the sys.path, but only for searching params. It means
|
||||||
@@ -449,83 +447,6 @@ class ArrayInstance(pr.Base):
|
|||||||
return items
|
return items
|
||||||
|
|
||||||
|
|
||||||
def usages(definitions, search_name, mods):
|
|
||||||
def compare_array(definitions):
|
|
||||||
""" `definitions` are being compared by module/start_pos, because
|
|
||||||
sometimes the id's of the objects change (e.g. executions).
|
|
||||||
"""
|
|
||||||
result = []
|
|
||||||
for d in definitions:
|
|
||||||
module = d.get_parent_until()
|
|
||||||
result.append((module, d.start_pos))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def check_call(call):
|
|
||||||
result = []
|
|
||||||
follow = [] # There might be multiple search_name's in one call_path
|
|
||||||
call_path = list(call.generate_call_path())
|
|
||||||
for i, name in enumerate(call_path):
|
|
||||||
# name is `pr.NamePart`.
|
|
||||||
if name == search_name:
|
|
||||||
follow.append(call_path[:i + 1])
|
|
||||||
|
|
||||||
for f in follow:
|
|
||||||
follow_res, search = evaluate.goto(call.parent, f)
|
|
||||||
follow_res = usages_add_import_modules(follow_res, search)
|
|
||||||
|
|
||||||
compare_follow_res = compare_array(follow_res)
|
|
||||||
# compare to see if they match
|
|
||||||
if any(r in compare_definitions for r in compare_follow_res):
|
|
||||||
scope = call.parent
|
|
||||||
result.append(api_classes.Usage(search, scope))
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
if not definitions:
|
|
||||||
return set()
|
|
||||||
|
|
||||||
compare_definitions = compare_array(definitions)
|
|
||||||
mods |= set([d.get_parent_until() for d in definitions])
|
|
||||||
names = []
|
|
||||||
for m in get_directory_modules_for_name(mods, search_name):
|
|
||||||
try:
|
|
||||||
stmts = m.used_names[search_name]
|
|
||||||
except KeyError:
|
|
||||||
continue
|
|
||||||
for stmt in stmts:
|
|
||||||
if isinstance(stmt, pr.Import):
|
|
||||||
count = 0
|
|
||||||
imps = []
|
|
||||||
for i in stmt.get_all_import_names():
|
|
||||||
for name_part in i.names:
|
|
||||||
count += 1
|
|
||||||
if name_part == search_name:
|
|
||||||
imps.append((count, name_part))
|
|
||||||
|
|
||||||
for used_count, name_part in imps:
|
|
||||||
i = imports.ImportPath(_evaluator, stmt, kill_count=count - used_count,
|
|
||||||
direct_resolve=True)
|
|
||||||
f = i.follow(is_goto=True)
|
|
||||||
if set(f) & set(definitions):
|
|
||||||
names.append(api_classes.Usage(name_part, stmt))
|
|
||||||
else:
|
|
||||||
for call in _scan_statement(stmt, search_name,
|
|
||||||
assignment_details=True):
|
|
||||||
names += check_call(call)
|
|
||||||
return names
|
|
||||||
|
|
||||||
|
|
||||||
def usages_add_import_modules(definitions, search_name):
|
|
||||||
""" Adds the modules of the imports """
|
|
||||||
new = set()
|
|
||||||
for d in definitions:
|
|
||||||
if isinstance(d.parent, pr.Import):
|
|
||||||
s = imports.ImportPath(_evaluator, d.parent, direct_resolve=True)
|
|
||||||
with common.ignored(IndexError):
|
|
||||||
new.add(s.follow(is_goto=True)[0])
|
|
||||||
return set(definitions) | new
|
|
||||||
|
|
||||||
|
|
||||||
def check_flow_information(flow, search_name, pos):
|
def check_flow_information(flow, search_name, pos):
|
||||||
""" Try to find out the type of a variable just with the information that
|
""" Try to find out the type of a variable just with the information that
|
||||||
is given by the flows: e.g. It is also responsible for assert checks.::
|
is given by the flows: e.g. It is also responsible for assert checks.::
|
||||||
|
|||||||
Reference in New Issue
Block a user