From 259aa6bd5fa3a81091bca894002ba2f94e6a4ee0 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Mon, 17 Nov 2014 16:22:47 +0100 Subject: [PATCH] First dynamic params working. --- jedi/evaluate/__init__.py | 6 +++++- jedi/evaluate/dynamic.py | 17 +++++++++-------- jedi/evaluate/helpers.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 2ed640ec..106dbf73 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -87,7 +87,7 @@ from jedi.evaluate import finder from jedi.evaluate import compiled from jedi.evaluate import precedence from jedi.evaluate import param -from jedi.evaluate.helpers import FakeStatement, deep_ast_copy +from jedi.evaluate.helpers import FakeStatement, deep_ast_copy, call_of_name class Evaluator(object): @@ -424,6 +424,10 @@ class Evaluator(object): debug.dbg('execute result: %s in %s', types, obj) return types + def goto_definition(self, name): + call = call_of_name(name) + return self.eval_element(call) + def goto(self, stmt, call_path): if isinstance(stmt, pr.Import): # Nowhere to goto for aliases diff --git a/jedi/evaluate/dynamic.py b/jedi/evaluate/dynamic.py index 7612eb48..a7240b23 100644 --- a/jedi/evaluate/dynamic.py +++ b/jedi/evaluate/dynamic.py @@ -73,22 +73,23 @@ def search_params(evaluator, param): stmt = name.get_definition() if not isinstance(stmt, pr.ExprStmt): continue - print(stmt, stmt.start_pos, name.parent) try: trailer = name.parent.children[1] except IndexError: continue else: - types = evaluator.goto(name) + types = evaluator.goto_definition(name) - if compare in types: + # TODO why not a direct comparison? functions seem to be + # decorated in types and not in compare... + if compare.base in [t.base for t in types if hasattr(t, 'base')]: # Only if we have the correct function we execute # it, otherwise just ignore it. evaluator.eval_trailer(types, trailer) + + # TODO REMOVE continue - - calls = helpers.scan_statement_for_calls(stmt, func_name) for c in calls: # no execution means that params cannot be set @@ -115,7 +116,6 @@ def search_params(evaluator, param): if before: scopes = evaluator.eval_call_path(iter(before), c.parent, pos) pos = None - from jedi.evaluate import representation as er for scope in scopes: # Not resolving decorators is a speed hack: # By ignoring them, we get the function that is @@ -138,8 +138,8 @@ def search_params(evaluator, param): result = [] for params in get_posibilities(evaluator, module, func_name): for p in params: - if str(p) == param.name: - result += evaluator.eval_statement(p.get_definition()) + if str(p) == str(param.get_name()): + result += p.parent.eval(evaluator) return result func = param.get_parent_until(pr.Function) @@ -149,6 +149,7 @@ def search_params(evaluator, param): if func_name == '__init__' and isinstance(func.parent, pr.Class): func_name = unicode(func.parent.name) compare = func.parent + compare = er.wrap(evaluator, compare) # add the listener listener = ParamListener() diff --git a/jedi/evaluate/helpers.py b/jedi/evaluate/helpers.py index 8c64052e..28589ebd 100644 --- a/jedi/evaluate/helpers.py +++ b/jedi/evaluate/helpers.py @@ -97,6 +97,36 @@ def deep_ast_copy(obj, new_elements_default=None): return recursion(obj) +def call_of_name(name): + """ + Creates a "call" node that consist of all ``trailer`` and ``power`` + objects. E.g. if you call it with ``append``:: + + list([]).append(3) or None + + You would get a node with the content ``list([]).append`` back. + + This generates a copy of the original ast node. + """ + par = name + if pr.is_node(par.parent, 'trailer'): + par = par.parent + + power = par.parent + if pr.is_node(power, 'power') and power.children[0] != name \ + and not (power.children[-2] == '**' and + name.start_pos > power.children[-1].start_pos): + par = power + # Now the name must be part of a trailer + index = par.children.index(name.parent) + if index != len(par.children) - 1: + # Now we have to cut the other trailers away. + par = deep_ast_copy(par) + par.children[index + 1:] = [] + + return par + + def call_signature_array_for_pos(stmt, pos): """ Searches for the array and position of a tuple.