mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 22:14:27 +08:00
fixed many get_in_function_call related bugs
This commit is contained in:
46
api.py
46
api.py
@@ -9,6 +9,7 @@ import modules
|
|||||||
import debug
|
import debug
|
||||||
import settings
|
import settings
|
||||||
import keywords
|
import keywords
|
||||||
|
import helpers
|
||||||
|
|
||||||
from _compatibility import next
|
from _compatibility import next
|
||||||
|
|
||||||
@@ -130,7 +131,14 @@ class CallDef(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def bracket_start(self):
|
def bracket_start(self):
|
||||||
return self.call.name.end_pos
|
c = self.call
|
||||||
|
while c.next is not None:
|
||||||
|
c = c.next
|
||||||
|
return c.name.end_pos
|
||||||
|
|
||||||
|
@property
|
||||||
|
def call_name(self):
|
||||||
|
return str(self.executable.name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s: %s index %s>' % (self.__class__.__name__, self.executable,
|
return '<%s: %s index %s>' % (self.__class__.__name__, self.executable,
|
||||||
@@ -374,7 +382,7 @@ class Script(object):
|
|||||||
index = 0
|
index = 0
|
||||||
call = None
|
call = None
|
||||||
stop = False
|
stop = False
|
||||||
for index, sub in enumerate(arr):
|
for index, sub in enumerate(arr.values):
|
||||||
call = None
|
call = None
|
||||||
for s in sub:
|
for s in sub:
|
||||||
if isinstance(s, parsing.Array):
|
if isinstance(s, parsing.Array):
|
||||||
@@ -384,26 +392,27 @@ class Script(object):
|
|||||||
if stop:
|
if stop:
|
||||||
return call, index, stop
|
return call, index, stop
|
||||||
elif isinstance(s, parsing.Call):
|
elif isinstance(s, parsing.Call):
|
||||||
|
start_s = s
|
||||||
while s is not None:
|
while s is not None:
|
||||||
if s.start_pos >= pos:
|
if s.start_pos >= pos:
|
||||||
return call, index, stop
|
return call, index, stop
|
||||||
if s.execution is not None:
|
elif s.execution is not None:
|
||||||
if s.execution.start_pos <= pos:
|
end = s.execution.end_pos
|
||||||
call = s
|
if s.execution.start_pos < pos and \
|
||||||
|
(end is None or pos < end):
|
||||||
c, index, stop = scan_array_for_pos(
|
c, index, stop = scan_array_for_pos(
|
||||||
s.execution, pos)
|
s.execution, pos)
|
||||||
if stop:
|
if stop:
|
||||||
return c, index, stop
|
return c, index, stop
|
||||||
if c is not None:
|
|
||||||
call = c
|
# call should return without execution and
|
||||||
else:
|
# next
|
||||||
return call, index, stop
|
reset = c or s
|
||||||
print('E', pos, s.execution.end_pos)
|
reset.execution = None
|
||||||
if s.execution.end_pos is not None:
|
reset.next = None
|
||||||
if pos < s.execution.end_pos:
|
return c or start_s, index, True
|
||||||
return call, index, True
|
#else:
|
||||||
else:
|
#return call, index, stop
|
||||||
return None, 0, True
|
|
||||||
s = s.next
|
s = s.next
|
||||||
# The third return is just necessary for recursion inside, because
|
# The third return is just necessary for recursion inside, because
|
||||||
# it needs to know when to stop iterating.
|
# it needs to know when to stop iterating.
|
||||||
@@ -412,20 +421,21 @@ class Script(object):
|
|||||||
user_stmt = self.parser.user_stmt
|
user_stmt = self.parser.user_stmt
|
||||||
if user_stmt is None or not isinstance(user_stmt, parsing.Statement):
|
if user_stmt is None or not isinstance(user_stmt, parsing.Statement):
|
||||||
return None
|
return None
|
||||||
ass = user_stmt.get_assignment_calls()
|
ass = helpers.fast_parent_copy(user_stmt.get_assignment_calls())
|
||||||
|
|
||||||
call, index, stop = scan_array_for_pos(ass, self.pos)
|
call, index, stop = scan_array_for_pos(ass, self.pos)
|
||||||
if call is None:
|
if call is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
call.execution, temp = None, call.execution
|
|
||||||
origins = evaluate.follow_call(call)
|
origins = evaluate.follow_call(call)
|
||||||
call.execution = temp
|
|
||||||
|
|
||||||
if len(origins) == 0:
|
if len(origins) == 0:
|
||||||
return None
|
return None
|
||||||
# just take entry zero, because we need just one.
|
# just take entry zero, because we need just one.
|
||||||
executable = origins[0]
|
executable = origins[0]
|
||||||
|
|
||||||
|
after = self.module.get_line(self.pos[0])[self.pos[1]:]
|
||||||
|
index -= re.search('^[ ,]*', after).group(0).count(',')
|
||||||
return CallDef(executable, index, call)
|
return CallDef(executable, index, call)
|
||||||
|
|
||||||
def _get_completion_parts(self, path):
|
def _get_completion_parts(self, path):
|
||||||
|
|||||||
@@ -1260,6 +1260,7 @@ class PyFuzzyParser(object):
|
|||||||
if param and tok == ':':
|
if param and tok == ':':
|
||||||
# parse annotations
|
# parse annotations
|
||||||
annotation, tok = self._parse_statement(added_breaks=breaks)
|
annotation, tok = self._parse_statement(added_breaks=breaks)
|
||||||
|
if annotation:
|
||||||
param.add_annotation(annotation)
|
param.add_annotation(annotation)
|
||||||
|
|
||||||
if param:
|
if param:
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ endif
|
|||||||
function! jedi#complete(findstart, base)
|
function! jedi#complete(findstart, base)
|
||||||
python << PYTHONEOF
|
python << PYTHONEOF
|
||||||
if 1:
|
if 1:
|
||||||
|
vim.eval('jedi#clear_func_def()')
|
||||||
row, column = vim.current.window.cursor
|
row, column = vim.current.window.cursor
|
||||||
if vim.eval('a:findstart') == '1':
|
if vim.eval('a:findstart') == '1':
|
||||||
count = 0
|
count = 0
|
||||||
@@ -387,6 +388,7 @@ function! jedi#configure_function_definition()
|
|||||||
autocmd FileType python inoremap <buffer> ( (<C-R>=jedi#show_func_def()<CR>
|
autocmd FileType python inoremap <buffer> ( (<C-R>=jedi#show_func_def()<CR>
|
||||||
autocmd FileType python inoremap <buffer> ) )<C-R>=jedi#show_func_def()<CR>
|
autocmd FileType python inoremap <buffer> ) )<C-R>=jedi#show_func_def()<CR>
|
||||||
autocmd FileType python inoremap <buffer> , ,<C-R>=jedi#show_func_def()<CR>
|
autocmd FileType python inoremap <buffer> , ,<C-R>=jedi#show_func_def()<CR>
|
||||||
|
autocmd FileType python inoremap <buffer> <BS> <BS><C-R>=jedi#show_func_def()<CR>
|
||||||
|
|
||||||
hi def link jediIgnore Ignore
|
hi def link jediIgnore Ignore
|
||||||
hi def link jediFatSymbol Ignore
|
hi def link jediFatSymbol Ignore
|
||||||
|
|||||||
@@ -111,23 +111,43 @@ class TestRegression(unittest.TestCase):
|
|||||||
api.Script(s, 2, 2, '/').related_names()
|
api.Script(s, 2, 2, '/').related_names()
|
||||||
|
|
||||||
def test_get_in_function_call(self):
|
def test_get_in_function_call(self):
|
||||||
s = "isinstance(a, abs("
|
def check(call_def, name, index):
|
||||||
s2 = "isinstance(), "
|
return call_def and call_def.call_name == name \
|
||||||
s3 = "isinstance()."
|
and call_def.index == index
|
||||||
|
|
||||||
check = lambda call_def, index: call_def and call_def.index == index
|
# simple
|
||||||
|
s = "abs(a, str("
|
||||||
|
s2 = "abs(), "
|
||||||
|
s3 = "abs()."
|
||||||
|
# more complicated
|
||||||
|
s4 = 'abs(zip(), , set,'
|
||||||
|
s5 = "abs(1,\nif 2:\n def a():"
|
||||||
|
s6 = "str().center("
|
||||||
|
|
||||||
assert check(self.get_in_function_call(s, (1, 11)), 0)
|
assert check(self.get_in_function_call(s, (1, 4)), 'abs', 0)
|
||||||
assert check(self.get_in_function_call(s, (1, 14)), 1)
|
assert check(self.get_in_function_call(s, (1, 6)), 'abs', 1)
|
||||||
assert check(self.get_in_function_call(s, (1, 15)), 1)
|
assert check(self.get_in_function_call(s, (1, 7)), 'abs', 1)
|
||||||
assert check(self.get_in_function_call(s, (1, 18)), 0)
|
assert check(self.get_in_function_call(s, (1, 8)), 'abs', 1)
|
||||||
|
assert check(self.get_in_function_call(s, (1, 11)), 'str', 0)
|
||||||
|
|
||||||
assert check(self.get_in_function_call(s2, (1, 11)), 0)
|
assert check(self.get_in_function_call(s2, (1, 4)), 'abs', 0)
|
||||||
assert self.get_in_function_call(s2, (1, 12)) is None
|
assert self.get_in_function_call(s2, (1, 5)) is None
|
||||||
assert self.get_in_function_call(s2) is None
|
assert self.get_in_function_call(s2) is None
|
||||||
|
|
||||||
assert self.get_in_function_call(s3, (1, 12)) is None
|
assert self.get_in_function_call(s3, (1, 5)) is None
|
||||||
assert self.get_in_function_call(s3) is None
|
assert self.get_in_function_call(s3) is None
|
||||||
|
|
||||||
|
assert self.get_in_function_call(s4, (1, 3)) is None
|
||||||
|
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, 9)), 'abs', 0)
|
||||||
|
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, 6)), 'abs', 1)
|
||||||
|
|
||||||
|
assert check(self.get_in_function_call(s6, (1, 13)), 'center', 0)
|
||||||
|
assert check(self.get_in_function_call(s6, (1, 4)), 'str', 0)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user