Progress with call signatures.

This commit is contained in:
Dave Halter
2014-12-07 13:56:40 +01:00
parent 24903739f2
commit e1e5c3a6c7
2 changed files with 57 additions and 25 deletions
+24 -17
View File
@@ -420,9 +420,9 @@ class Script(object):
else: else:
# Fetch definition of callee, if there's no path otherwise. # Fetch definition of callee, if there's no path otherwise.
if not goto_path: if not goto_path:
call, _, _ = search_call_signatures(user_stmt, self._pos) node, _, _ = search_call_signatures(user_stmt, self._pos)
if call is not None: if node is not None:
definitions = set(self._evaluator.eval_call(call)) definitions = set(self._evaluator.eval_element(node))
if not definitions: if not definitions:
if goto_path: if goto_path:
@@ -573,26 +573,33 @@ class Script(object):
:rtype: list of :class:`classes.CallSignature` :rtype: list of :class:`classes.CallSignature`
""" """
user_stmt = self._parser.user_stmt_with_whitespace() call_txt, call_index = self._user_context.call_signature()
call, trailer, index = search_call_signatures(user_stmt, self._pos) if call_txt is None:
if call is None:
return [] 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): with common.scale_speed_settings(settings.scale_call_signatures):
origins = cache.cache_call_signatures(self._evaluator, call, self.source, origins = cache.cache_call_signatures(self._evaluator, stmt, self.source,
self._pos, user_stmt) self._pos, stmt)
debug.speed('func_call followed') debug.speed('func_call followed')
key_name = None key_name = None
try: if 0: # Change logic.
# Access the trailers arglist node. try:
argument = trailer.children[0].children[index] # Access the trailers arglist node.
except (IndexError, AttributeError): argument = trailer.children[0].children[index]
pass except (IndexError, AttributeError):
else: pass
if argument.children[1] == '=': else:
key_name = argument.children[0] if argument.children[1] == '=':
return [classes.CallSignature(self._evaluator, o.name, call, index, key_name) 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__')] for o in origins if hasattr(o, 'py__call__')]
def _analysis(self): def _analysis(self):
+33 -8
View File
@@ -23,8 +23,6 @@ class UserContext(object):
self.position = position self.position = position
self._line_cache = None 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 self._relevant_temp = None
@cache.underscore_memoization @cache.underscore_memoization
@@ -33,11 +31,9 @@ class UserContext(object):
path, self._start_cursor_pos = self._calc_path_until_cursor(self.position) path, self._start_cursor_pos = self._calc_path_until_cursor(self.position)
return path return path
def _calc_path_until_cursor(self, start_pos=None): def _get_backwards_tokenizer(self, start_pos):
"""
Something like a reverse tokenizer that tokenizes the reversed strings.
"""
def fetch_line(): def fetch_line():
# No nonlocal so use class variables.
if self._is_first: if self._is_first:
self._is_first = False self._is_first = False
self._line_length = self._column_temp self._line_length = self._column_temp
@@ -59,13 +55,20 @@ class UserContext(object):
return line[::-1] return line[::-1]
self._is_first = True 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] 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 = ['(', '[', '{'] open_brackets = ['(', '[', '{']
close_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('') string = u('')
level = 0 level = 0
force_point = False force_point = False
@@ -154,6 +157,28 @@ class UserContext(object):
return (before.group(0) if before is not None else '') \ return (before.group(0) if before is not None else '') \
+ (after.group(0) if after 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): def get_context(self, yield_positions=False):
self.get_path_until_cursor() # In case _start_cursor_pos is undefined. self.get_path_until_cursor() # In case _start_cursor_pos is undefined.
pos = self._start_cursor_pos pos = self._start_cursor_pos