diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index edd7acd1..6013b3e0 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -249,12 +249,12 @@ class Script(object): except IndexError: raise NotFoundError() user_stmt = self._parser.user_stmt() - if type(user_stmt) is pr.Statement: - stmt.start_pos = user_stmt.start_pos - else: + if user_stmt is None: # Set the start_pos to a pseudo position, that doesn't exist but works # perfectly well (for both completions in docstrings and statements). stmt.start_pos = self._pos + else: + stmt.start_pos = user_stmt.start_pos stmt.parent = self._parser.user_scope() return stmt @@ -437,7 +437,7 @@ class Script(object): for name in user_stmt.get_set_vars(): if name.start_pos <= self._pos <= name.end_pos \ and len(name.names) == 1: - return user_stmt, name.names[-1] + return name, name.names[-1] return None, None lhs, search_name = test_lhs() diff --git a/jedi/api/usages.py b/jedi/api/usages.py index bc2be942..94d887fc 100644 --- a/jedi/api/usages.py +++ b/jedi/api/usages.py @@ -36,8 +36,18 @@ def usages(evaluator, definitions, search_name, mods): result.append((module, d.start_pos)) return result - def check_call(call): - result = [] + def check_call_for_usage(call): + stmt = call.parent + while not isinstance(stmt.parent, pr.IsScope): + stmt = stmt.parent + # New definition, call cannot be a part of stmt + if len(call.name) == 1 and call.execution is None \ + and call.name in stmt.get_set_vars(): + # Class params are not definitions (like function params). They + # are super classes, that need to be resolved. + if not (isinstance(stmt, pr.Param) and isinstance(stmt.parent, pr.Class)): + return + follow = [] # There might be multiple search_name's in one call_path call_path = list(call.generate_call_path()) for i, name in enumerate(call_path): @@ -45,10 +55,10 @@ def usages(evaluator, definitions, search_name, mods): if name == search_name: follow.append(call_path[:i + 1]) - for f in follow: - follow_res, search = evaluator.goto(call.parent, f) + for call_path in follow: + follow_res, search = evaluator.goto(call.parent, call_path) # names can change (getattr stuff), therefore filter names that - # don't match `search_name`. + # don't match `search`. # TODO add something like that in the future - for now usages are # completely broken anyway. @@ -61,9 +71,7 @@ def usages(evaluator, definitions, search_name, mods): # compare to see if they match if any(r in compare_definitions for r in compare_follow_res): scope = call.parent - result.append(Usage(evaluator, search, scope)) - - return result + yield Usage(evaluator, search, scope) if not definitions: return set() @@ -94,7 +102,7 @@ def usages(evaluator, definitions, search_name, mods): names.append(Usage(evaluator, name_part, stmt)) else: for call in helpers.scan_statement_for_calls(stmt, search_name, assignment_details=True): - names += check_call(call) + names += check_call_for_usage(call) return names diff --git a/test/completion/usages.py b/test/completion/usages.py index 7284c8b0..274ad913 100644 --- a/test/completion/usages.py +++ b/test/completion/usages.py @@ -11,6 +11,11 @@ abc.d.a.bsaasd.abc.d abc +if 1: + abc = +else: + (abc) = + abc = #< (-3,0), (0,0)