From 0f012429545acf9c185126021080d39d99901eb3 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Mon, 8 Dec 2014 01:52:32 +0100 Subject: [PATCH] named param goto. --- jedi/api/classes.py | 9 +++++++++ jedi/evaluate/__init__.py | 28 +++++++++++++++++++++++++--- jedi/evaluate/helpers.py | 28 +--------------------------- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/jedi/api/classes.py b/jedi/api/classes.py index 2d11ef36..4218d4b1 100644 --- a/jedi/api/classes.py +++ b/jedi/api/classes.py @@ -314,6 +314,11 @@ class BaseDefinition(object): return '.'.join(path if path[0] else path[1:]) def goto_assignments(self): + defs = self._evaluator.goto(self._name) + return [Definition(self._evaluator, d) for d in defs] + + + # TODO REMOVE! def call_path_for_name_part(stmt_or_imp, name_part): if isinstance(stmt_or_imp, pr.Import): return [name_part] @@ -636,6 +641,10 @@ class Definition(use_metaclass(CachedMetaClass, BaseDefinition)): Returns True, if defined as a name in a statement, function or class. Returns False, if it's a reference to such a definition. """ + return self._name.is_definition() + + + # TODO REMOVE this. _def = self._name.get_parent_until((pr.ExprStmt, pr.Import, pr.Function, pr.Class, pr.Module)) if isinstance(_def, pr.ExprStmt): diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index d797aa12..a3b8eef3 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -468,10 +468,32 @@ class Evaluator(object): yield name stmt = name.get_definition() - # Only take the parent, because if it's more complicated than just a - # name it's something you can "goto" again. par = name.parent - if isinstance(par, pr.ExprStmt) and name in par.get_defined_names(): + if par.type == 'argument' and par.children[1] == '=' and par.children[0] == name: + # Named param goto. + trailer = par.parent + if trailer.type == 'arglist': + trailer = trailer.parent + if trailer.type != 'classdef': + for i, t in enumerate(trailer.parent.children): + if t == trailer: + to_evaluate = trailer.parent.children[:i] + types = self.eval_element(to_evaluate[0]) + for trailer in to_evaluate[1:]: + types = self.eval_trailer(types, trailer) + param_names = [] + for typ in types: + try: + params = typ.params + except AttributeError: + pass + else: + param_names += [param.name for param in params + if param.name.value == name.value] + return param_names + elif isinstance(par, pr.ExprStmt) and name in par.get_defined_names(): + # Only take the parent, because if it's more complicated than just + # a name it's something you can "goto" again. return [name] elif isinstance(par, (pr.Param, pr.Function, pr.Class)) and par.name is name: return [name] diff --git a/jedi/evaluate/helpers.py b/jedi/evaluate/helpers.py index 1832e039..2b6e175d 100644 --- a/jedi/evaluate/helpers.py +++ b/jedi/evaluate/helpers.py @@ -290,33 +290,7 @@ def get_module_name_parts(module): Returns a dictionary with name parts as keys and their call paths as values. """ - def scope_name_parts(scope): - for s in scope.subscopes: - # Yield the name parts, not names. - yield s.name - for need_yield_from in scope_name_parts(s): - yield need_yield_from - - statements_or_imports = set(chain(*module.used_names.values())) - name_parts = set(scope_name_parts(module)) - for stmt_or_import in statements_or_imports: - if isinstance(stmt_or_import, pr.Import): - for name in stmt_or_import.get_all_import_names(): - name_parts.add(name) - else: - # Running this ensures that all the expression lists are generated - # and the parents are all set. (Important for Lambdas) Howeer, this - # is only necessary because of the weird fault-tolerant structure - # of the parser. I hope to get rid of such behavior in the future. - stmt_or_import.expression_list() - # For now this is ok, but this could change if we don't have a - # token_list anymore, but for now this is the easiest way to get - # all the name_parts. - for tok in stmt_or_import._token_list: - if isinstance(tok, pr.Name): - name_parts.add(tok) - - return name_parts + return chain.from_iterable(module.used_names.values()) def statement_elements_in_statement(stmt):