forked from VimPlug/jedi
Enable better ways for analysis to analyze loop variables.
This commit is contained in:
@@ -570,7 +570,7 @@ class Script(object):
|
||||
# Iterate tuples.
|
||||
unpack_tuple_to_dict(self._evaluator, types, testlist)
|
||||
else:
|
||||
try_iter_content(self._evaluator.eval_element(node))
|
||||
try_iter_content(self._evaluator.goto_definition(node))
|
||||
|
||||
ana = [a for a in self._evaluator.analysis if self.path == a.path]
|
||||
return sorted(set(ana), key=lambda x: x.line)
|
||||
|
||||
@@ -409,9 +409,15 @@ class Evaluator(object):
|
||||
# TODO rename to goto_definitions
|
||||
def_ = name.get_definition()
|
||||
if def_.type == 'expr_stmt' and name in def_.get_defined_names():
|
||||
return self.eval_statement(def_, name)
|
||||
call = helpers.call_of_name(name)
|
||||
return self.eval_element(call)
|
||||
types = self.eval_statement(def_, name)
|
||||
elif def_.type == 'for_stmt':
|
||||
container_types = self.eval_element(def_.children[3])
|
||||
for_types = iterable.py__iter__types(self, container_types, def_.children[3])
|
||||
types = finder.check_tuple_assignments(self, for_types, name)
|
||||
else:
|
||||
call = helpers.call_of_name(name)
|
||||
types = self.eval_element(call)
|
||||
return types
|
||||
|
||||
def goto(self, name):
|
||||
def resolve_implicit_imports(names):
|
||||
|
||||
@@ -251,7 +251,6 @@ class NameFinder(object):
|
||||
def _names_to_types(self, names, search_global):
|
||||
types = set()
|
||||
|
||||
debug.warning('start nt %s', names)
|
||||
# Add isinstance and other if/assert knowledge.
|
||||
if isinstance(self.name_str, tree.Name):
|
||||
# Ignore FunctionExecution parents for now.
|
||||
|
||||
@@ -452,7 +452,6 @@ def py__getitem__(evaluator, types, index, node):
|
||||
if isinstance(typ, Array) and typ.type == 'dict':
|
||||
types.remove(typ)
|
||||
result |= typ.dict_values()
|
||||
print('ITER', types, py__iter__types(evaluator, types))
|
||||
return result | py__iter__types(evaluator, types)
|
||||
|
||||
for typ in types:
|
||||
|
||||
@@ -144,6 +144,51 @@ class Base(object):
|
||||
scope = scope.parent
|
||||
return scope
|
||||
|
||||
def get_definition(self):
|
||||
scope = self
|
||||
while scope.parent is not None:
|
||||
parent = scope.parent
|
||||
if scope.isinstance(Node, Name) and parent.type != 'simple_stmt':
|
||||
if scope.type == 'testlist_comp':
|
||||
try:
|
||||
if isinstance(scope.children[1], CompFor):
|
||||
return scope.children[1]
|
||||
except IndexError:
|
||||
pass
|
||||
scope = parent
|
||||
else:
|
||||
break
|
||||
return scope
|
||||
|
||||
def assignment_indexes(self):
|
||||
"""
|
||||
Returns an array of tuple(int, node) of the indexes that are used in
|
||||
tuple assignments.
|
||||
|
||||
For example if the name is ``y`` in the following code::
|
||||
|
||||
x, (y, z) = 2, ''
|
||||
|
||||
would result in ``[(1, xyz_node), (0, yz_node)]``.
|
||||
"""
|
||||
indexes = []
|
||||
node = self.parent
|
||||
compare = self
|
||||
while node is not None:
|
||||
if is_node(node, 'testlist_comp', 'testlist_star_expr', 'exprlist'):
|
||||
for i, child in enumerate(node.children):
|
||||
if child == compare:
|
||||
indexes.insert(0, (int(i / 2), node))
|
||||
break
|
||||
else:
|
||||
raise LookupError("Couldn't find the assignment.")
|
||||
elif isinstance(node, (ExprStmt, CompFor)):
|
||||
break
|
||||
|
||||
compare = node
|
||||
node = node.parent
|
||||
return indexes
|
||||
|
||||
def is_scope(self):
|
||||
# Default is not being a scope. Just inherit from Scope.
|
||||
return False
|
||||
@@ -288,22 +333,6 @@ class Name(Leaf):
|
||||
return "<%s: %s@%s,%s>" % (type(self).__name__, self.value,
|
||||
self.start_pos[0], self.start_pos[1])
|
||||
|
||||
def get_definition(self):
|
||||
scope = self
|
||||
while scope.parent is not None:
|
||||
parent = scope.parent
|
||||
if scope.isinstance(Node, Name) and parent.type != 'simple_stmt':
|
||||
if scope.type == 'testlist_comp':
|
||||
try:
|
||||
if isinstance(scope.children[1], CompFor):
|
||||
return scope.children[1]
|
||||
except IndexError:
|
||||
pass
|
||||
scope = parent
|
||||
else:
|
||||
break
|
||||
return scope
|
||||
|
||||
def is_definition(self):
|
||||
stmt = self.get_definition()
|
||||
if stmt.type in ('funcdef', 'classdef', 'file_input', 'param'):
|
||||
@@ -317,35 +346,6 @@ class Name(Leaf):
|
||||
'comp_for', 'with_stmt') \
|
||||
and self in stmt.get_defined_names()
|
||||
|
||||
def assignment_indexes(self):
|
||||
"""
|
||||
Returns an array of tuple(int, node) of the indexes that are used in
|
||||
tuple assignments.
|
||||
|
||||
For example if the name is ``y`` in the following code::
|
||||
|
||||
x, (y, z) = 2, ''
|
||||
|
||||
would result in ``[(1, xyz_node), (0, yz_node)]``.
|
||||
"""
|
||||
indexes = []
|
||||
node = self.parent
|
||||
compare = self
|
||||
while node is not None:
|
||||
if is_node(node, 'testlist_comp', 'testlist_star_expr', 'exprlist'):
|
||||
for i, child in enumerate(node.children):
|
||||
if child == compare:
|
||||
indexes.insert(0, (int(i / 2), node))
|
||||
break
|
||||
else:
|
||||
raise LookupError("Couldn't find the assignment.")
|
||||
elif isinstance(node, (ExprStmt, CompFor)):
|
||||
break
|
||||
|
||||
compare = node
|
||||
node = node.parent
|
||||
return indexes
|
||||
|
||||
def nodes_to_execute(self, last_added=False):
|
||||
if last_added is False:
|
||||
yield self
|
||||
@@ -500,7 +500,8 @@ class Node(BaseNode):
|
||||
_IGNORE_EXECUTE_NODES = set([
|
||||
'suite', 'subscriptlist', 'subscript', 'simple_stmt', 'sliceop',
|
||||
'testlist_comp', 'dictorsetmaker', 'trailer', 'decorators',
|
||||
'decorated', 'arglist', 'argument'
|
||||
'decorated', 'arglist', 'argument', 'exprlist', 'testlist',
|
||||
'testlist_safe', 'testlist1'
|
||||
])
|
||||
|
||||
def __init__(self, type, children):
|
||||
@@ -1024,12 +1025,6 @@ class ForStmt(Flow):
|
||||
type = 'for_stmt'
|
||||
__slots__ = ()
|
||||
|
||||
def nodes_to_execute(self, last_added=False):
|
||||
# We shouldn't include the definitions.
|
||||
for child in self.children[3:]:
|
||||
for node_to_execute in child.nodes_to_execute():
|
||||
yield node_to_execute
|
||||
|
||||
def get_input_node(self):
|
||||
"""
|
||||
Returns the input node ``y`` from: ``for x in y:``.
|
||||
|
||||
@@ -4,3 +4,11 @@ a
|
||||
|
||||
x = [1]
|
||||
x[0], b = {'a': 1, 'b': '2'}
|
||||
|
||||
dct = {3: ''}
|
||||
for x in dct:
|
||||
pass
|
||||
|
||||
#! 4 type-error-not-iterable
|
||||
for x, y in dct:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user