1
0
forked from VimPlug/jedi

catched recursions in a special array case

This commit is contained in:
David Halter
2012-08-22 15:14:36 +02:00
parent d85184d387
commit b844fa201a
3 changed files with 86 additions and 38 deletions

View File

@@ -156,25 +156,27 @@ def _check_array_additions(compare_array, module, is_list):
scope = c.parent_stmt().parent()
found = evaluate.follow_call_path(backtrack_path, scope, position)
if not compare_array in found:
# the `append`, etc. belong to other arrays
# Check if the original scope is an execution. If it is, one
# can search for the same statement, that is in the module
# dict. Executions are somewhat special in jedi, since they
# literally copy the contents of a function.
if isinstance(comp_arr_parent, evaluate.Execution):
found_bases = []
for f in found:
base = get_execution_parent(f, parsing.Function)
found_bases.append(base)
#for f in found_bases:
#print 'adsf', c.start_pos, found, found_bases
if comp_arr_parent.base.base_func in found_bases:
stmt = comp_arr_parent. \
get_statement_for_position(c.start_pos)
if stmt is not None:
#print 'LA', stmt.parent(), stmt
if evaluate.follow_statement.push_stmt(stmt):
# check recursion
continue
ass = stmt.get_assignment_calls()
result += check_calls(scan_array(ass, add_name),
add_name)
#print found_bases, comp_arr_parent.base.base_func
#print found, found[0]._array.parent_stmt().parent()
#print compare_array_parent.base
new_calls = scan_array(ass, add_name)
#print [c.start_pos for c in new_calls], stmt.start_pos
result += check_calls(new_calls, add_name)
evaluate.follow_statement.pop_stmt()
continue
params = call_path[separate_index + 1]
@@ -204,9 +206,7 @@ def _check_array_additions(compare_array, module, is_list):
search_names = ['append', 'extend', 'insert'] if is_list else \
['add', 'update']
#print compare_array
comp_arr_parent = get_execution_parent(compare_array, evaluate.Execution)
#print 'par', comp_arr_parent
possible_stmts = []
result = []
for n in search_names:
@@ -246,6 +246,9 @@ class ArrayInstance(parsing.Base):
items = []
#print 'ic', self.var_args, self.var_args.parent_stmt()
stmt = self.var_args.parent_stmt()
#if evaluate.follow_statement.push_stmt(stmt):
# check recursion
#return []
#if stmt.get_parent_until() == builtin.Builtin.scope:
#evaluate.follow_statement.push(stmt)
for array in evaluate.follow_call_list(self.var_args):
@@ -255,11 +258,15 @@ class ArrayInstance(parsing.Base):
#print items, self, id(self.var_args), id(self.var_args.parent_stmt()), array
# prevent recursions
# TODO compare Modules
#if evaluate.follow_statement.push_stmt(stmt):
# check recursion
# continue
if self.var_args.start_pos != temp.var_args.start_pos:
items += temp.iter_content()
else:
debug.warning('ArrayInstance recursion', self.var_args)
print 'yippie'
#evaluate.follow_statement.pop_stmt()
continue
items += evaluate.get_iterator_types([array])
@@ -269,4 +276,5 @@ class ArrayInstance(parsing.Base):
module = self.var_args.parent_stmt().get_parent_until()
is_list = str(self.instance.name) == 'list'
items += _check_array_additions(self.instance, module, is_list)
#evaluate.follow_statement.pop_stmt()
return items

View File

@@ -15,51 +15,64 @@ class RecursionDecorator(object):
self.current = None
def __call__(self, stmt, *args, **kwargs):
r = RecursionNode(stmt, self.current)
# Don't check param instances, they are not causing recursions
# The same's true for the builtins, because the builtins are really
# simple.
if isinstance(stmt, parsing.Param) \
or (r.script == builtin.Builtin.scope and
stmt.start_pos[0] != 538000):
return self.func(stmt, *args, **kwargs)
if r.script == builtin.Builtin.scope:
print 'rec_catch', stmt, stmt.parent().parent()
#print stmt
if self._check_recursion(r):
debug.warning('catched recursion', stmt, args, kwargs)
if self.push_stmt(stmt):
return []
parent, self.current = self.current, r
else:
result = self.func(stmt, *args, **kwargs)
self.current = parent
self.pop_stmt()
return result
def _check_recursion(self, new):
def push_stmt(self, stmt):
self.current = RecursionNode(stmt, self.current)
if self._check_recursion():
debug.warning('catched recursion', stmt)
self.pop_stmt()
return True
return False
def pop_stmt(self):
self.current = self.current.parent
def _check_recursion(self):
test = self.current
while True:
if new == test:
test = test.parent
if self.current == test:
return True
if not test:
return False
test = test.parent
def reset(self):
self.top = None
self.current = None
def node_statements(self):
result = []
n = self.current
while n:
result.append(n.stmt)
n = n.parent
return result
class RecursionNode(object):
def __init__(self, stmt, parent):
self.script = stmt.get_parent_until()
self.position = stmt.start_pos
self.parent = parent
self.stmt = stmt
# Don't check param instances, they are not causing recursions
# The same's true for the builtins, because the builtins are really
# simple.
self.is_ignored = isinstance(stmt, parsing.Param) \
or (self.script == builtin.Builtin.scope)
def __eq__(self, other):
if not other:
return None
return self.script == other.script and self.position == other.position
return self.script == other.script \
and self.position == other.position and not self.is_ignored
def fast_parent_copy(obj):

View File

@@ -299,6 +299,28 @@ def blub():
#? int()
blub()[0]
# -----------------
# returns, the same for classes
# -----------------
class C():
def blub(self, b):
if 1:
a = []
a.append(b)
return a
def blub2(self):
""" mapper function """
a = self.blub(1.0)
#? float()
a[0]
return a
#? int()
C().blub(1)[0]
#? float()
C().blub2(1)[0]
# -----------------
# array recursions
@@ -314,15 +336,20 @@ list(a)[0]
def first(a):
b = []
b.append(a)
#b.extend(second(a))
return b
b.extend(second(a))
return list(b)
def second(a):
b = []
b.append(a)
b.extend(first(a))
b.extend(second(a))
return list(b)
#? float()
first(1.0)[0]
def third():
b = []
b.extend(first())
return list(b)
#?
third()[0]