1
0
forked from VimPlug/jedi

fix list comprehensions. they were not implemented in a good way

This commit is contained in:
Dave Halter
2014-06-12 11:10:10 +02:00
parent f8b79b3dd0
commit d5758adb2b
4 changed files with 13 additions and 40 deletions

View File

@@ -192,10 +192,6 @@ class Evaluator(object):
next(call_path, None) # the first one has been used already next(call_path, None) # the first one has been used already
return self.follow_path(call_path, r, element.parent) return self.follow_path(call_path, r, element.parent)
elif isinstance(element, pr.ListComprehension): elif isinstance(element, pr.ListComprehension):
#lc = element.get_most_inner_lc()
# Caveat: parents are being changed, but this doesn't matter,
# because nothing else uses it.
#element.stmt.parent = loop
return self.eval_statement(element.stmt) return self.eval_statement(element.stmt)
elif isinstance(element, pr.Lambda): elif isinstance(element, pr.Lambda):
return [er.Function(self, element)] return [er.Function(self, element)]

View File

@@ -470,8 +470,8 @@ def get_names_of_scope(evaluator, scope, position=None, star_search=True, includ
:rtype: [(pr.Scope, [pr.Name])] :rtype: [(pr.Scope, [pr.Name])]
:return: Return an generator that yields a pair of scope and names. :return: Return an generator that yields a pair of scope and names.
""" """
if isinstance(scope, iterable.ListComprehensionFlow): if isinstance(scope, pr.ListComprehension):
position = scope.list_comprehension.parent.start_pos position = scope.parent.start_pos
in_func_scope = scope in_func_scope = scope
non_flow = scope.get_parent_until(pr.Flow, reverse=True) non_flow = scope.get_parent_until(pr.Flow, reverse=True)
@@ -497,7 +497,7 @@ def get_names_of_scope(evaluator, scope, position=None, star_search=True, includ
yield scope, _get_defined_names_for_position(scope, position, in_func_scope) yield scope, _get_defined_names_for_position(scope, position, in_func_scope)
except StopIteration: except StopIteration:
reraise(common.MultiLevelStopIteration, sys.exc_info()[2]) reraise(common.MultiLevelStopIteration, sys.exc_info()[2])
if scope.isinstance(iterable.ListComprehensionFlow): if scope.isinstance(pr.ListComprehension):
# is a list comprehension # is a list comprehension
yield scope, scope.get_defined_names(is_internal_call=True) yield scope, scope.get_defined_names(is_internal_call=True)

View File

@@ -88,7 +88,7 @@ class _RecursionNode(object):
if not other: if not other:
return None return None
is_list_comp = lambda x: isinstance(x, iterable.ListComprehensionFlow) is_list_comp = lambda x: isinstance(x, pr.ListComprehension)
return self.script == other.script \ return self.script == other.script \
and self.position == other.position \ and self.position == other.position \
and not is_list_comp(self.stmt.parent) \ and not is_list_comp(self.stmt.parent) \

View File

@@ -1483,20 +1483,22 @@ class Name(Simple):
class ListComprehension(ForFlow): class ListComprehension(ForFlow):
""" Helper class for list comprehensions """ """ Helper class for list comprehensions """
def __init__(self, module, stmt, middle, input, parent): def __init__(self, module, stmt, middle, input, parent):
self.stmt = stmt
self.middle = middle
self.input = input self.input = input
for s in middle, input:
s.parent = self
stmt.parent = self._get_most_inner_lc()
self.parent = parent
nested_lc = input.expression_list()[0] nested_lc = input.expression_list()[0]
if isinstance(nested_lc, ListComprehension): if isinstance(nested_lc, ListComprehension):
# is nested LC # is nested LC
input = nested_lc.stmt input = nested_lc.stmt
nested_lc.parent = self
super(ListComprehension, self).__init__(module, [input], super(ListComprehension, self).__init__(module, [input],
stmt.start_pos, middle) stmt.start_pos, middle)
self.parent = parent
self.stmt = stmt
self.middle = middle
for s in middle, input:
s.parent = self
# The stmt always refers to the most inner list comprehension.
stmt.parent = self._get_most_inner_lc()
def _get_most_inner_lc(self): def _get_most_inner_lc(self):
nested_lc = self.input.expression_list()[0] nested_lc = self.input.expression_list()[0]
@@ -1517,31 +1519,6 @@ class ListComprehension(ForFlow):
return "%s for %s in %s" % tuple(code) return "%s for %s in %s" % tuple(code)
def _evaluate_list_comprehension(lc, parent=None):
# create a for loop, which does the same as list comprehensions
input = lc.input
nested_lc = input.expression_list()[0]
if isinstance(nested_lc, ListComprehension):
# is nested LC
input = nested_lc.stmt
loop = ListComprehensionFlow(lc, input, parent)
if isinstance(nested_lc, ListComprehension):
loop = _evaluate_list_comprehension(nested_lc, loop)
return loop
class ListComprehensionFlow(ForFlow):
"""Fake implementation to pretend being a ForFlow."""
def __init__(self, list_comprehension, input, parent):
lc = list_comprehension
sup = super(ListComprehensionFlow, self)
module = list_comprehension.get_parent_until()
sup.__init__(module, [input], lc.parent.start_pos, lc.middle)
self.parent = parent or lc.get_parent_until(IsScope)
self.list_comprehension = list_comprehension
class Operator(Base): class Operator(Base):
__slots__ = ('string', '_line', '_column') __slots__ = ('string', '_line', '_column')