diff --git a/evaluate.py b/evaluate.py index 5ad23ca6..f6159f92 100644 --- a/evaluate.py +++ b/evaluate.py @@ -149,6 +149,9 @@ class Instance(Executable): self.execute_subscope_by_name('__init__', self.var_args) except KeyError: pass + # Generated instances are classes that are just generated by self + # (No var_args) used. + self.is_generated = False @memoize_default() def get_init_execution(self, func): @@ -911,12 +914,22 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False): str(token_name)) else: # generated objects are used within executions, where - if isinstance(r, parsing.Param) and not r.is_generated: - res_new += dynamic.search_params(r) - if not r.assignment_details: - # this means that there are no default params, so - # just ignore it. - continue + if isinstance(r, parsing.Param): + func = r.parent() + # Instances are typically faked, if the instance is not + # called from outside. Here we check it for __init__ + # functions and return + if isinstance(func, InstanceElement) \ + and func.instance.is_generated \ + and str(func.name) == '__init__' \ + and r.position_nr > 0: # 0 would be self + r = func.var.params[r.position_nr] + if not r.is_generated: + res_new += dynamic.search_params(r) + if not r.assignment_details: + # this means that there are no default params, + # so just ignore it. + continue scopes = follow_statement(r, seek_name=name_str) res_new += remove_statements(scopes) @@ -958,7 +971,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False): elif isinstance(par, parsing.Param) \ and par.parent() is not None \ and isinstance(par.parent().parent(), parsing.Class) \ - and par.position == 0: + and par.position_nr == 0: # This is where self gets added - this happens at another # place, if the var_args are clear. But sometimes the class is # not known. Therefore add a new instance for self. Otherwise @@ -967,6 +980,7 @@ def get_scopes_for_name(scope, name_str, position=None, search_global=False): inst = scope.instance else: inst = Instance(Class(par.parent().parent())) + inst.is_generated = True result.append(inst) else: result.append(par) diff --git a/parsing.py b/parsing.py index 5660a678..6bd13339 100644 --- a/parsing.py +++ b/parsing.py @@ -732,7 +732,7 @@ class Param(Statement): # this is defined by the parser later on, not at the initialization # it is the position in the call (first argument, second...) - self.position = None + self.position_nr = None self.is_generated = False def get_name(self): @@ -1091,7 +1091,7 @@ class PyFuzzyParser(object): stmt, tok = self._parse_statement(added_breaks=',', stmt_class=Param) if stmt: - stmt.position = pos + stmt.position_nr = pos names.append(stmt) pos += 1 diff --git a/test/completion/dynamic.py b/test/completion/dynamic.py index 24dac2e5..e3a5807b 100644 --- a/test/completion/dynamic.py +++ b/test/completion/dynamic.py @@ -79,10 +79,17 @@ class A(): def test(self, a): #? float() a + self.c = self.test2() def test2(self): - ##? int() - self.a + #? int() + return self.a + + def test3(self): + #? int() + self.test2() + #? int() + self.c A(3).test(2.0) A(3).test2() @@ -223,5 +230,5 @@ def add_to_arr(arr, a): return arr a = [1.0] -#? float() int() +##? float() int() add_to_arr(a, 1)[0]