forked from VimPlug/jedi
Trying to change used_names, so that they don't contain name definitions from CompFor.
This commit is contained in:
@@ -136,8 +136,8 @@ class Evaluator(object):
|
|||||||
if seek_name:
|
if seek_name:
|
||||||
types = finder.check_tuple_assignments(types, seek_name)
|
types = finder.check_tuple_assignments(types, seek_name)
|
||||||
|
|
||||||
ass_details = stmt.assignment_details
|
#ass_details = stmt.assignment_details
|
||||||
if ass_details and ass_details[0][1] != '=' and not isinstance(stmt, er.InstanceElement): # TODO don't check for this.
|
if False and stmt.assignment_details and ass_details[0][1] != '=' and not isinstance(stmt, er.InstanceElement): # TODO don't check for this.
|
||||||
expr_list, _operator = ass_details[0]
|
expr_list, _operator = ass_details[0]
|
||||||
# `=` is always the last character in aug assignments -> -1
|
# `=` is always the last character in aug assignments -> -1
|
||||||
operator = copy.copy(_operator)
|
operator = copy.copy(_operator)
|
||||||
@@ -156,7 +156,7 @@ class Evaluator(object):
|
|||||||
result = left
|
result = left
|
||||||
else:
|
else:
|
||||||
result = precedence.calculate(self, left, operator, result)
|
result = precedence.calculate(self, left, operator, result)
|
||||||
elif len(stmt.get_defined_names()) > 1 and seek_name and ass_details:
|
elif False and len(stmt.get_defined_names()) > 1 and seek_name and ass_details:
|
||||||
# Assignment checking is only important if the statement defines
|
# Assignment checking is only important if the statement defines
|
||||||
# multiple variables.
|
# multiple variables.
|
||||||
new_result = []
|
new_result = []
|
||||||
@@ -201,8 +201,8 @@ class Evaluator(object):
|
|||||||
if isinstance(atom, pr.Name):
|
if isinstance(atom, pr.Name):
|
||||||
# This is the first global lookup.
|
# This is the first global lookup.
|
||||||
stmt = atom.get_definition()
|
stmt = atom.get_definition()
|
||||||
return self.find_types(stmt.get_parent_until(pr.IsScope), atom,
|
scope = stmt.get_parent_until(pr.IsScope, include_current=True)
|
||||||
stmt.start_pos, search_global=True)
|
return self.find_types(scope, atom, stmt.start_pos, search_global=True)
|
||||||
elif isinstance(atom, pr.Literal):
|
elif isinstance(atom, pr.Literal):
|
||||||
return [compiled.create(self, atom.eval())]
|
return [compiled.create(self, atom.eval())]
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ class NameFinder(object):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
names = [name for name in names if name.is_definition()]
|
|
||||||
names = pr.filter_after_position(names, position)
|
names = pr.filter_after_position(names, position)
|
||||||
|
names = [name for name in names if name.is_definition()]
|
||||||
|
|
||||||
# Only the names defined in the last position are valid definitions.
|
# Only the names defined in the last position are valid definitions.
|
||||||
last_names = []
|
last_names = []
|
||||||
@@ -287,12 +287,8 @@ class NameFinder(object):
|
|||||||
types += check_tuple_assignments(for_types, name)
|
types += check_tuple_assignments(for_types, name)
|
||||||
elif isinstance(typ, pr.Param):
|
elif isinstance(typ, pr.Param):
|
||||||
types += self._eval_param(typ)
|
types += self._eval_param(typ)
|
||||||
elif typ.isinstance(pr.ExprStmt):
|
elif typ.isinstance(pr.ExprStmt, pr.CompFor):
|
||||||
if typ.is_global():
|
types += self._remove_statements(typ, name)
|
||||||
# global keyword handling.
|
|
||||||
types += evaluator.find_types(typ.parent.parent, str(name))
|
|
||||||
else:
|
|
||||||
types += self._remove_statements(typ, name)
|
|
||||||
elif isinstance(typ, pr.Import):
|
elif isinstance(typ, pr.Import):
|
||||||
types += imports.ImportWrapper(self._evaluator, name).follow()
|
types += imports.ImportWrapper(self._evaluator, name).follow()
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ class Array(IterableWrapper):
|
|||||||
if array_node in (']', '}', ')'):
|
if array_node in (']', '}', ')'):
|
||||||
return [] # Direct closing bracket, doesn't contain items.
|
return [] # Direct closing bracket, doesn't contain items.
|
||||||
|
|
||||||
if pr.is_node(array_node, 'testlist_comp', 'testlist_star_expr', 'testlist'):
|
if pr.is_node(array_node, 'testlist_comp'):
|
||||||
return array_node.children[::2]
|
return array_node.children[::2]
|
||||||
elif pr.is_node(array_node, 'dictorsetmaker'):
|
elif pr.is_node(array_node, 'dictorsetmaker'):
|
||||||
kv = []
|
kv = []
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ class Parser(object):
|
|||||||
'for_stmt': pr.ForStmt,
|
'for_stmt': pr.ForStmt,
|
||||||
'while_stmt': pr.WhileStmt,
|
'while_stmt': pr.WhileStmt,
|
||||||
'try_stmt': pr.TryStmt,
|
'try_stmt': pr.TryStmt,
|
||||||
|
'comp_for': pr.CompFor,
|
||||||
}
|
}
|
||||||
|
|
||||||
self._ast_mapping = dict((getattr(pytree.python_symbols, k), v)
|
self._ast_mapping = dict((getattr(pytree.python_symbols, k), v)
|
||||||
@@ -126,6 +127,11 @@ class Parser(object):
|
|||||||
arr = self.scope_names_stack[-1].setdefault(n.value, [])
|
arr = self.scope_names_stack[-1].setdefault(n.value, [])
|
||||||
arr.append(n)
|
arr.append(n)
|
||||||
new_node.names_dict = scope_names
|
new_node.names_dict = scope_names
|
||||||
|
elif isinstance(new_node, pr.CompFor):
|
||||||
|
# The name definitions of comprehenions shouldn't be part of the
|
||||||
|
# current scope. They are part of the comprehension scope.
|
||||||
|
for n in new_node.get_defined_names():
|
||||||
|
self.scope_names_stack[-1][n.value].remove(n)
|
||||||
return new_node
|
return new_node
|
||||||
|
|
||||||
def convert_leaf(self, grammar, type, value, prefix, start_pos):
|
def convert_leaf(self, grammar, type, value, prefix, start_pos):
|
||||||
@@ -176,8 +182,11 @@ class Parser(object):
|
|||||||
clear_names(c.children)
|
clear_names(c.children)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
if isinstance(c, pr.Name):
|
if isinstance(c, pr.Name):
|
||||||
self.scope_names_stack[-1][c.value].remove(c)
|
try:
|
||||||
self.used_names[c.value].remove(c)
|
self.scope_names_stack[-1][c.value].remove(c)
|
||||||
|
self.used_names[c.value].remove(c)
|
||||||
|
except ValueError:
|
||||||
|
pass # This may happen with CompFor.
|
||||||
|
|
||||||
for dfa, state, node in stack[start_index:]:
|
for dfa, state, node in stack[start_index:]:
|
||||||
clear_names(children=node[1])
|
clear_names(children=node[1])
|
||||||
|
|||||||
@@ -253,7 +253,19 @@ class Name(Leaf):
|
|||||||
self.start_pos[0], self.start_pos[1])
|
self.start_pos[0], self.start_pos[1])
|
||||||
|
|
||||||
def get_definition(self):
|
def get_definition(self):
|
||||||
return self.parent.get_parent_until((ArrayStmt, StatementElement, Node), reverse=True)
|
scope = self.parent
|
||||||
|
while scope.parent is not None:
|
||||||
|
if scope.isinstance(Node):
|
||||||
|
if scope.type == python_symbols.testlist_comp:
|
||||||
|
try:
|
||||||
|
if isinstance(scope.children[1], CompFor):
|
||||||
|
return scope.children[1]
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
scope = scope.parent
|
||||||
|
return scope
|
||||||
|
|
||||||
def is_definition(self):
|
def is_definition(self):
|
||||||
stmt = self.get_definition()
|
stmt = self.get_definition()
|
||||||
@@ -264,7 +276,7 @@ class Name(Leaf):
|
|||||||
elif isinstance(stmt, Param):
|
elif isinstance(stmt, Param):
|
||||||
return self == stmt.get_name()
|
return self == stmt.get_name()
|
||||||
else:
|
else:
|
||||||
return isinstance(stmt, (ExprStmt, Import)) \
|
return isinstance(stmt, (ExprStmt, Import, CompFor)) \
|
||||||
and self in stmt.get_defined_names()
|
and self in stmt.get_defined_names()
|
||||||
|
|
||||||
def assignment_indexes(self):
|
def assignment_indexes(self):
|
||||||
@@ -289,6 +301,8 @@ class Name(Leaf):
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise LookupError("Couldn't find the assignment.")
|
raise LookupError("Couldn't find the assignment.")
|
||||||
|
elif isinstance(node, (ExprStmt, CompFor)):
|
||||||
|
break
|
||||||
|
|
||||||
compare = node
|
compare = node
|
||||||
node = node.parent
|
node = node.parent
|
||||||
@@ -1131,6 +1145,27 @@ class YieldExpr(Simple):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _defined_names(current):
|
||||||
|
"""
|
||||||
|
A helper function to find the defined names in statements, for loops and
|
||||||
|
list comprehensions.
|
||||||
|
"""
|
||||||
|
names = []
|
||||||
|
if is_node(current, 'testlist_star_expr', 'testlist_comp', 'exprlist'):
|
||||||
|
for child in current.children[::2]:
|
||||||
|
names += _defined_names(child)
|
||||||
|
elif is_node(current, 'atom'):
|
||||||
|
names += _defined_names(current.children[1])
|
||||||
|
elif is_node(current, 'power'):
|
||||||
|
if current.children[-2] != '**': # Just if there's no operation
|
||||||
|
trailer = current.children[-1]
|
||||||
|
if trailer.children[0] == '.':
|
||||||
|
names.append(trailer.children[1])
|
||||||
|
else:
|
||||||
|
names.append(current)
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
class Statement(Simple, DocstringMixin):
|
class Statement(Simple, DocstringMixin):
|
||||||
"""
|
"""
|
||||||
This is the class for all the possible statements. Which means, this class
|
This is the class for all the possible statements. Which means, this class
|
||||||
@@ -1167,23 +1202,7 @@ class Statement(Simple, DocstringMixin):
|
|||||||
self.expression_list()
|
self.expression_list()
|
||||||
|
|
||||||
def get_defined_names(self):
|
def get_defined_names(self):
|
||||||
def check_tuple(current):
|
return list(chain.from_iterable(_defined_names(self.children[i])
|
||||||
names = []
|
|
||||||
if is_node(current, 'testlist_star_expr') or is_node(current, 'testlist_comp'):
|
|
||||||
for child in current.children[::2]:
|
|
||||||
names += check_tuple(child)
|
|
||||||
elif is_node(current, 'atom'):
|
|
||||||
names += check_tuple(current.children[1])
|
|
||||||
elif is_node(current, 'power'):
|
|
||||||
if current.children[-2] != '**': # Just if there's no operation
|
|
||||||
trailer = current.children[-1]
|
|
||||||
if trailer.children[0] == '.':
|
|
||||||
names.append(trailer.children[1])
|
|
||||||
else:
|
|
||||||
names.append(current)
|
|
||||||
return names
|
|
||||||
|
|
||||||
return list(chain.from_iterable(check_tuple(self.children[i])
|
|
||||||
for i in range(0, len(self.children) - 2, 2)
|
for i in range(0, len(self.children) - 2, 2)
|
||||||
if self.children[i + 1].value == '='))
|
if self.children[i + 1].value == '='))
|
||||||
|
|
||||||
@@ -1247,10 +1266,6 @@ class Statement(Simple, DocstringMixin):
|
|||||||
as_name.start_pos, as_name.end_pos, self))
|
as_name.start_pos, as_name.end_pos, self))
|
||||||
return dct
|
return dct
|
||||||
|
|
||||||
def is_global(self):
|
|
||||||
p = self.parent
|
|
||||||
return isinstance(p, KeywordStatement) and p.name == 'global'
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def assignment_details(self):
|
def assignment_details(self):
|
||||||
"""
|
"""
|
||||||
@@ -1483,6 +1498,28 @@ class Array(StatementElement):
|
|||||||
return "<%s: %s%s>" % (type(self).__name__, typ, self.values)
|
return "<%s: %s%s>" % (type(self).__name__, typ, self.values)
|
||||||
|
|
||||||
|
|
||||||
|
class CompFor(Simple):
|
||||||
|
def is_scope(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def names_dict(self):
|
||||||
|
dct = {}
|
||||||
|
for name in self.get_defined_names():
|
||||||
|
arr = dct.setdefault(name.value, [])
|
||||||
|
arr.append(name)
|
||||||
|
return dct
|
||||||
|
|
||||||
|
def get_rhs(self):
|
||||||
|
return self.children[3]
|
||||||
|
|
||||||
|
def get_defined_names(self):
|
||||||
|
return _defined_names(self.children[1])
|
||||||
|
|
||||||
|
def scope_names_generator(self, position):
|
||||||
|
yield self, []
|
||||||
|
|
||||||
|
|
||||||
class ListComprehension(ForFlow):
|
class ListComprehension(ForFlow):
|
||||||
""" Helper class for list comprehensions """
|
""" Helper class for list comprehensions """
|
||||||
def __init__(self, module, stmt, middle, input, parent):
|
def __init__(self, module, stmt, middle, input, parent):
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ a[0]
|
|||||||
|
|
||||||
arr = [1,'']
|
arr = [1,'']
|
||||||
a = [a for a in arr]
|
a = [a for a in arr]
|
||||||
#? int() str()
|
#? int()
|
||||||
a[0]
|
a[0]
|
||||||
|
|
||||||
a = [a if 1.0 else '' for a in [1] if [1.0]]
|
a = [a if 1.0 else '' for a in [1] if [1.0]]
|
||||||
|
|||||||
Reference in New Issue
Block a user