1
0
forked from VimPlug/jedi

Change implementation of StatementElement.

Instead of having both next and execution as attributes, we now only have next, because it's an execution if there's an array.
This commit is contained in:
Dave Halter
2014-08-18 22:25:55 +02:00
parent 7619bf27d1
commit 8006d6f190
7 changed files with 36 additions and 52 deletions

View File

@@ -22,7 +22,7 @@ def usages(evaluator, definitions, search_name, mods):
while not stmt.parent.is_scope(): while not stmt.parent.is_scope():
stmt = stmt.parent stmt = stmt.parent
# New definition, call cannot be a part of stmt # New definition, call cannot be a part of stmt
if len(call.name) == 1 and call.execution is None \ if len(call.name) == 1 and call.next is None \
and call.name in stmt.get_defined_names(): and call.name in stmt.get_defined_names():
# Class params are not definitions (like function params). They # Class params are not definitions (like function params). They
# are super classes, that need to be resolved. # are super classes, that need to be resolved.

View File

@@ -243,7 +243,7 @@ def save_parser(path, name, parser, pickling=True):
class ParserPickling(object): class ParserPickling(object):
version = 14 version = 15
""" """
Version number (integer) for file system cache. Version number (integer) for file system cache.

View File

@@ -161,7 +161,8 @@ def _check_for_exception_catch(evaluator, jedi_obj, exception, payload=None):
assert len(expression_list) == 1 assert len(expression_list) == 1
call = expression_list[0] call = expression_list[0]
assert isinstance(call, pr.Call) and str(call.name) == 'hasattr' assert isinstance(call, pr.Call) and str(call.name) == 'hasattr'
execution = call.execution assert call.next_is_execution()
execution = call.next
assert execution and len(execution) == 2 assert execution and len(execution) == 2
# check if the names match # check if the names match

View File

@@ -187,7 +187,7 @@ class NameFinder(object):
# Compare start_pos, because names may be different # Compare start_pos, because names may be different
# because of executions. # because of executions.
if c.name.start_pos == name.start_pos \ if c.name.start_pos == name.start_pos \
and c.execution: and isinstance(c.next, pr.Array):
return True return True
return False return False
@@ -391,10 +391,10 @@ def _check_isinstance_type(evaluator, stmt, search_name_part):
assert len(expression_list) == 1 assert len(expression_list) == 1
call = expression_list[0] call = expression_list[0]
assert isinstance(call, pr.Call) and str(call.name) == 'isinstance' assert isinstance(call, pr.Call) and str(call.name) == 'isinstance'
assert bool(call.execution) assert call.next_is_execution()
# isinstance check # isinstance check
isinst = call.execution.values isinst = call.next.values
assert len(isinst) == 2 # has two params assert len(isinst) == 2 # has two params
obj, classes = [statement.expression_list() for statement in isinst] obj, classes = [statement.expression_list() for statement in isinst]
assert len(obj) == 1 assert len(obj) == 1

View File

@@ -96,11 +96,11 @@ def call_signature_array_for_pos(stmt, pos):
# Since we need the index, we duplicate efforts (with empty # Since we need the index, we duplicate efforts (with empty
# arrays). # arrays).
if arr.start_pos < pos <= stmt.end_pos: if arr.start_pos < pos <= stmt.end_pos:
if arr.type in accepted_types and isinstance(origin_call, pr.Call): if arr.type in accepted_types and origin_call:
return arr, i, origin_call return arr, i, origin_call
if len(arr) == 0 and arr.start_pos < pos < arr.end_pos: if len(arr) == 0 and arr.start_pos < pos < arr.end_pos:
if arr.type in accepted_types and isinstance(origin_call, pr.Call): if arr.type in accepted_types and origin_call:
return arr, 0, origin_call return arr, 0, origin_call
return None, 0, None return None, 0, None
@@ -109,8 +109,6 @@ def call_signature_array_for_pos(stmt, pos):
if call.next is not None: if call.next is not None:
method = search_array if isinstance(call.next, pr.Array) else search_call method = search_array if isinstance(call.next, pr.Array) else search_call
tup = method(call.next, pos, origin_call or call) tup = method(call.next, pos, origin_call or call)
if not tup[0] and call.execution is not None:
tup = search_array(call.execution, pos, origin_call)
return tup return tup
if stmt.start_pos >= pos >= stmt.end_pos: if stmt.start_pos >= pos >= stmt.end_pos:
@@ -142,11 +140,9 @@ def search_call_signatures(user_stmt, position):
# statement. # statement.
stmt_el = call stmt_el = call
while isinstance(stmt_el, pr.StatementElement): while isinstance(stmt_el, pr.StatementElement):
if stmt_el.execution == arr: if stmt_el.next == arr:
stmt_el.execution = None
stmt_el.next = None stmt_el.next = None
break break
stmt_el = stmt_el.next stmt_el = stmt_el.next
debug.speed('func_call parsed') debug.speed('func_call parsed')
@@ -178,13 +174,14 @@ def scan_statement_for_calls(stmt, search_name, assignment_details=False):
elif isinstance(c, pr.Call): elif isinstance(c, pr.Call):
s_new = c s_new = c
while s_new is not None: while s_new is not None:
n = s_new.name if isinstance(s_new, pr.Array):
if isinstance(n, pr.Name) \ result += scan_array(s_new, search_name)
and search_name in [str(x) for x in n.names]: else:
result.append(c) n = s_new.name
if isinstance(n, pr.Name) \
and search_name in [str(x) for x in n.names]:
result.append(c)
if s_new.execution is not None:
result += scan_array(s_new.execution, search_name)
s_new = s_new.next s_new = s_new.next
elif isinstance(c, pr.ListComprehension): elif isinstance(c, pr.ListComprehension):
for s in c.stmt, c.middle, c.input: for s in c.stmt, c.middle, c.input:

View File

@@ -71,17 +71,20 @@ def _paths_from_insert(module_path, exe):
""" extract the inserted module path from an "sys.path.insert" statement """ extract the inserted module path from an "sys.path.insert" statement
""" """
exe_type, exe.type = exe.type, pr.Array.NOARRAY exe_type, exe.type = exe.type, pr.Array.NOARRAY
exe_pop = exe.values.pop(0) try:
res = _execute_code(module_path, exe.get_code()) exe_pop = exe.values.pop(0)
exe.type = exe_type res = _execute_code(module_path, exe.get_code())
finally:
exe.type = exe_type
exe.values.insert(0, exe_pop) exe.values.insert(0, exe_pop)
return res return res
def _paths_from_call_expression(module_path, call): def _paths_from_call_expression(module_path, call):
""" extract the path from either "sys.path.append" or "sys.path.insert" """ """ extract the path from either "sys.path.append" or "sys.path.insert" """
if call.execution is None: if not call.next_is_execution():
return return
n = call.name n = call.name
if not isinstance(n, pr.Name) or len(n.names) != 3: if not isinstance(n, pr.Name) or len(n.names) != 3:
return return
@@ -89,7 +92,7 @@ def _paths_from_call_expression(module_path, call):
if names[:2] != ['sys', 'path']: if names[:2] != ['sys', 'path']:
return return
cmd = names[2] cmd = names[2]
exe = call.execution exe = call.next
if cmd == 'insert' and len(exe) == 2: if cmd == 'insert' and len(exe) == 2:
path = _paths_from_insert(module_path, exe) path = _paths_from_insert(module_path, exe)
elif cmd == 'append' and len(exe) == 1: elif cmd == 'append' and len(exe) == 1:
@@ -109,10 +112,8 @@ def _check_module(module):
if len(expressions) == 1 and isinstance(expressions[0], pr.Call): if len(expressions) == 1 and isinstance(expressions[0], pr.Call):
sys_path.extend( sys_path.extend(
_paths_from_call_expression(module.path, expressions[0]) or []) _paths_from_call_expression(module.path, expressions[0]) or [])
elif ( elif hasattr(stmt, 'assignment_details') \
hasattr(stmt, 'assignment_details') and and len(stmt.assignment_details) == 1:
len(stmt.assignment_details) == 1
):
sys_path.extend(_paths_from_assignment(stmt) or []) sys_path.extend(_paths_from_assignment(stmt) or [])
return sys_path return sys_path

View File

@@ -952,7 +952,8 @@ class Statement(Simple, DocstringMixin):
# not a set_var. # not a set_var.
is_execution = False is_execution = False
while c: while c:
if Array.is_type(c.execution, Array.TUPLE): # TODO use StatementElement.next_is_execution
if Array.is_type(c.next, Array.TUPLE):
is_execution = True is_execution = True
c = c.next c = c.next
if is_execution: if is_execution:
@@ -1194,7 +1195,7 @@ class Statement(Simple, DocstringMixin):
token_iterator, brackets[tok.string], tok.start_pos token_iterator, brackets[tok.string], tok.start_pos
) )
if result and isinstance(result[-1], StatementElement): if result and isinstance(result[-1], StatementElement):
result[-1].set_execution(arr) result[-1].set_next(arr)
else: else:
arr.parent = self arr.parent = self
result.append(arr) result.append(arr)
@@ -1264,7 +1265,7 @@ class Param(Statement):
class StatementElement(Simple): class StatementElement(Simple):
__slots__ = ('parent', 'next', 'execution') __slots__ = ('parent', 'next')
def __init__(self, module, start_pos, end_pos, parent): def __init__(self, module, start_pos, end_pos, parent):
super(StatementElement, self).__init__(module, start_pos, end_pos) super(StatementElement, self).__init__(module, start_pos, end_pos)
@@ -1273,7 +1274,6 @@ class StatementElement(Simple):
# be an array. # be an array.
self.parent = parent self.parent = parent
self.next = None self.next = None
self.execution = None
def set_next(self, call): def set_next(self, call):
""" Adds another part of the statement""" """ Adds another part of the statement"""
@@ -1283,18 +1283,8 @@ class StatementElement(Simple):
else: else:
self.next = call self.next = call
def set_execution(self, call): def next_is_execution(self):
""" return Array.is_type(self.next, Array.TUPLE, Array.NOARRAY)
An execution is nothing else than brackets, with params in them, which
shows access on the internals of this name.
"""
call.parent = self.parent
if self.next is not None:
self.next.set_execution(call)
elif self.execution is not None:
self.execution.set_execution(call)
else:
self.execution = call
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. """
@@ -1303,20 +1293,15 @@ class StatementElement(Simple):
yield name_part yield name_part
except AttributeError: except AttributeError:
yield self yield self
if self.execution is not None:
for y in self.execution.generate_call_path():
yield y
if self.next is not None: if self.next is not None:
for y in self.next.generate_call_path(): for y in self.next.generate_call_path():
yield y yield y
def get_code(self): def get_code(self):
s = ''
if self.execution is not None:
s += self.execution.get_code()
if self.next is not None: if self.next is not None:
s += '.' + self.next.get_code() s = '.' if isinstance(self, Array) else ''
return s return s + self.next.get_code()
return ''
class Call(StatementElement): class Call(StatementElement):