diff --git a/jedi/evaluate/dynamic.py b/jedi/evaluate/dynamic.py index d91a26a1..9e8d5714 100644 --- a/jedi/evaluate/dynamic.py +++ b/jedi/evaluate/dynamic.py @@ -73,14 +73,21 @@ def search_params(evaluator, execution_context, funcdef): # you will see the slowdown, especially in 3.6. return create_default_params(execution_context, funcdef) - debug.dbg('Dynamic param search in %s.', funcdef.name.value, color='MAGENTA') + if funcdef.type == 'lambdef': + string_name = _get_lambda_name(funcdef) + if string_name is None: + return create_default_params(execution_context, funcdef) + else: + string_name = funcdef.name.value + debug.dbg('Dynamic param search in %s.', string_name, color='MAGENTA') try: module_context = execution_context.get_root_context() function_executions = _search_function_executions( evaluator, module_context, - funcdef + funcdef, + string_name=string_name, ) if function_executions: zipped_params = zip(*list( @@ -100,25 +107,24 @@ def search_params(evaluator, execution_context, funcdef): @evaluator_function_cache(default=None) @to_list -def _search_function_executions(evaluator, module_context, funcdef): +def _search_function_executions(evaluator, module_context, funcdef, string_name): """ Returns a list of param names. """ - func_string_name = funcdef.name.value compare_node = funcdef - if func_string_name == '__init__': + if string_name == '__init__': cls = get_parent_scope(funcdef) if isinstance(cls, tree.Class): - func_string_name = cls.name.value + 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_string_name): + evaluator, [module_context], string_name): if not isinstance(module_context, ModuleContext): return - for name, trailer in _get_possible_nodes(for_mod_context, func_string_name): + for name, trailer in _get_possible_nodes(for_mod_context, string_name): i += 1 # This is a simple way to stop Jedi's dynamic param recursion @@ -139,6 +145,18 @@ def _search_function_executions(evaluator, module_context, funcdef): return +def _get_lambda_name(node): + stmt = node.parent + if stmt.type == 'expr_stmt': + first_operator = next(stmt.yield_operators(), None) + if first_operator == '=': + first = stmt.children[0] + if first.type == 'name': + return first.value + + return None + + def _get_possible_nodes(module_context, func_string_name): try: names = module_context.tree_node.get_used_names()[func_string_name] @@ -160,9 +178,7 @@ def _check_name_for_execution(evaluator, context, compare_node, name, trailer): if arglist == ')': arglist = None args = TreeArguments(evaluator, context, arglist, trailer) - if value_node.type == 'funcdef': - yield value.get_function_execution(args) - else: + if value_node.type == 'classdef': created_instance = instance.TreeInstance( evaluator, value.parent_context, @@ -171,6 +187,8 @@ def _check_name_for_execution(evaluator, context, compare_node, name, trailer): ) for execution in created_instance.create_init_executions(): yield execution + else: + yield value.get_function_execution(args) for value in evaluator.goto_definitions(context, name): value_node = value.tree_node diff --git a/test/completion/dynamic_params.py b/test/completion/dynamic_params.py index 8af1730c..6d513f44 100644 --- a/test/completion/dynamic_params.py +++ b/test/completion/dynamic_params.py @@ -132,3 +132,19 @@ def from_comprehension(foo): [from_comprehension(1.0) for n in (1,)] [from_comprehension(n) for n in (1,)] + +# ----------------- +# lambdas +# ----------------- + +#? int() +x_lambda = lambda x: x + +x_lambda(1) + +class X(): + #? str() + x_method = lambda self, a: a + + +X().x_method('')