From e1e5c3a6c7004f7828037777389a0d874e449aa5 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sun, 7 Dec 2014 13:56:40 +0100 Subject: [PATCH] Progress with call signatures. --- jedi/api/__init__.py | 41 ++++++++++++++++++++++--------------- jedi/parser/user_context.py | 41 +++++++++++++++++++++++++++++-------- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index 6c9518c6..337afc64 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -420,9 +420,9 @@ class Script(object): else: # Fetch definition of callee, if there's no path otherwise. if not goto_path: - call, _, _ = search_call_signatures(user_stmt, self._pos) - if call is not None: - definitions = set(self._evaluator.eval_call(call)) + node, _, _ = search_call_signatures(user_stmt, self._pos) + if node is not None: + definitions = set(self._evaluator.eval_element(node)) if not definitions: if goto_path: @@ -573,26 +573,33 @@ class Script(object): :rtype: list of :class:`classes.CallSignature` """ - user_stmt = self._parser.user_stmt_with_whitespace() - call, trailer, index = search_call_signatures(user_stmt, self._pos) - if call is None: + call_txt, call_index = self._user_context.call_signature() + if call_txt is None: return [] + print(call_txt, call_index) + stmt = self._get_under_cursor_stmt(call_txt) + #user_stmt = self._parser.user_stmt_with_whitespace() + #call, trailer, index = search_call_signatures(user_stmt, self._pos) + #if call is None: + # return [] + with common.scale_speed_settings(settings.scale_call_signatures): - origins = cache.cache_call_signatures(self._evaluator, call, self.source, - self._pos, user_stmt) + origins = cache.cache_call_signatures(self._evaluator, stmt, self.source, + self._pos, stmt) debug.speed('func_call followed') key_name = None - try: - # Access the trailers arglist node. - argument = trailer.children[0].children[index] - except (IndexError, AttributeError): - pass - else: - if argument.children[1] == '=': - key_name = argument.children[0] - return [classes.CallSignature(self._evaluator, o.name, call, index, key_name) + if 0: # Change logic. + try: + # Access the trailers arglist node. + argument = trailer.children[0].children[index] + except (IndexError, AttributeError): + pass + else: + if argument.children[1] == '=': + key_name = argument.children[0] + return [classes.CallSignature(self._evaluator, o.name, stmt, call_index, key_name) for o in origins if hasattr(o, 'py__call__')] def _analysis(self): diff --git a/jedi/parser/user_context.py b/jedi/parser/user_context.py index f30058ca..d0eff656 100644 --- a/jedi/parser/user_context.py +++ b/jedi/parser/user_context.py @@ -23,8 +23,6 @@ class UserContext(object): self.position = position self._line_cache = None - # this two are only used, because there is no nonlocal in Python 2 - self._line_temp = None self._relevant_temp = None @cache.underscore_memoization @@ -33,11 +31,9 @@ class UserContext(object): path, self._start_cursor_pos = self._calc_path_until_cursor(self.position) return path - def _calc_path_until_cursor(self, start_pos=None): - """ - Something like a reverse tokenizer that tokenizes the reversed strings. - """ + def _get_backwards_tokenizer(self, start_pos): def fetch_line(): + # No nonlocal so use class variables. if self._is_first: self._is_first = False self._line_length = self._column_temp @@ -59,13 +55,20 @@ class UserContext(object): return line[::-1] self._is_first = True - self._line_temp, self._column_temp = start_cursor = start_pos + self._line_temp, self._column_temp = start_pos first_line = self.get_line(self._line_temp)[:self._column_temp] + return tokenize.generate_tokens(fetch_line) + def _calc_path_until_cursor(self, start_pos=None): + """ + Something like a reverse tokenizer that tokenizes the reversed strings. + """ open_brackets = ['(', '[', '{'] close_brackets = [')', ']', '}'] - gen = PushBackIterator(tokenize.generate_tokens(fetch_line)) + start_cursor = start_pos + gen = PushBackIterator(self._get_backwards_tokenizer(start_pos)) + first_line = self.get_line(self._line_temp)[:start_pos[1]] string = u('') level = 0 force_point = False @@ -154,6 +157,28 @@ class UserContext(object): return (before.group(0) if before is not None else '') \ + (after.group(0) if after is not None else '') + def call_signature(self): + """ + :return: Tuple of string of the call and the index of the cursor. + """ + index = 0 + level = 0 + for token in self._get_backwards_tokenizer(self.position): + tok_str = token.value + if tok_str == '(': + level += 1 + if level == 1: + end = token.end_pos + self._column_temp = self._line_length - end[1] + pos = self._line_temp + 1, self._column_temp + call, _ = self._calc_path_until_cursor(start_pos=pos) + return call, index + elif tok_str == ')': + level -= 1 + elif tok_str == ',': + index += 1 + return None, 0 + def get_context(self, yield_positions=False): self.get_path_until_cursor() # In case _start_cursor_pos is undefined. pos = self._start_cursor_pos