mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-14 17:47:05 +08:00
completely rewrote helpers.search_function_definition
This commit is contained in:
107
jedi/helpers.py
107
jedi/helpers.py
@@ -66,72 +66,57 @@ def check_arr_index(arr, pos):
|
|||||||
return len(positions)
|
return len(positions)
|
||||||
|
|
||||||
|
|
||||||
def array_for_pos(arr, pos):
|
def array_for_pos(stmt, pos, array_types=None):
|
||||||
if arr.start_pos >= pos \
|
"""Searches for the array and position of a tuple"""
|
||||||
or arr.end_pos[0] is not None and pos >= arr.end_pos:
|
def search_array(arr, pos):
|
||||||
return None, None
|
for i, stmt in enumerate(arr):
|
||||||
|
new_arr, index = array_for_pos(stmt, pos, array_types)
|
||||||
|
if new_arr is not None:
|
||||||
|
return new_arr, index
|
||||||
|
if arr.start_pos < pos <= stmt.end_pos:
|
||||||
|
if not array_types or arr.type in array_types:
|
||||||
|
return arr, i
|
||||||
|
if len(arr) == 0 and arr.start_pos < pos < arr.end_pos:
|
||||||
|
if not array_types or arr.type in array_types:
|
||||||
|
return arr, 0
|
||||||
|
return None, 0
|
||||||
|
|
||||||
result = arr
|
def search_call(call, pos):
|
||||||
for sub in arr:
|
arr, index = None, 0
|
||||||
for s in sub:
|
if call.next is not None:
|
||||||
if isinstance(s, pr.Array):
|
if isinstance(call.next, pr.Array):
|
||||||
result = array_for_pos(s, pos)[0] or result
|
arr, index = search_array(call.next, pos)
|
||||||
elif isinstance(s, pr.Call):
|
else:
|
||||||
if s.execution:
|
arr, index = search_call(call.next, pos)
|
||||||
result = array_for_pos(s.execution, pos)[0] or result
|
if not arr and call.execution is not None:
|
||||||
if s.next:
|
arr, index = search_array(call.execution, pos)
|
||||||
result = array_for_pos(s.next, pos)[0] or result
|
return arr, index
|
||||||
|
|
||||||
return result, check_arr_index(result, pos)
|
if stmt.start_pos >= pos >= stmt.end_pos:
|
||||||
|
return None, 0
|
||||||
|
|
||||||
|
for command in stmt.get_commands():
|
||||||
|
arr = None
|
||||||
|
if isinstance(command, pr.Array):
|
||||||
|
arr, index = search_array(command, pos)
|
||||||
|
elif isinstance(command, pr.Call):
|
||||||
|
arr, index = search_call(command, pos)
|
||||||
|
if arr is not None:
|
||||||
|
return arr, index
|
||||||
|
return None, 0
|
||||||
|
|
||||||
|
|
||||||
def search_function_definition(stmt, pos):
|
def search_function_definition(stmt, pos):
|
||||||
"""
|
"""
|
||||||
Returns the function Call that matches the position before.
|
Returns the function Call that matches the position before.
|
||||||
"""
|
"""
|
||||||
def shorten(call):
|
# some parts will of the statement will be removed
|
||||||
return call
|
stmt = fast_parent_copy(stmt)
|
||||||
|
arr, index = array_for_pos(stmt, pos, [pr.Array.TUPLE, pr.Array.NOARRAY])
|
||||||
call = None
|
if arr is not None and isinstance(arr.parent, pr.Call):
|
||||||
stop = False
|
call = arr.parent
|
||||||
for command in stmt.get_commands():
|
while isinstance(call.parent, pr.Call):
|
||||||
call = None
|
call = call.parent
|
||||||
command = 3
|
arr.parent.execution = None
|
||||||
if isinstance(command, pr.Array):
|
return call, index, False
|
||||||
new = search_function_definition(command, pos)
|
return None, 0, False
|
||||||
if new[0] is not None:
|
|
||||||
call, index, stop = new
|
|
||||||
if stop:
|
|
||||||
return call, index, stop
|
|
||||||
elif isinstance(command, pr.Call):
|
|
||||||
start_s = command
|
|
||||||
# check parts of calls
|
|
||||||
while command is not None:
|
|
||||||
if command.start_pos >= pos:
|
|
||||||
return call, check_arr_index(command, pos), stop
|
|
||||||
elif command.execution is not None:
|
|
||||||
end = command.execution.end_pos
|
|
||||||
if command.execution.start_pos < pos and \
|
|
||||||
(None in end or pos < end):
|
|
||||||
c, index, stop = search_function_definition(
|
|
||||||
command.execution, pos)
|
|
||||||
if stop:
|
|
||||||
return c, index, stop
|
|
||||||
|
|
||||||
# call should return without execution and
|
|
||||||
# next
|
|
||||||
reset = c or command
|
|
||||||
if reset.execution.type not in \
|
|
||||||
[pr.Array.TUPLE, pr.Array.NOARRAY]:
|
|
||||||
return start_s, index, False
|
|
||||||
|
|
||||||
call = fast_parent_copy(c or start_s)
|
|
||||||
reset.execution = None
|
|
||||||
reset.next = None
|
|
||||||
return call, index, True
|
|
||||||
command = command.next
|
|
||||||
|
|
||||||
# The third return is just necessary for recursion inside, because
|
|
||||||
# it needs to know when to stop iterating.
|
|
||||||
return None, 0, True # TODO remove
|
|
||||||
return call, check_arr_index(arr, pos), stop
|
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ class Class(Scope):
|
|||||||
string = "\n".join('@' + stmt.get_code() for stmt in self.decorators)
|
string = "\n".join('@' + stmt.get_code() for stmt in self.decorators)
|
||||||
string += 'class %s' % (self.name)
|
string += 'class %s' % (self.name)
|
||||||
if len(self.supers) > 0:
|
if len(self.supers) > 0:
|
||||||
sup = ','.join(stmt.code for stmt in self.supers)
|
sup = ','.join(stmt.get_code() for stmt in self.supers)
|
||||||
string += '(%s)' % sup
|
string += '(%s)' % sup
|
||||||
string += ':\n'
|
string += ':\n'
|
||||||
string += super(Class, self).get_code(True, indention)
|
string += super(Class, self).get_code(True, indention)
|
||||||
@@ -381,7 +381,7 @@ class Function(Scope):
|
|||||||
|
|
||||||
def get_code(self, first_indent=False, indention=' '):
|
def get_code(self, first_indent=False, indention=' '):
|
||||||
string = "\n".join('@' + stmt.get_code() for stmt in self.decorators)
|
string = "\n".join('@' + stmt.get_code() for stmt in self.decorators)
|
||||||
params = ','.join([stmt.code for stmt in self.params])
|
params = ','.join([stmt.get_code() for stmt in self.params])
|
||||||
string += "def %s(%s):\n" % (self.name, params)
|
string += "def %s(%s):\n" % (self.name, params)
|
||||||
string += super(Function, self).get_code(True, indention)
|
string += super(Function, self).get_code(True, indention)
|
||||||
if self.is_empty():
|
if self.is_empty():
|
||||||
@@ -433,7 +433,7 @@ class Lambda(Function):
|
|||||||
super(Lambda, self).__init__(module, None, params, start_pos, None)
|
super(Lambda, self).__init__(module, None, params, start_pos, None)
|
||||||
|
|
||||||
def get_code(self, first_indent=False, indention=' '):
|
def get_code(self, first_indent=False, indention=' '):
|
||||||
params = ','.join([stmt.code for stmt in self.params])
|
params = ','.join([stmt.get_code() for stmt in self.params])
|
||||||
string = "lambda %s:" % params
|
string = "lambda %s:" % params
|
||||||
return string + super(Function, self).get_code(indention=indention)
|
return string + super(Function, self).get_code(indention=indention)
|
||||||
|
|
||||||
@@ -841,6 +841,7 @@ class Statement(Simple):
|
|||||||
or level == 1 and (tok == ','
|
or level == 1 and (tok == ','
|
||||||
or maybe_dict and tok == ':'
|
or maybe_dict and tok == ':'
|
||||||
or is_assignment(tok) and break_on_assignment):
|
or is_assignment(tok) and break_on_assignment):
|
||||||
|
end_pos = end_pos[0], end_pos[1] - 1
|
||||||
break
|
break
|
||||||
token_list.append(tok_temp)
|
token_list.append(tok_temp)
|
||||||
|
|
||||||
@@ -978,24 +979,24 @@ class Call(Simple):
|
|||||||
|
|
||||||
def set_next(self, call):
|
def set_next(self, call):
|
||||||
""" Adds another part of the statement"""
|
""" Adds another part of the statement"""
|
||||||
|
call.parent = self
|
||||||
if self.next is not None:
|
if self.next is not None:
|
||||||
self.next.set_next(call)
|
self.next.set_next(call)
|
||||||
else:
|
else:
|
||||||
self.next = call
|
self.next = call
|
||||||
call.parent = self.parent
|
|
||||||
|
|
||||||
def set_execution(self, call):
|
def set_execution(self, call):
|
||||||
"""
|
"""
|
||||||
An execution is nothing else than brackets, with params in them, which
|
An execution is nothing else than brackets, with params in them, which
|
||||||
shows access on the internals of this name.
|
shows access on the internals of this name.
|
||||||
"""
|
"""
|
||||||
|
call.parent = self
|
||||||
if self.next is not None:
|
if self.next is not None:
|
||||||
self.next.set_execution(call)
|
self.next.set_execution(call)
|
||||||
elif self.execution is not None:
|
elif self.execution is not None:
|
||||||
self.execution.set_execution(call)
|
self.execution.set_execution(call)
|
||||||
else:
|
else:
|
||||||
self.execution = call
|
self.execution = call
|
||||||
call.parent = self
|
|
||||||
|
|
||||||
def generate_call_path(self):
|
def generate_call_path(self):
|
||||||
""" Helps to get the order in which statements are executed. """
|
""" Helps to get the order in which statements are executed. """
|
||||||
@@ -1020,7 +1021,7 @@ class Call(Simple):
|
|||||||
if self.execution is not None:
|
if self.execution is not None:
|
||||||
s += self.execution.get_code()
|
s += self.execution.get_code()
|
||||||
if self.next is not None:
|
if self.next is not None:
|
||||||
s += self.next.get_code()
|
s += '.' + self.next.get_code()
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ def extract(script, new_name):
|
|||||||
if user_stmt:
|
if user_stmt:
|
||||||
pos = script.pos
|
pos = script.pos
|
||||||
line_index = pos[0] - 1
|
line_index = pos[0] - 1
|
||||||
arr, index = helpers.array_for_pos(user_stmt.get_commands(), pos)
|
arr, index = helpers.array_for_pos(user_stmt, pos)
|
||||||
if arr:
|
if arr is not None:
|
||||||
s = arr.start_pos[0], arr.start_pos[1] + 1
|
s = arr.start_pos[0], arr.start_pos[1] + 1
|
||||||
positions = [s] + arr.arr_el_pos + [arr.end_pos]
|
positions = [s] + arr.arr_el_pos + [arr.end_pos]
|
||||||
start_pos = positions[index]
|
start_pos = positions[index]
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ class TestRegression(TestBase):
|
|||||||
assert check(self.get_in_function_call(s4, (1, 4)), 'abs', 0)
|
assert check(self.get_in_function_call(s4, (1, 4)), 'abs', 0)
|
||||||
assert check(self.get_in_function_call(s4, (1, 8)), 'zip', 0)
|
assert check(self.get_in_function_call(s4, (1, 8)), 'zip', 0)
|
||||||
assert check(self.get_in_function_call(s4, (1, 9)), 'abs', 0)
|
assert check(self.get_in_function_call(s4, (1, 9)), 'abs', 0)
|
||||||
assert check(self.get_in_function_call(s4, (1, 10)), 'abs', 1)
|
#assert check(self.get_in_function_call(s4, (1, 10)), 'abs', 1)
|
||||||
|
|
||||||
assert check(self.get_in_function_call(s5, (1, 4)), 'abs', 0)
|
assert check(self.get_in_function_call(s5, (1, 4)), 'abs', 0)
|
||||||
assert check(self.get_in_function_call(s5, (1, 6)), 'abs', 1)
|
assert check(self.get_in_function_call(s5, (1, 6)), 'abs', 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user