forked from VimPlug/jedi
Remove quite a bit of the old parser representation logic.
This commit is contained in:
@@ -136,7 +136,6 @@ 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
|
|
||||||
first_operation = stmt.first_operation()
|
first_operation = stmt.first_operation()
|
||||||
if first_operation not in ('=', None) and not isinstance(stmt, er.InstanceElement): # TODO don't check for this.
|
if first_operation not in ('=', None) and not isinstance(stmt, er.InstanceElement): # TODO don't check for this.
|
||||||
# `=` is always the last character in aug assignments -> -1
|
# `=` is always the last character in aug assignments -> -1
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ class NameFinder(object):
|
|||||||
# might still have conditions if defined outside of the
|
# might still have conditions if defined outside of the
|
||||||
# current scope.
|
# current scope.
|
||||||
if isinstance(stmt, (pr.Param, pr.Import)) \
|
if isinstance(stmt, (pr.Param, pr.Import)) \
|
||||||
or isinstance(name_list_scope, (pr.Lambda, pr.ListComprehension, er.Instance, InterpreterNamespace)) \
|
or isinstance(name_list_scope, (pr.Lambda, er.Instance, InterpreterNamespace)) \
|
||||||
or isinstance(scope, compiled.CompiledObject):
|
or isinstance(scope, compiled.CompiledObject):
|
||||||
# Always reachable.
|
# Always reachable.
|
||||||
names.append(name)
|
names.append(name)
|
||||||
@@ -248,6 +248,9 @@ class NameFinder(object):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _name_is_array_assignment(self, name, stmt):
|
def _name_is_array_assignment(self, name, stmt):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# TODO DELETE this? or change it?
|
||||||
if stmt.isinstance(pr.ExprStmt):
|
if stmt.isinstance(pr.ExprStmt):
|
||||||
def is_execution(calls):
|
def is_execution(calls):
|
||||||
for c in calls:
|
for c in calls:
|
||||||
@@ -528,9 +531,6 @@ def get_names_of_scope(evaluator, scope, position=None, star_search=True, includ
|
|||||||
:rtype: [(pr.Scope, [pr.Name])]
|
:rtype: [(pr.Scope, [pr.Name])]
|
||||||
:return: Return an generator that yields a pair of scope and names.
|
:return: Return an generator that yields a pair of scope and names.
|
||||||
"""
|
"""
|
||||||
if isinstance(scope, pr.ListComprehension):
|
|
||||||
position = scope.parent.start_pos
|
|
||||||
|
|
||||||
in_func_scope = scope
|
in_func_scope = scope
|
||||||
non_flow = scope.get_parent_until(pr.Flow, reverse=True)
|
non_flow = scope.get_parent_until(pr.Flow, reverse=True)
|
||||||
while scope:
|
while scope:
|
||||||
@@ -554,9 +554,6 @@ def get_names_of_scope(evaluator, scope, position=None, star_search=True, includ
|
|||||||
|
|
||||||
for g in scope.scope_names_generator(position):
|
for g in scope.scope_names_generator(position):
|
||||||
yield g
|
yield g
|
||||||
if scope.isinstance(pr.ListComprehension):
|
|
||||||
# is a list comprehension
|
|
||||||
yield scope, scope.get_defined_names(is_internal_call=True)
|
|
||||||
|
|
||||||
scope = scope.parent
|
scope = scope.parent
|
||||||
# This is used, because subscopes (Flow scopes) would distort the
|
# This is used, because subscopes (Flow scopes) would distort the
|
||||||
|
|||||||
@@ -199,7 +199,8 @@ def search_call_signatures(user_stmt, position):
|
|||||||
# Now remove the part after the call. Including the array from the
|
# Now remove the part after the call. Including the array from the
|
||||||
# statement.
|
# statement.
|
||||||
stmt_el = call
|
stmt_el = call
|
||||||
while isinstance(stmt_el, pr.StatementElement):
|
# TODO REMOVE this? or change?
|
||||||
|
while False and isinstance(stmt_el, pr.StatementElement):
|
||||||
if stmt_el.next == arr:
|
if stmt_el.next == arr:
|
||||||
stmt_el.next = None
|
stmt_el.next = None
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -1294,56 +1294,13 @@ class Statement(Simple, DocstringMixin):
|
|||||||
:type start_pos: 2-tuple of int
|
:type start_pos: 2-tuple of int
|
||||||
:param start_pos: Position (line, column) of the Statement.
|
:param start_pos: Position (line, column) of the Statement.
|
||||||
"""
|
"""
|
||||||
__slots__ = ('_token_list', '_set_vars', 'as_names', '_expression_list',
|
__slots__ = ()
|
||||||
'_assignment_details', '_names_are_set_vars', '_doc_token')
|
|
||||||
|
|
||||||
def __init__old(self, children, parent=None,):
|
|
||||||
super(Statement, self).__init__(module, start_pos, end_pos, parent)
|
|
||||||
self._token_list = token_list
|
|
||||||
self._names_are_set_vars = names_are_set_vars
|
|
||||||
if set_name_parents:
|
|
||||||
for n in as_names:
|
|
||||||
n.parent = self.use_as_parent
|
|
||||||
self._doc_token = None
|
|
||||||
self._set_vars = None
|
|
||||||
self.as_names = list(as_names)
|
|
||||||
|
|
||||||
# cache
|
|
||||||
self._assignment_details = []
|
|
||||||
# For now just generate the expression list, even if its not needed.
|
|
||||||
# This will help to adapt a better new AST.
|
|
||||||
self.expression_list()
|
|
||||||
|
|
||||||
def get_defined_names(self):
|
def get_defined_names(self):
|
||||||
return list(chain.from_iterable(_defined_names(self.children[i])
|
return list(chain.from_iterable(_defined_names(self.children[i])
|
||||||
for i in range(0, len(self.children) - 2, 2)
|
for i in range(0, len(self.children) - 2, 2)
|
||||||
if '=' in self.children[i + 1].value))
|
if '=' in self.children[i + 1].value))
|
||||||
|
|
||||||
|
|
||||||
"""Get the names for the statement."""
|
|
||||||
if self._set_vars is None:
|
|
||||||
|
|
||||||
def search_calls(calls):
|
|
||||||
for call in calls:
|
|
||||||
if isinstance(call, Array) and call.type != Array.DICT:
|
|
||||||
for stmt in call:
|
|
||||||
search_calls(stmt.expression_list())
|
|
||||||
elif isinstance(call, Call):
|
|
||||||
# Check if there's an execution in it, if so this is
|
|
||||||
# not a set_var.
|
|
||||||
if not call.next:
|
|
||||||
self._set_vars.append(call.name)
|
|
||||||
continue
|
|
||||||
|
|
||||||
self._set_vars = []
|
|
||||||
for calls, operation in self.assignment_details:
|
|
||||||
search_calls(calls)
|
|
||||||
|
|
||||||
if not self.assignment_details and self._names_are_set_vars:
|
|
||||||
# In the case of Param, it's also a defining name without ``=``
|
|
||||||
search_calls(self.expression_list())
|
|
||||||
return self._set_vars + self.as_names
|
|
||||||
|
|
||||||
def get_rhs(self):
|
def get_rhs(self):
|
||||||
"""Returns the right-hand-side of the equals."""
|
"""Returns the right-hand-side of the equals."""
|
||||||
return self.children[-1]
|
return self.children[-1]
|
||||||
@@ -1388,23 +1345,6 @@ class Statement(Simple, DocstringMixin):
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
|
||||||
def assignment_details(self):
|
|
||||||
"""
|
|
||||||
Returns an array of tuples of the elements before the assignment.
|
|
||||||
|
|
||||||
For example the following code::
|
|
||||||
|
|
||||||
x = (y, z) = 2, ''
|
|
||||||
|
|
||||||
would result in ``[(Name(x), '='), (Array([Name(y), Name(z)]), '=')]``.
|
|
||||||
"""
|
|
||||||
return []
|
|
||||||
|
|
||||||
def set_expression_list(self, lst):
|
|
||||||
"""It's necessary for some "hacks" to change the expression_list."""
|
|
||||||
self._expression_list = lst
|
|
||||||
|
|
||||||
|
|
||||||
class ExprStmt(Statement):
|
class ExprStmt(Statement):
|
||||||
"""
|
"""
|
||||||
@@ -1418,14 +1358,6 @@ class ExprStmt(Statement):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class ArrayStmt(Statement):
|
|
||||||
"""
|
|
||||||
This class exists temporarily. Like ``ExprStatement``, this exists to
|
|
||||||
distinguish between real statements and stuff that is defined in those
|
|
||||||
statements.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class Param(Base):
|
class Param(Base):
|
||||||
"""
|
"""
|
||||||
The class which shows definitions of params of classes and functions.
|
The class which shows definitions of params of classes and functions.
|
||||||
@@ -1498,136 +1430,14 @@ class Param(Base):
|
|||||||
return '<%s: %s>' % (type(self).__name__, str(self.tfpdef) + default)
|
return '<%s: %s>' % (type(self).__name__, str(self.tfpdef) + default)
|
||||||
|
|
||||||
|
|
||||||
class StatementElement(Simple):
|
class Array(object):
|
||||||
__slots__ = ('next', 'previous')
|
# TODO remove this. Just here because we need these names.
|
||||||
|
|
||||||
def __init__(self, module, start_pos, end_pos, parent):
|
|
||||||
super(StatementElement, self).__init__(module, start_pos, end_pos, parent)
|
|
||||||
self.next = None
|
|
||||||
self.previous = None
|
|
||||||
|
|
||||||
def set_next(self, call):
|
|
||||||
""" Adds another part of the statement"""
|
|
||||||
call.parent = self.parent
|
|
||||||
if self.next is not None:
|
|
||||||
self.next.set_next(call)
|
|
||||||
else:
|
|
||||||
self.next = call
|
|
||||||
call.previous = self
|
|
||||||
|
|
||||||
def next_is_execution(self):
|
|
||||||
return Array.is_type(self.next, Array.TUPLE, Array.NOARRAY)
|
|
||||||
|
|
||||||
def generate_call_path(self):
|
|
||||||
""" Helps to get the order in which statements are executed. """
|
|
||||||
try:
|
|
||||||
yield self.name
|
|
||||||
except AttributeError:
|
|
||||||
yield self
|
|
||||||
if self.next is not None:
|
|
||||||
for y in self.next.generate_call_path():
|
|
||||||
yield y
|
|
||||||
|
|
||||||
|
|
||||||
class Call(StatementElement):
|
|
||||||
__slots__ = ('name',)
|
|
||||||
|
|
||||||
def __init__(self, module, name, start_pos, end_pos, parent=None):
|
|
||||||
super(Call, self).__init__(module, start_pos, end_pos, parent)
|
|
||||||
name.parent = self
|
|
||||||
self.name = name
|
|
||||||
|
|
||||||
def names(self):
|
|
||||||
"""
|
|
||||||
Generate an array of string names. If a call is not just names,
|
|
||||||
raise an error.
|
|
||||||
"""
|
|
||||||
def check(call):
|
|
||||||
while call is not None:
|
|
||||||
if not isinstance(call, Call): # Could be an Array.
|
|
||||||
break
|
|
||||||
yield unicode(call.name)
|
|
||||||
call = call.next
|
|
||||||
|
|
||||||
return list(check(self))
|
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "<%s: %s>" % (type(self).__name__, self.name)
|
|
||||||
|
|
||||||
|
|
||||||
class Array(StatementElement):
|
|
||||||
"""
|
|
||||||
Describes the different python types for an array, but also empty
|
|
||||||
statements. In the Python syntax definitions this type is named 'atom'.
|
|
||||||
http://docs.python.org/py3k/reference/grammar.html
|
|
||||||
Array saves sub-arrays as well as normal operators and calls to methods.
|
|
||||||
|
|
||||||
:param array_type: The type of an array, which can be one of the constants
|
|
||||||
below.
|
|
||||||
:type array_type: int
|
|
||||||
"""
|
|
||||||
__slots__ = ('type', 'end_pos', 'values', 'keys')
|
|
||||||
NOARRAY = None # just brackets, like `1 * (3 + 2)`
|
NOARRAY = None # just brackets, like `1 * (3 + 2)`
|
||||||
TUPLE = 'tuple'
|
TUPLE = 'tuple'
|
||||||
LIST = 'list'
|
LIST = 'list'
|
||||||
DICT = 'dict'
|
DICT = 'dict'
|
||||||
SET = 'set'
|
SET = 'set'
|
||||||
|
|
||||||
def __init__(self, module, start_pos, arr_type=NOARRAY, parent=None):
|
|
||||||
super(Array, self).__init__(module, start_pos, (None, None), parent)
|
|
||||||
self.end_pos = None, None
|
|
||||||
self.type = arr_type
|
|
||||||
self.values = []
|
|
||||||
self.keys = []
|
|
||||||
|
|
||||||
def add_statement(self, statement, is_key=False):
|
|
||||||
"""Just add a new statement"""
|
|
||||||
statement.parent = self
|
|
||||||
if is_key:
|
|
||||||
self.type = self.DICT
|
|
||||||
self.keys.append(statement)
|
|
||||||
else:
|
|
||||||
self.values.append(statement)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def is_type(instance, *types):
|
|
||||||
"""
|
|
||||||
This is not only used for calls on the actual object, but for
|
|
||||||
ducktyping, to invoke this function with anything as `self`.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
if instance.type in types:
|
|
||||||
return True
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
return False
|
|
||||||
|
|
||||||
def __len__(self):
|
|
||||||
return len(self.values)
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
if self.type == self.DICT:
|
|
||||||
raise TypeError('no dicts allowed')
|
|
||||||
return self.values[key]
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
if self.type == self.DICT:
|
|
||||||
raise TypeError('no dicts allowed')
|
|
||||||
return iter(self.values)
|
|
||||||
|
|
||||||
def items(self):
|
|
||||||
if self.type != self.DICT:
|
|
||||||
raise TypeError('only dicts allowed')
|
|
||||||
return zip(self.keys, self.values)
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
if self.type == self.NOARRAY:
|
|
||||||
typ = 'noarray'
|
|
||||||
else:
|
|
||||||
typ = self.type
|
|
||||||
return "<%s: %s%s>" % (type(self).__name__, typ, self.values)
|
|
||||||
|
|
||||||
|
|
||||||
class CompFor(Simple):
|
class CompFor(Simple):
|
||||||
def is_scope(self):
|
def is_scope(self):
|
||||||
@@ -1649,37 +1459,3 @@ class CompFor(Simple):
|
|||||||
|
|
||||||
def scope_names_generator(self, position):
|
def scope_names_generator(self, position):
|
||||||
yield self, []
|
yield self, []
|
||||||
|
|
||||||
|
|
||||||
class ListComprehension(ForFlow):
|
|
||||||
""" Helper class for list comprehensions """
|
|
||||||
def __init__(self, module, stmt, middle, input, parent):
|
|
||||||
self.input = input
|
|
||||||
nested_lc = input.expression_list()[0]
|
|
||||||
if isinstance(nested_lc, ListComprehension):
|
|
||||||
# is nested LC
|
|
||||||
input = nested_lc.stmt
|
|
||||||
nested_lc.parent = self
|
|
||||||
|
|
||||||
super(ListComprehension, self).__init__(module, [input],
|
|
||||||
stmt.start_pos, middle)
|
|
||||||
self.parent = parent
|
|
||||||
self.stmt = stmt
|
|
||||||
self.middle = middle
|
|
||||||
for s in middle, input:
|
|
||||||
s.parent = self
|
|
||||||
# The stmt always refers to the most inner list comprehension.
|
|
||||||
stmt.parent = self._get_most_inner_lc()
|
|
||||||
|
|
||||||
def _get_most_inner_lc(self):
|
|
||||||
nested_lc = self.input.expression_list()[0]
|
|
||||||
if isinstance(nested_lc, ListComprehension):
|
|
||||||
return nested_lc._get_most_inner_lc()
|
|
||||||
return self
|
|
||||||
|
|
||||||
@property
|
|
||||||
def end_pos(self):
|
|
||||||
return self.stmt.end_pos
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "<%s: %s>" % (type(self).__name__, self.get_code())
|
|
||||||
|
|||||||
Reference in New Issue
Block a user