diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 0ee0a491..d6c1a66e 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -92,8 +92,13 @@ class NameFinder(object): # Exclude `arr[1] =` from the result set. if not self._name_is_array_assignment(name): + # TODO we ignore a lot of elements here that should not be + # ignored. But then again flow_analysis also stops when the + # input scope is reached. This is not correct: variables + # might still have conditions if defined outside of the + # current scope. if isinstance(stmt, (pr.Param, pr.Import)) \ - or isinstance(name_list_scope, (pr.ListComprehension, er.Instance, InterpreterNamespace)) \ + or isinstance(name_list_scope, (pr.Lambda, pr.ListComprehension, er.Instance, InterpreterNamespace)) \ or isinstance(scope, compiled.CompiledObject) \ or isinstance(stmt, pr.Statement) and stmt.is_global(): # Always reachable. diff --git a/jedi/evaluate/helpers.py b/jedi/evaluate/helpers.py index e33dcb19..c4169146 100644 --- a/jedi/evaluate/helpers.py +++ b/jedi/evaluate/helpers.py @@ -11,6 +11,7 @@ def fast_parent_copy(obj): """ new_elements = {} accept = (pr.Simple, pr.NamePart) + start=obj def recursion(obj): if isinstance(obj, pr.Statement): @@ -48,7 +49,7 @@ def fast_parent_copy(obj): elif isinstance(value, (list, tuple)): setattr(new_obj, key, list_or_tuple_rec(value)) elif isinstance(value, accept): - try: # because of the circular Flow.previous/Flow.next + try: setattr(new_obj, key, new_elements[value]) except KeyError: setattr(new_obj, key, recursion(value)) @@ -61,7 +62,10 @@ def fast_parent_copy(obj): copied_array = array_obj[:] # lists, tuples, strings, unicode for i, el in enumerate(copied_array): if isinstance(el, accept): - copied_array[i] = recursion(el) + try: + copied_array[i] = new_elements[el] + except KeyError: + copied_array[i] = recursion(el) elif isinstance(el, (tuple, list)): copied_array[i] = list_or_tuple_rec(el) diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index 959e7d9f..56aa391e 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -551,6 +551,7 @@ class FunctionExecution(Executed): else: copied = helpers.fast_parent_copy(element) copied.parent = self._scope_copy(copied.parent) + # TODO remove? Doesn't make sense, at least explain. if isinstance(copied, pr.Function): copied = Function(self._evaluator, copied) objects.append(copied) diff --git a/jedi/parser/representation.py b/jedi/parser/representation.py index 434f4cc6..0529cacf 100644 --- a/jedi/parser/representation.py +++ b/jedi/parser/representation.py @@ -1107,8 +1107,7 @@ class Statement(Simple, DocstringMixin): return None, tok # Since Lambda is a Function scope, it needs Scope parents. - parent = self.get_parent_scope() - lambd = Lambda(self._sub_module, params, start_pos, parent) + lambd = Lambda(self._sub_module, params, start_pos, self) ret, tok = parse_stmt(token_iterator) if ret is not None: @@ -1278,7 +1277,7 @@ class StatementElement(Simple): def set_next(self, call): """ Adds another part of the statement""" - call.parent = self + call.parent = self.parent if self.next is not None: self.next.set_next(call) else: @@ -1289,7 +1288,7 @@ class StatementElement(Simple): An execution is nothing else than brackets, with params in them, which shows access on the internals of this name. """ - call.parent = self + call.parent = self.parent if self.next is not None: self.next.set_execution(call) elif self.execution is not None: diff --git a/test/completion/lambdas.py b/test/completion/lambdas.py index ce617d44..429bbbba 100644 --- a/test/completion/lambdas.py +++ b/test/completion/lambdas.py @@ -61,6 +61,15 @@ class C(): C().a() +def xy(param): + def ret(a, b): + return a + b + + return lambda b: ret(param, b) + +#? int() +xy(1)(2) + # ----------------- # lambda param (#379) # -----------------