forked from VimPlug/jedi
nested list comprehensions are working + tests
This commit is contained in:
40
evaluate.py
40
evaluate.py
@@ -856,8 +856,6 @@ def get_names_for_scope(scope, position=None, star_search=True,
|
|||||||
"""
|
"""
|
||||||
start_scope = scope
|
start_scope = scope
|
||||||
in_scope = scope
|
in_scope = scope
|
||||||
if isinstance(start_scope, parsing.ForFlow) and start_scope.is_list_comp:
|
|
||||||
yield start_scope, start_scope.get_set_vars(is_internal_call=True)
|
|
||||||
while scope:
|
while scope:
|
||||||
# `parsing.Class` is used, because the parent is never `Class`.
|
# `parsing.Class` is used, because the parent is never `Class`.
|
||||||
# Ignore the Flows, because the classes and functions care for that.
|
# Ignore the Flows, because the classes and functions care for that.
|
||||||
@@ -869,6 +867,9 @@ def get_names_for_scope(scope, position=None, star_search=True,
|
|||||||
in_scope)
|
in_scope)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
raise MultiLevelStopIteration('StopIteration raised somewhere')
|
raise MultiLevelStopIteration('StopIteration raised somewhere')
|
||||||
|
if isinstance(scope, parsing.ForFlow) and scope.is_list_comp:
|
||||||
|
yield scope, scope.get_set_vars(is_internal_call=True)
|
||||||
|
|
||||||
scope = scope.parent()
|
scope = scope.parent()
|
||||||
# This is used, because subscopes (Flow scopes) would distort the
|
# This is used, because subscopes (Flow scopes) would distort the
|
||||||
# results.
|
# results.
|
||||||
@@ -1179,9 +1180,23 @@ def follow_call_list(call_list):
|
|||||||
It is used to evaluate a two dimensional object, that has calls, arrays and
|
It is used to evaluate a two dimensional object, that has calls, arrays and
|
||||||
operators in it.
|
operators in it.
|
||||||
"""
|
"""
|
||||||
def evaluate_list_comprehension(self, call_list):
|
def evaluate_list_comprehension(lc, parent=None):
|
||||||
for a in call_list:
|
input = lc.input
|
||||||
pass
|
nested_lc = lc.input.token_list[0]
|
||||||
|
if isinstance(nested_lc, parsing.ListComprehension):
|
||||||
|
# is nested LC
|
||||||
|
input = nested_lc.stmt
|
||||||
|
loop = parsing.ForFlow([input], lc.stmt.start_pos,
|
||||||
|
lc.middle, True)
|
||||||
|
if parent is None:
|
||||||
|
loop.parent = weakref.ref(lc.stmt.parent())
|
||||||
|
else:
|
||||||
|
loop.parent = lambda: parent
|
||||||
|
|
||||||
|
if isinstance(nested_lc, parsing.ListComprehension):
|
||||||
|
loop = evaluate_list_comprehension(nested_lc, loop)
|
||||||
|
return loop
|
||||||
|
|
||||||
if parsing.Array.is_type(call_list, parsing.Array.TUPLE,
|
if parsing.Array.is_type(call_list, parsing.Array.TUPLE,
|
||||||
parsing.Array.DICT):
|
parsing.Array.DICT):
|
||||||
# Tuples can stand just alone without any braces. These would be
|
# Tuples can stand just alone without any braces. These would be
|
||||||
@@ -1195,14 +1210,11 @@ def follow_call_list(call_list):
|
|||||||
if parsing.Array.is_type(call, parsing.Array.NOARRAY):
|
if parsing.Array.is_type(call, parsing.Array.NOARRAY):
|
||||||
result += follow_call_list(call)
|
result += follow_call_list(call)
|
||||||
elif isinstance(call, parsing.ListComprehension):
|
elif isinstance(call, parsing.ListComprehension):
|
||||||
stmt = call.stmt
|
loop = evaluate_list_comprehension(call)
|
||||||
|
stmt = copy.copy(call.stmt)
|
||||||
|
stmt.parent = lambda: loop
|
||||||
# create a for loop which does the same as list
|
# create a for loop which does the same as list
|
||||||
# comprehensions
|
# comprehensions
|
||||||
loop = parsing.ForFlow([call.input], stmt.start_pos,
|
|
||||||
call.middle, True)
|
|
||||||
loop.parent = weakref.ref(stmt.parent())
|
|
||||||
stmt = copy.copy(stmt)
|
|
||||||
stmt.parent = lambda: loop
|
|
||||||
result += follow_statement(stmt)
|
result += follow_statement(stmt)
|
||||||
else:
|
else:
|
||||||
if isinstance(call, (Function, Class, Instance,
|
if isinstance(call, (Function, Class, Instance,
|
||||||
@@ -1267,11 +1279,7 @@ def follow_call_path(path, scope, position):
|
|||||||
# Reset the position, when imports where stripped.
|
# Reset the position, when imports where stripped.
|
||||||
position = None
|
position = None
|
||||||
|
|
||||||
debug.dbg('before next follow %s, current "%s", scope %s'
|
return follow_paths(path, result, position=position)
|
||||||
% (result, current, scope))
|
|
||||||
result = follow_paths(path, result, position=position)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def follow_paths(path, results, position=None):
|
def follow_paths(path, results, position=None):
|
||||||
|
|||||||
@@ -66,6 +66,10 @@ a = [a for a in [1]]
|
|||||||
#? int()
|
#? int()
|
||||||
a[0]
|
a[0]
|
||||||
|
|
||||||
|
a = [a for a in 1,2]
|
||||||
|
#? int()
|
||||||
|
a[0]
|
||||||
|
|
||||||
a = [a for a,b in [(1,'')]]
|
a = [a for a,b in [(1,'')]]
|
||||||
#? int()
|
#? int()
|
||||||
a[0]
|
a[0]
|
||||||
@@ -75,6 +79,26 @@ a = [a for a in arr]
|
|||||||
#? int() str()
|
#? int() str()
|
||||||
a[0]
|
a[0]
|
||||||
|
|
||||||
|
a = [a if 1.0 else '' for a in [1] if [1.0]]
|
||||||
|
#? int() str()
|
||||||
|
a[0]
|
||||||
|
|
||||||
|
# -----------------
|
||||||
|
# nested list comprehensions
|
||||||
|
# -----------------
|
||||||
|
|
||||||
|
b = [a for arr in [[1]] for a in arr]
|
||||||
|
#? int()
|
||||||
|
b[0]
|
||||||
|
|
||||||
|
b = [a for arr in [[1]] if '' for a in arr if '']
|
||||||
|
#? int()
|
||||||
|
b[0]
|
||||||
|
|
||||||
|
b = [b for arr in [[[1.0]]] for a in arr for b in a]
|
||||||
|
#? float()
|
||||||
|
b[0]
|
||||||
|
|
||||||
# -----------------
|
# -----------------
|
||||||
# ternary operator
|
# ternary operator
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|||||||
Reference in New Issue
Block a user