1
0
forked from VimPlug/jedi

working list comprehensions with tests.

This commit is contained in:
David Halter
2012-08-27 17:52:16 +02:00
parent 5d6e30c6ab
commit 6e59e96f78
3 changed files with 47 additions and 17 deletions

View File

@@ -856,6 +856,8 @@ 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.
@@ -1192,18 +1194,24 @@ def follow_call_list(call_list):
for call in calls_iterator: for call in calls_iterator:
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):
stmt = call.stmt
# create a for loop which does the same as list
# 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)
else: else:
# With things like params, these can also be functions...
if isinstance(call, (Function, Class, Instance, if isinstance(call, (Function, Class, Instance,
dynamic.ArrayInstance)): dynamic.ArrayInstance)):
# With things like params, these can also be functions...
result.append(call) result.append(call)
# The string tokens are just operations (+, -, etc.) # The string tokens are just operations (+, -, etc.)
elif not isinstance(call, str): elif not isinstance(call, str):
if str(call.name) == 'for': if str(call.name) == 'if':
# list comprehensions
print '\n\ndini mueter', call_list
return []
elif str(call.name) == 'if':
# Ternary operators. # Ternary operators.
while True: while True:
try: try:

View File

@@ -479,10 +479,11 @@ class ForFlow(Flow):
""" """
Used for the for loop, because there are two statement parts. Used for the for loop, because there are two statement parts.
""" """
def __init__(self, command, inits, start_pos, set_stmt): def __init__(self, inits, start_pos, set_stmt, is_list_comp=False):
super(ForFlow, self).__init__(command, inits, start_pos, super(ForFlow, self).__init__('for', inits, start_pos,
set_stmt.used_vars) set_stmt.used_vars)
self.set_stmt = set_stmt self.set_stmt = set_stmt
self.is_list_comp = is_list_comp
class Import(Simple): class Import(Simple):
@@ -664,6 +665,9 @@ class Statement(Simple):
tok_iter = enumerate(self.token_list) tok_iter = enumerate(self.token_list)
for i, tok_temp in tok_iter: for i, tok_temp in tok_iter:
#print 'tok', tok_temp, result #print 'tok', tok_temp, result
if isinstance(tok_temp, ListComprehension):
result.add_to_current_field(tok_temp)
continue
try: try:
token_type, tok, start_pos = tok_temp token_type, tok, start_pos = tok_temp
except TypeError: except TypeError:
@@ -1006,14 +1010,14 @@ class Name(Simple):
class ListComprehension(object): class ListComprehension(object):
""" Helper class for list comprehensions """ """ Helper class for list comprehensions """
def __init__(self, tok_list, middle, input): def __init__(self, stmt, middle, input):
self.tok_list = tok_list self.stmt = stmt
self.middle = middle self.middle = middle
self.input = input self.input = input
def __repr__(self): def __repr__(self):
return "<%s: %s for in %s>" % \ return "<%s: %s for %s in %s>" % \
(self.__class__.__name__, self.tok_list, self.input) (self.__class__.__name__, self.stmt, self.middle, self.input)
@@ -1322,7 +1326,9 @@ class PyFuzzyParser(object):
(tok, self.start_pos[0])) (tok, self.start_pos[0]))
continue continue
other_level = 0 other_level = 0
for i, (d1, tok, d2) in enumerate(reversed(tok_list)): for i, tok in enumerate(reversed(tok_list)):
if not isinstance(tok, Name):
tok = tok[1]
if tok in closing_brackets: if tok in closing_brackets:
other_level -= 1 other_level -= 1
elif tok in opening_brackets: elif tok in opening_brackets:
@@ -1333,7 +1339,11 @@ class PyFuzzyParser(object):
i = 0 # could not detect brackets -> nested list comp i = 0 # could not detect brackets -> nested list comp
tok_list, toks = tok_list[:-i], tok_list[-i:-1] tok_list, toks = tok_list[:-i], tok_list[-i:-1]
tok_list.append(ListComprehension(toks, middle, in_clause)) st = Statement('', [], [], [], \
toks, first_pos, self.end_pos)
for s in [st, middle, in_clause]:
s.parent = weakref.ref(self.scope)
tok_list.append(ListComprehension(st, middle, in_clause))
print tok_list print tok_list
elif tok in ['print', 'exec']: elif tok in ['print', 'exec']:
# TODO they should be reinstated, since the goal of the # TODO they should be reinstated, since the goal of the
@@ -1399,7 +1409,6 @@ class PyFuzzyParser(object):
if list_comp: if list_comp:
self.gen.push_back(self._current_full) self.gen.push_back(self._current_full)
return stmt, tok return stmt, tok
def next(self): def next(self):
@@ -1522,7 +1531,7 @@ class PyFuzzyParser(object):
if tok == 'in': if tok == 'in':
statement, tok = self._parse_statement() statement, tok = self._parse_statement()
if tok == ':': if tok == ':':
f = ForFlow('for', [statement], first_pos, f = ForFlow([statement], first_pos,
set_stmt) set_stmt)
self.scope = self.scope.add_statement(f) self.scope = self.scope.add_statement(f)

View File

@@ -56,11 +56,24 @@ for i in range(10):
# list comprehensions # list comprehensions
# ----------------- # -----------------
a = ['' for abc in [1]] # basics:
a = ['' for a in [1]]
#? str() #? str()
a[0] a[0]
a = [a for a in [1]]
#? int()
a[0]
a = [a for a,b in [(1,'')]]
#? int()
a[0]
arr = [1,'']
a = [a for a in arr]
#? int() str()
a[0]
# ----------------- # -----------------
# ternary operator # ternary operator