1
0
forked from VimPlug/jedi

Fix most usage tests.

This commit is contained in:
Dave Halter
2016-11-19 02:24:34 +01:00
parent 05581714d9
commit b77fa58058
4 changed files with 68 additions and 55 deletions
+13 -11
View File
@@ -34,6 +34,7 @@ from jedi.evaluate.param import try_iter_content
from jedi.evaluate.helpers import get_module_names from jedi.evaluate.helpers import get_module_names
from jedi.evaluate.sys_path import get_venv_path from jedi.evaluate.sys_path import get_venv_path
from jedi.evaluate.iterable import unpack_tuple_to_dict from jedi.evaluate.iterable import unpack_tuple_to_dict
from jedi.evaluate.filters import TreeNameDefinition
# Jedi uses lots and lots of recursion. By setting this a little bit higher, we # Jedi uses lots and lots of recursion. By setting this a little bit higher, we
# can remove some "maximum recursion depth" errors. # can remove some "maximum recursion depth" errors.
@@ -256,8 +257,8 @@ class Script(object):
try: try:
module_node = self._get_module_node() module_node = self._get_module_node()
user_stmt = module_node.get_statement_for_position(self._pos) user_stmt = module_node.get_statement_for_position(self._pos)
definitions = self._goto() definition_names = self._goto()
if not definitions and isinstance(user_stmt, tree.Import): if not definition_names and isinstance(user_stmt, tree.Import):
# For not defined imports (goto doesn't find something, we take # For not defined imports (goto doesn't find something, we take
# the name as a definition. This is enough, because every name # the name as a definition. This is enough, because every name
# points to it. # points to it.
@@ -265,22 +266,23 @@ class Script(object):
if name is None: if name is None:
# Must be syntax # Must be syntax
return [] return []
definitions = [name] self._evaluator
definition_names = [TreeNameDefinition(self._get_module(), name)]
if not definitions: if not definition_names:
# Without a definition for a name we cannot find references. # Without a definition for a name we cannot find references.
return [] return []
if not isinstance(user_stmt, tree.Import): if not isinstance(user_stmt, tree.Import) and False:
# import case is looked at with add_import_name option # import case is looked at with add_import_name option
definitions = usages.usages_add_import_modules(self._evaluator, definition_names = usages.usages_add_import_modules(self._evaluator,
definitions) definition_names)
module = set([d.get_parent_until() for d in definitions]) modules = set([d.get_root_context() for d in definition_names])
module.add(module_node) modules.add(self._get_module())
names = usages.usages(self._evaluator, definitions, module) names = usages.usages(self._evaluator, definition_names, modules)
for d in set(definitions): for d in set(definition_names):
names.append(classes.Definition(self._evaluator, d)) names.append(classes.Definition(self._evaluator, d))
finally: finally:
settings.dynamic_flow_information = temp settings.dynamic_flow_information = temp
+9 -10
View File
@@ -2,6 +2,7 @@ from jedi._compatibility import unicode
from jedi.api import classes from jedi.api import classes
from jedi.parser import tree from jedi.parser import tree
from jedi.evaluate import imports from jedi.evaluate import imports
from jedi.evaluate.filters import TreeNameDefinition
def usages(evaluator, definition_names, mods): def usages(evaluator, definition_names, mods):
@@ -14,23 +15,20 @@ def usages(evaluator, definition_names, mods):
""" """
result = [] result = []
for d in definitions: for d in definitions:
module = d.get_parent_until() module = d.get_root_context()
result.append((module, d.start_pos)) result.append((module, d.start_pos))
return result return result
search_name = unicode(list(definition_names)[0]) search_name = list(definition_names)[0].string_name
compare_definitions = compare_array(definition_names) compare_definitions = compare_array(definition_names)
mods |= set([d.get_parent_until() for d in definition_names]) mods = mods | set([d.get_root_context() for d in definition_names])
definitions = [] definitions = []
for m in imports.get_modules_containing_name(evaluator, mods, search_name): for m in imports.get_modules_containing_name(evaluator, mods, search_name):
try: for name_node in m.module_node.used_names.get(search_name, []):
check_names = m.used_names[search_name] context = evaluator.create_context(m, name_node)
except KeyError: result = evaluator.goto(context, name_node)
continue
for name in check_names:
result = evaluator.goto(name)
if [c for c in compare_array(result) if c in compare_definitions]: if [c for c in compare_array(result) if c in compare_definitions]:
name = TreeNameDefinition(context, name_node)
definitions.append(classes.Definition(evaluator, name)) definitions.append(classes.Definition(evaluator, name))
# Previous definitions might be imports, so include them # Previous definitions might be imports, so include them
# (because goto might return that import name). # (because goto might return that import name).
@@ -42,6 +40,7 @@ def usages_add_import_modules(evaluator, definitions):
""" Adds the modules of the imports """ """ Adds the modules of the imports """
new = set() new = set()
for d in definitions: for d in definitions:
print(d)
imp_or_stmt = d.get_definition() imp_or_stmt = d.get_definition()
if isinstance(imp_or_stmt, tree.Import): if isinstance(imp_or_stmt, tree.Import):
s = imports.ImportWrapper(context, d) s = imports.ImportWrapper(context, d)
+12 -9
View File
@@ -74,7 +74,12 @@ def search_params(evaluator, parent_context, funcdef):
evaluator.dynamic_params_depth += 1 evaluator.dynamic_params_depth += 1
try: try:
debug.dbg('Dynamic param search in %s.', funcdef.name.value, color='MAGENTA') debug.dbg('Dynamic param search in %s.', funcdef.name.value, color='MAGENTA')
function_executions = _search_function_executions(evaluator, funcdef) module_context = parent_context.get_root_context()
function_executions = _search_function_executions(
evaluator,
module_context,
funcdef
)
if function_executions: if function_executions:
zipped_params = zip(*( zipped_params = zip(*(
function_execution.get_params() function_execution.get_params()
@@ -92,15 +97,15 @@ def search_params(evaluator, parent_context, funcdef):
@memoize_default([], evaluator_is_first_arg=True) @memoize_default([], evaluator_is_first_arg=True)
@to_list @to_list
def _search_function_executions(evaluator, funcdef): def _search_function_executions(evaluator, module_context, funcdef):
""" """
Returns a list of param names. Returns a list of param names.
""" """
from jedi.evaluate import representation as er from jedi.evaluate import representation as er
def get_possible_nodes(module_node, func_name): def get_possible_nodes(module_context, func_name):
try: try:
names = module_node.used_names[func_name] names = module_context.module_node.used_names[func_name]
except KeyError: except KeyError:
return return
@@ -110,7 +115,6 @@ def _search_function_executions(evaluator, funcdef):
if trailer.type == 'trailer' and bracket == '(': if trailer.type == 'trailer' and bracket == '(':
yield name, trailer yield name, trailer
current_module_node = funcdef.get_parent_until()
func_name = unicode(funcdef.name) func_name = unicode(funcdef.name)
compare_node = funcdef compare_node = funcdef
if func_name == '__init__': if func_name == '__init__':
@@ -122,10 +126,9 @@ def _search_function_executions(evaluator, funcdef):
found_executions = False found_executions = False
i = 0 i = 0
for module_node in imports.get_module_nodes_containing_name( for for_mod_context in imports.get_modules_containing_name(
evaluator, [current_module_node], func_name): evaluator, [module_context], func_name):
module_context = er.ModuleContext(evaluator, module_node) for name, trailer in get_possible_nodes(for_mod_context, func_name):
for name, trailer in get_possible_nodes(module_node, func_name):
i += 1 i += 1
# This is a simple way to stop Jedi's dynamic param recursion # This is a simple way to stop Jedi's dynamic param recursion
+34 -25
View File
@@ -455,9 +455,12 @@ def _load_module(evaluator, path=None, source=None, sys_path=None, parent_module
sys_path = evaluator.sys_path sys_path = evaluator.sys_path
cached = load_parser(path) cached = load_parser(path)
module = load(source) if cached is None else cached.module module_node = load(source) if cached is None else cached.module
if isinstance(module_node, compiled.CompiledObject):
return module_node
from jedi.evaluate.representation import ModuleContext from jedi.evaluate.representation import ModuleContext
return ModuleContext(evaluator, module) return ModuleContext(evaluator, module_node)
def add_module(evaluator, module_name, module): def add_module(evaluator, module_name, module):
@@ -469,18 +472,22 @@ def add_module(evaluator, module_name, module):
evaluator.modules[module_name] = module evaluator.modules[module_name] = module
def get_module_nodes_containing_name(evaluator, module_nodes, name): def get_modules_containing_name(evaluator, modules, name):
""" """
Search a name in the directories of modules. Search a name in the directories of modules.
""" """
from jedi.evaluate import representation as er
def check_python_file(path): def check_python_file(path):
try: try:
return parser_cache[path].parser.module parser_cache_item = parser_cache[path]
except KeyError: except KeyError:
try: try:
return check_fs(path) return check_fs(path)
except IOError: except IOError:
return None return None
else:
return er.ModuleContext(evaluator, parser_cache_item.parser.module)
def check_fs(path): def check_fs(path):
with open(path, 'rb') as f: with open(path, 'rb') as f:
@@ -492,27 +499,29 @@ def get_module_nodes_containing_name(evaluator, module_nodes, name):
return module return module
# skip non python modules # skip non python modules
module_nodes = set(m for m in module_nodes if not isinstance(m, compiled.CompiledObject)) used_mod_paths = set()
mod_paths = set() for m in modules:
for m in module_nodes: used_mod_paths.add(m.py__file__())
mod_paths.add(m.path)
yield m yield m
if settings.dynamic_params_for_other_modules: if not settings.dynamic_params_for_other_modules:
paths = set(settings.additional_dynamic_modules) return
for p in mod_paths:
if p is not None:
# We need abspath, because the seetings paths might not already
# have been converted to absolute paths.
d = os.path.dirname(os.path.abspath(p))
for entry in os.listdir(d):
if entry not in mod_paths:
if entry.endswith('.py'):
paths.add(d + os.path.sep + entry)
for p in sorted(paths): paths = set(settings.additional_dynamic_modules)
# make testing easier, sort it - same results on every interpreter for p in used_mod_paths:
c = check_python_file(p) if p is not None:
if c is not None and c not in module_nodes and not isinstance(c, compiled.CompiledObject): # We need abspath, because the seetings paths might not already
continue # TODO REENABLE # have been converted to absolute paths.
yield c.module_node d = os.path.dirname(os.path.abspath(p))
for file_name in os.listdir(d):
path = os.path.join(d, file_name)
if path not in used_mod_paths and path not in paths:
if file_name.endswith('.py'):
paths.add(path)
# Sort here to make issues less random.
for p in sorted(paths):
# make testing easier, sort it - same results on every interpreter
m = check_python_file(p)
if m is not None and not isinstance(m, compiled.CompiledObject):
yield m