forked from VimPlug/jedi
First small implementation of goto.
This commit is contained in:
@@ -442,18 +442,13 @@ class Script(object):
|
|||||||
user_stmt = self._parser.user_stmt()
|
user_stmt = self._parser.user_stmt()
|
||||||
|
|
||||||
stmt = self._get_under_cursor_stmt(goto_path)
|
stmt = self._get_under_cursor_stmt(goto_path)
|
||||||
expression_list = stmt.expression_list()
|
if stmt is None:
|
||||||
if len(expression_list) == 0:
|
|
||||||
return []
|
|
||||||
# The reverse tokenizer only generates parses call.
|
|
||||||
assert len(expression_list) == 1
|
|
||||||
call = expression_list[0]
|
|
||||||
if isinstance(call, pr.Call):
|
|
||||||
call_path = list(call.generate_call_path())
|
|
||||||
else:
|
|
||||||
# goto_assignments on Operator returns nothing.
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
last_name = stmt
|
||||||
|
while not isinstance(last_name, pr.Name):
|
||||||
|
last_name = last_name.children[-1]
|
||||||
|
|
||||||
if next(context) in ('class', 'def'):
|
if next(context) in ('class', 'def'):
|
||||||
# The cursor is on a class/function name.
|
# The cursor is on a class/function name.
|
||||||
user_scope = self._parser.user_scope()
|
user_scope = self._parser.user_scope()
|
||||||
@@ -476,14 +471,14 @@ class Script(object):
|
|||||||
# The Evaluator.goto function checks for definitions, but since we
|
# The Evaluator.goto function checks for definitions, but since we
|
||||||
# use a reverse tokenizer, we have new name_part objects, so we
|
# use a reverse tokenizer, we have new name_part objects, so we
|
||||||
# have to check the user_stmt here for positions.
|
# have to check the user_stmt here for positions.
|
||||||
if isinstance(user_stmt, pr.ExprStmt):
|
if False and isinstance(user_stmt, pr.ExprStmt):
|
||||||
for name in user_stmt.get_defined_names():
|
for name in user_stmt.get_defined_names():
|
||||||
if name.start_pos <= self._pos <= name.end_pos \
|
if name.start_pos <= self._pos <= name.end_pos \
|
||||||
and (not isinstance(name.parent, pr.Call)
|
and (not isinstance(name.parent, pr.Call)
|
||||||
or name.parent.next is None):
|
or name.parent.next is None):
|
||||||
return [name]
|
return [name]
|
||||||
|
|
||||||
defs = self._evaluator.goto(stmt, call_path)
|
defs = self._evaluator.goto(last_name)
|
||||||
definitions = follow_inexistent_imports(defs)
|
definitions = follow_inexistent_imports(defs)
|
||||||
return definitions
|
return definitions
|
||||||
|
|
||||||
|
|||||||
@@ -442,7 +442,15 @@ class Evaluator(object):
|
|||||||
call = call_of_name(name)
|
call = call_of_name(name)
|
||||||
return self.eval_element(call)
|
return self.eval_element(call)
|
||||||
|
|
||||||
def goto(self, stmt, call_path):
|
def goto(self, name):
|
||||||
|
scope = name.get_parent_scope()
|
||||||
|
if pr.is_node(name.parent, 'trailer'):
|
||||||
|
call = call_of_name(name, cut_own_trailer=True)
|
||||||
|
types = self.eval_element(call)
|
||||||
|
return iterable.unite(self.find_types(typ, name, is_goto=True)
|
||||||
|
for typ in types)
|
||||||
|
else:
|
||||||
|
return self.find_types(scope, name, search_global=True, is_goto=True)
|
||||||
if isinstance(stmt, pr.Import):
|
if isinstance(stmt, pr.Import):
|
||||||
# Nowhere to goto for aliases
|
# Nowhere to goto for aliases
|
||||||
if stmt.alias == call_path[0]:
|
if stmt.alias == call_path[0]:
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ def deep_ast_copy(obj, new_elements_default=None):
|
|||||||
return recursion(obj)
|
return recursion(obj)
|
||||||
|
|
||||||
|
|
||||||
def call_of_name(name):
|
def call_of_name(name, cut_own_trailer=False):
|
||||||
"""
|
"""
|
||||||
Creates a "call" node that consist of all ``trailer`` and ``power``
|
Creates a "call" node that consist of all ``trailer`` and ``power``
|
||||||
objects. E.g. if you call it with ``append``::
|
objects. E.g. if you call it with ``append``::
|
||||||
@@ -119,10 +119,14 @@ def call_of_name(name):
|
|||||||
par = power
|
par = power
|
||||||
# Now the name must be part of a trailer
|
# Now the name must be part of a trailer
|
||||||
index = par.children.index(name.parent)
|
index = par.children.index(name.parent)
|
||||||
if index != len(par.children) - 1:
|
if index != len(par.children) - 1 or cut_own_trailer:
|
||||||
# Now we have to cut the other trailers away.
|
# Now we have to cut the other trailers away.
|
||||||
par = deep_ast_copy(par)
|
par = deep_ast_copy(par)
|
||||||
par.children[index + 1:] = []
|
if not cut_own_trailer:
|
||||||
|
# Normally we would remove just the stuff after the index, but
|
||||||
|
# if the option is set remove the index as well. (for goto)
|
||||||
|
index = index + 1
|
||||||
|
par.children[index:] = []
|
||||||
|
|
||||||
return par
|
return par
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user