From 4e102e25e69515786fae51b74d4e5935d165aca3 Mon Sep 17 00:00:00 2001 From: David Halter Date: Sun, 17 Feb 2013 23:23:57 +0430 Subject: [PATCH] fix some of the dynamic bugs --- jedi/dynamic.py | 69 ++++++++++++++++++++++++++++-------------------- jedi/evaluate.py | 3 +-- 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/jedi/dynamic.py b/jedi/dynamic.py index 08982855..f0301d81 100644 --- a/jedi/dynamic.py +++ b/jedi/dynamic.py @@ -21,7 +21,6 @@ import parsing_representation as pr import evaluate_representation as er import modules import evaluate -import helpers import settings import debug import imports @@ -133,9 +132,7 @@ def search_params(param): for stmt in possible_stmts: if not isinstance(stmt, pr.Import): - arr = [c for c in stmt.get_commands() - if isinstance(c, pr.Statement)] - calls = _scan_array(arr, func_name) + calls = _scan_statement(stmt, func_name) for c in calls: # no execution means that params cannot be set call_path = c.generate_call_path() @@ -195,23 +192,37 @@ def check_array_additions(array): return res -def _scan_array(arr, search_name): +def _scan_statement(stmt, search_name, assignment_details=False): """ Returns the function Call that match search_name in an Array. """ - result = [] - for stmt in arr: - for s in stmt.get_commands(): - if isinstance(s, pr.Array): - result += _scan_array(s, search_name) - elif isinstance(s, pr.Call): - s_new = s - while s_new is not None: - n = s_new.name - if isinstance(n, pr.Name) and search_name in n.names: - result.append(s) + def scan_array(arr, search_name): + result = [] + if arr.type == pr.Array.DICT: + for key_stmt, value_stmt in arr.items(): + result += _scan_statement(key_stmt, search_name) + result += _scan_statement(value_stmt, search_name) + else: + for stmt in arr: + result += _scan_statement(stmt, search_name) + return result - if s_new.execution is not None: - result += _scan_array(s_new.execution, search_name) - s_new = s_new.next + result = [] + for c in stmt.get_commands(): + if isinstance(c, pr.Array): + result += scan_array(c, search_name) + elif isinstance(c, pr.Call): + s_new = c + while s_new is not None: + n = s_new.name + if isinstance(n, pr.Name) and search_name in n.names: + result.append(c) + + if s_new.execution is not None: + result += scan_array(s_new.execution, search_name) + s_new = s_new.next + + if assignment_details: + for stmt, op in stmt.assignment_details: + result += _scan_statement(stmt, search_name) return result @@ -241,7 +252,7 @@ def _check_array_additions(compare_array, module, is_list): backtrack_path = iter(call_path[:separate_index]) position = c.start_pos - scope = c.parent_stmt.parent + scope = c.get_parent_until(pr.IsScope) found = evaluate.follow_call_path(backtrack_path, scope, position) if not compare_array in found: @@ -251,16 +262,18 @@ def _check_array_additions(compare_array, module, is_list): if not params.values: continue # no params: just ignore it if add_name in ['append', 'add']: - result += evaluate.follow_call_list(params) + for param in params: + result += evaluate.follow_call_list(param.get_commands()) elif add_name in ['insert']: try: second_param = params[1] except IndexError: continue else: - result += evaluate.follow_call_list([second_param]) + result += evaluate.follow_call_list(second_param.get_comands()) elif add_name in ['extend', 'update']: - iterators = evaluate.follow_call_list(params) + for param in params: + iterators = evaluate.follow_call_list(param.get_commands()) result += evaluate.get_iterator_types(iterators) return result @@ -311,7 +324,7 @@ def _check_array_additions(compare_array, module, is_list): if evaluate.follow_statement.push_stmt(stmt): # check recursion continue - res += check_calls(_scan_array(stmt.get_commands(), n), n) + res += check_calls(_scan_statement(stmt, n), n) evaluate.follow_statement.pop_stmt() # reset settings settings.dynamic_params_for_other_modules = temp_param_add @@ -345,7 +358,7 @@ class ArrayInstance(pr.Base): for stmt in self.var_args: for typ in evaluate.follow_statement(stmt): if isinstance(typ, er.Instance) and len(typ.var_args): - array = typ.var_args[0][0] + array = typ.var_args[0] if isinstance(array, ArrayInstance): # prevent recursions # TODO compare Modules @@ -425,10 +438,8 @@ def related_names(definitions, search_name, mods): if set(f) & set(definitions): names.append(api_classes.RelatedName(name_part, stmt)) else: - calls = _scan_array(stmt.get_commands(), search_name) - for d in stmt.assignment_details: - calls += _scan_array(d[0], search_name) - for call in calls: + for call in _scan_statement(stmt, search_name, + assignment_details=True): names += check_call(call) return names diff --git a/jedi/evaluate.py b/jedi/evaluate.py index b860f60e..758524dc 100644 --- a/jedi/evaluate.py +++ b/jedi/evaluate.py @@ -555,8 +555,7 @@ def follow_statement(stmt, seek_name=None): def follow_call_list(call_list, follow_array=False): """ - The call_list has a special structure. - This can be either `pr.Array` or `list of list`. + `call_list` can be either `pr.Array` or `list of list`. It is used to evaluate a two dimensional object, that has calls, arrays and operators in it. """