forked from VimPlug/jedi
Fix dynamic param tests.
This commit is contained in:
+78
-37
@@ -16,9 +16,7 @@ It works as follows:
|
||||
- search for function calls named ``foo``
|
||||
- execute these calls and check the input. This work with a ``ParamListener``.
|
||||
"""
|
||||
from itertools import chain
|
||||
|
||||
from jedi._compatibility import unicode
|
||||
from jedi.parser import tree
|
||||
from jedi import settings
|
||||
from jedi import debug
|
||||
@@ -26,7 +24,6 @@ from jedi.evaluate.cache import memoize_default
|
||||
from jedi.evaluate import imports
|
||||
from jedi.evaluate.param import TreeArguments, create_default_param
|
||||
from jedi.common import to_list, unite
|
||||
from jedi.evaluate import context
|
||||
|
||||
|
||||
MAX_PARAM_SEARCHES = 20
|
||||
@@ -103,33 +100,21 @@ def _search_function_executions(evaluator, module_context, funcdef):
|
||||
"""
|
||||
from jedi.evaluate import representation as er
|
||||
|
||||
def get_possible_nodes(module_context, func_name):
|
||||
if not isinstance(module_context, er.ModuleContext):
|
||||
return
|
||||
try:
|
||||
names = module_context.module_node.used_names[func_name]
|
||||
except KeyError:
|
||||
return
|
||||
|
||||
for name in names:
|
||||
bracket = name.get_next_leaf()
|
||||
trailer = bracket.parent
|
||||
if trailer.type == 'trailer' and bracket == '(':
|
||||
yield name, trailer
|
||||
|
||||
func_name = unicode(funcdef.name)
|
||||
func_string_name = funcdef.name.value
|
||||
compare_node = funcdef
|
||||
if func_name == '__init__':
|
||||
if func_string_name == '__init__':
|
||||
cls = funcdef.get_parent_scope()
|
||||
if isinstance(cls, tree.Class):
|
||||
func_name = unicode(cls.name)
|
||||
func_string_name = cls.name.value
|
||||
compare_node = cls
|
||||
|
||||
found_executions = False
|
||||
i = 0
|
||||
for for_mod_context in imports.get_modules_containing_name(
|
||||
evaluator, [module_context], func_name):
|
||||
for name, trailer in get_possible_nodes(for_mod_context, func_name):
|
||||
evaluator, [module_context], func_string_name):
|
||||
if not isinstance(module_context, er.ModuleContext):
|
||||
return
|
||||
for name, trailer in _get_possible_nodes(for_mod_context, func_string_name):
|
||||
i += 1
|
||||
|
||||
# This is a simple way to stop Jedi's dynamic param recursion
|
||||
@@ -138,23 +123,79 @@ def _search_function_executions(evaluator, module_context, funcdef):
|
||||
if i * evaluator.dynamic_params_depth > MAX_PARAM_SEARCHES:
|
||||
return
|
||||
|
||||
random_context = evaluator.create_context(module_context, name)
|
||||
for value in evaluator.goto_definitions(random_context, name):
|
||||
value_node = value.get_node()
|
||||
if compare_node == value_node:
|
||||
arglist = trailer.children[1]
|
||||
if arglist == ')':
|
||||
arglist = ()
|
||||
args = TreeArguments(evaluator, random_context, arglist, trailer)
|
||||
yield er.FunctionExecutionContext(
|
||||
evaluator,
|
||||
value.parent_context,
|
||||
value_node,
|
||||
args
|
||||
)
|
||||
found_executions = True
|
||||
random_context = evaluator.create_context(for_mod_context, name)
|
||||
for function_execution in _check_name_for_execution(
|
||||
evaluator, random_context, compare_node, name, trailer):
|
||||
found_executions = True
|
||||
yield function_execution
|
||||
|
||||
# If there are results after processing a module, we're probably
|
||||
# good to process. This is a speed optimization.
|
||||
if found_executions:
|
||||
return
|
||||
|
||||
|
||||
def _get_possible_nodes(module_context, func_string_name):
|
||||
try:
|
||||
names = module_context.module_node.used_names[func_string_name]
|
||||
except KeyError:
|
||||
return
|
||||
|
||||
for name in names:
|
||||
bracket = name.get_next_leaf()
|
||||
trailer = bracket.parent
|
||||
if trailer.type == 'trailer' and bracket == '(':
|
||||
yield name, trailer
|
||||
|
||||
|
||||
def _check_name_for_execution(evaluator, context, compare_node, name, trailer):
|
||||
from jedi.evaluate import representation as er, instance
|
||||
|
||||
def create_func_excs():
|
||||
arglist = trailer.children[1]
|
||||
if arglist == ')':
|
||||
arglist = ()
|
||||
args = TreeArguments(evaluator, context, arglist, trailer)
|
||||
if value_node.type == 'funcdef':
|
||||
yield value.get_function_execution(args)
|
||||
else:
|
||||
created_instance = instance.TreeInstance(
|
||||
evaluator,
|
||||
value.parent_context,
|
||||
value,
|
||||
args
|
||||
)
|
||||
for execution in created_instance.create_init_executions():
|
||||
yield execution
|
||||
|
||||
for value in evaluator.goto_definitions(context, name):
|
||||
value_node = value.get_node()
|
||||
if compare_node == value_node:
|
||||
for func_execution in create_func_excs():
|
||||
yield func_execution
|
||||
elif isinstance(value.parent_context, er.FunctionExecutionContext) and \
|
||||
compare_node.type == 'funcdef':
|
||||
# Here we're trying to find decorators by checking the first
|
||||
# parameter. It's not very generic though. Should find a better
|
||||
# solution that also applies to nested decorators.
|
||||
params = value.parent_context.get_params()
|
||||
if len(params) != 1:
|
||||
continue
|
||||
values = params[0].infer()
|
||||
nodes = [value.get_node() for value in values]
|
||||
if nodes == [compare_node]:
|
||||
# Found a decorator.
|
||||
module_context = context.get_root_context()
|
||||
execution_context = next(create_func_excs())
|
||||
for name, trailer in _get_possible_nodes(module_context, params[0].string_name):
|
||||
if value_node.start_pos < name.start_pos < value_node.end_pos:
|
||||
random_context = evaluator.create_context(execution_context, name)
|
||||
iterator = _check_name_for_execution(
|
||||
evaluator,
|
||||
random_context,
|
||||
compare_node,
|
||||
name,
|
||||
trailer
|
||||
)
|
||||
for function_execution in iterator:
|
||||
yield function_execution
|
||||
|
||||
Reference in New Issue
Block a user