diff --git a/api.py b/api.py index 68c13ddc..15291b0c 100644 --- a/api.py +++ b/api.py @@ -9,6 +9,7 @@ import modules import debug import settings import keywords +import helpers from _compatibility import next @@ -130,7 +131,14 @@ class CallDef(object): @property 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): return '<%s: %s index %s>' % (self.__class__.__name__, self.executable, @@ -374,7 +382,7 @@ class Script(object): index = 0 call = None stop = False - for index, sub in enumerate(arr): + for index, sub in enumerate(arr.values): call = None for s in sub: if isinstance(s, parsing.Array): @@ -384,26 +392,27 @@ class Script(object): if stop: return call, index, stop elif isinstance(s, parsing.Call): + start_s = s while s is not None: if s.start_pos >= pos: return call, index, stop - if s.execution is not None: - if s.execution.start_pos <= pos: - call = s + elif s.execution is not None: + end = s.execution.end_pos + if s.execution.start_pos < pos and \ + (end is None or pos < end): c, index, stop = scan_array_for_pos( - s.execution, pos) + s.execution, pos) if stop: return c, index, stop - if c is not None: - call = c - else: - return call, index, stop - print('E', pos, s.execution.end_pos) - if s.execution.end_pos is not None: - if pos < s.execution.end_pos: - return call, index, True - else: - return None, 0, True + + # call should return without execution and + # next + reset = c or s + reset.execution = None + reset.next = None + return c or start_s, index, True + #else: + #return call, index, stop s = s.next # The third return is just necessary for recursion inside, because # it needs to know when to stop iterating. @@ -412,20 +421,21 @@ class Script(object): user_stmt = self.parser.user_stmt if user_stmt is None or not isinstance(user_stmt, parsing.Statement): 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) if call is None: return None - call.execution, temp = None, call.execution origins = evaluate.follow_call(call) - call.execution = temp if len(origins) == 0: return None # just take entry zero, because we need just one. 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) def _get_completion_parts(self, path): diff --git a/parsing.py b/parsing.py index 744fb09d..0912b463 100644 --- a/parsing.py +++ b/parsing.py @@ -1260,7 +1260,8 @@ class PyFuzzyParser(object): if param and tok == ':': # parse annotations annotation, tok = self._parse_statement(added_breaks=breaks) - param.add_annotation(annotation) + if annotation: + param.add_annotation(annotation) if param: param.position_nr = pos diff --git a/plugin/jedi.vim b/plugin/jedi.vim index fb30ab62..425bb551 100644 --- a/plugin/jedi.vim +++ b/plugin/jedi.vim @@ -60,6 +60,7 @@ endif function! jedi#complete(findstart, base) python << PYTHONEOF if 1: + vim.eval('jedi#clear_func_def()') row, column = vim.current.window.cursor if vim.eval('a:findstart') == '1': count = 0 @@ -387,6 +388,7 @@ function! jedi#configure_function_definition() autocmd FileType python inoremap ( (=jedi#show_func_def() autocmd FileType python inoremap ) )=jedi#show_func_def() autocmd FileType python inoremap , ,=jedi#show_func_def() + autocmd FileType python inoremap =jedi#show_func_def() hi def link jediIgnore Ignore hi def link jediFatSymbol Ignore diff --git a/test/regression.py b/test/regression.py index 188beb18..f8d27c33 100755 --- a/test/regression.py +++ b/test/regression.py @@ -111,23 +111,43 @@ class TestRegression(unittest.TestCase): api.Script(s, 2, 2, '/').related_names() def test_get_in_function_call(self): - s = "isinstance(a, abs(" - s2 = "isinstance(), " - s3 = "isinstance()." + def check(call_def, name, index): + return call_def and call_def.call_name == name \ + 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, 14)), 1) - assert check(self.get_in_function_call(s, (1, 15)), 1) - assert check(self.get_in_function_call(s, (1, 18)), 0) + assert check(self.get_in_function_call(s, (1, 4)), 'abs', 0) + assert check(self.get_in_function_call(s, (1, 6)), 'abs', 1) + assert check(self.get_in_function_call(s, (1, 7)), 'abs', 1) + 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 self.get_in_function_call(s2, (1, 12)) is None + assert check(self.get_in_function_call(s2, (1, 4)), 'abs', 0) + 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(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(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__': unittest.main()