diff --git a/evaluate.py b/evaluate.py index deac596b..b62a6b72 100644 --- a/evaluate.py +++ b/evaluate.py @@ -197,7 +197,6 @@ class Instance(Executable): if isinstance(var.parent, (Function, parsing.Function)): var = InstanceElement(self, var) names.append(var) - return names def get_descriptor_return(self, obj): @@ -245,6 +244,16 @@ class InstanceElement(object): scope = self.var.get_parent_until(*classes) return InstanceElement(self.instance, scope) + def get_assignment_calls(self): + # copy and modify the array + origin = self.var.get_assignment_calls() + origin.parent_stmt, temp = None, origin.parent_stmt + new = copy.deepcopy(origin) + origin.parent_stmt = temp + new.parent_stmt = InstanceElement(self.instance, temp) + #print 'gac', new, new.parent_stmt, new.parent_stmt.instance + return new + def __getattr__(self, name): return getattr(self.var, name) @@ -547,12 +556,13 @@ class Execution(Executable): if isinstance(key, parsing.Name): name = key else: + # parsing.[Call|Function|Class] lookup name = key[0].name yield name, field # normal arguments (including key arguments) else: if len(var_arg) > 1 and var_arg[1] == '=': - # this is a named parameter + # this is a named parameter (var_arg[0] is a Call) yield var_arg[0].name, var_arg[2:] else: yield None, var_arg @@ -916,6 +926,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False): # compare func uses the tuple of line/indent = row/column comparison_func = lambda name: (name.line_nr, name.indent) for scope, name_list in scope_generator: + #print scope, name_list[:9] break_scopes = [] # here is the position stuff happening (sorting of variables) for name in sorted(name_list, key=comparison_func, reverse=True): @@ -1026,7 +1037,8 @@ def follow_statement(stmt, scope=None, seek_name=None): InstanceElement) debug.dbg('follow_stmt %s in %s (%s)' % (stmt, scope, seek_name)) call_list = stmt.get_assignment_calls() - debug.dbg('calls: %s' % call_list) + debug.dbg('calls: %s' % call_list, scope) + #if isinstance(scope, InstanceElement): print 'callinst', scope.instance try: result = follow_call_list(scope, call_list) @@ -1090,6 +1102,7 @@ def follow_call_list(scope, call_list): def follow_call(scope, call): """ Follow a call is following a function, variable, string, etc. """ + scope = call.parent_stmt.parent path = call.generate_call_list() position = (call.parent_stmt.line_nr, call.parent_stmt.indent) @@ -1104,6 +1117,7 @@ def follow_call(scope, call): scopes = get_scopes_for_name(builtin.Builtin.scope, t) else: debug.warning('unknown type:', current.type, current) + scopes = [] # make instances of those number/string objects scopes = [Instance(s) for s in scopes] else: @@ -1210,7 +1224,6 @@ def follow_import(_import): def remove_star_imports(scope): """ - TODO doc """ modules = strip_imports(i for i in scope.get_imports() if i.star) new = [] diff --git a/parsing.py b/parsing.py index a8c1f9f5..ebd15504 100644 --- a/parsing.py +++ b/parsing.py @@ -633,7 +633,7 @@ class Statement(Simple): c_type = Call.NUMBER if is_chain: - call = Call(tok, c_type, self, result) + call = Call(tok, c_type, parent=result) result = result.set_next_chain_call(call) is_chain = False close_brackets = False @@ -644,17 +644,17 @@ class Statement(Simple): if result.__class__ == Call: result = result.parent close_brackets = False - call = Call(tok, c_type, self, result) + call = Call(tok, c_type, parent=result) result.add_to_current_field(call) result = call elif tok in brackets.keys(): # brackets level += 1 if is_call_or_close(): - result = Array(brackets[tok], self, result) + result = Array(brackets[tok], parent=result) result = result.parent.add_execution(result) close_brackets = False else: - result = Array(brackets[tok], self, result) + result = Array(brackets[tok], parent=result) result.parent.add_to_current_field(result) elif tok == ':': if is_call_or_close(): @@ -730,12 +730,12 @@ class Call(object): """ TODO doc """ - NAME = object() - NUMBER = object() - STRING = object() + NAME = 1 + NUMBER = 2 + STRING = 3 """ The statement object of functions, to """ - def __init__(self, name, type, parent_stmt, parent=None): + def __init__(self, name, type, parent_stmt=None, parent=None): self.name = name # parent is not the oposite of next. The parent of c: a = [b.c] would # be an array. @@ -744,7 +744,18 @@ class Call(object): self.next = None self.execution = None - self.parent_stmt = parent_stmt + self._parent_stmt = parent_stmt + + @property + def parent_stmt(self): + if self._parent_stmt: + return self._parent_stmt + else: + return self.parent.parent_stmt + + @parent_stmt.setter + def parent_stmt(self, value): + self._parent_stmt = value def set_next_chain_call(self, call): """ Adds another part of the statement""" @@ -802,7 +813,7 @@ class Array(Call): DICT = 'dict' SET = 'set' - def __init__(self, arr_type, parent_stmt, parent=None, values=None): + def __init__(self, arr_type, parent_stmt=None, parent=None, values=None): super(Array, self).__init__(None, arr_type, parent_stmt, parent) self.values = values if values else [] diff --git a/test/completion/classes.py b/test/completion/classes.py index 9b842046..3ec98dd6 100644 --- a/test/completion/classes.py +++ b/test/completion/classes.py @@ -60,7 +60,7 @@ TestClass().ret(1).real #? ['real'] inst.ret(1).real -myclass = TestClass(1, '') +myclass = TestClass(1, '', 3.0) #? int() myclass.get_first() #? [] diff --git a/test/completion/decorators.py b/test/completion/decorators.py index c1b0900d..e115f884 100644 --- a/test/completion/decorators.py +++ b/test/completion/decorators.py @@ -37,7 +37,8 @@ exe[0] exe[1] #? set exe[2] - +#? [] +exe[3][0] #? str() exe[4]['d'] @@ -50,10 +51,10 @@ exe[3][0] # ----------------- # multiple decorators # ----------------- -def dec2(func): - def wrapper(first_arg, *args, **kwargs): - return func(first_arg, *args, **kwargs) - return wrapper +def dec2(func2): + def wrapper2(first_arg, *args2, **kwargs2): + return func2(first_arg, *args2, **kwargs2) + return wrapper2 @dec2 @dec @@ -68,7 +69,8 @@ exe[0] exe[1] #? set exe[2] - +#? [] +exe[3][0] #? str() exe[4]['d']