From 89ab0ba137d4b040598455927506fceb86f442ca Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Fri, 15 Aug 2014 01:55:43 +0200 Subject: [PATCH] Fix fast_parent_copy. The caching is now more solid than before (and doesn't produce weird side effects. This also solves an issue with Lambdas. However, by fixing all of this we have broken some other things. --- jedi/evaluate/finder.py | 7 ++++++- jedi/evaluate/helpers.py | 8 ++++++-- jedi/evaluate/representation.py | 1 + jedi/parser/representation.py | 7 +++---- test/completion/lambdas.py | 9 +++++++++ 5 files changed, 25 insertions(+), 7 deletions(-) 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) # -----------------