1
0
forked from VimPlug/jedi

Statement -> ExprStmt.

This commit is contained in:
Dave Halter
2014-12-15 16:18:09 +01:00
parent 9431d89797
commit af303e10c8
5 changed files with 19 additions and 68 deletions

View File

@@ -334,7 +334,7 @@ class BaseDefinition(object):
# Functions, classes and modules are already fixed definitions, we # Functions, classes and modules are already fixed definitions, we
# cannot follow them anymore. # cannot follow them anymore.
return [self] return [self]
stmt_or_imp = self._name.get_parent_until((pr.Statement, pr.Import)) stmt_or_imp = self._name.get_parent_until((pr.ExprStmt, pr.Import))
call_path = call_path_for_name_part(stmt_or_imp, self._name) call_path = call_path_for_name_part(stmt_or_imp, self._name)
names = self._evaluator.goto(stmt_or_imp, call_path) names = self._evaluator.goto(stmt_or_imp, call_path)
return [Definition(self._evaluator, n) for n in names] return [Definition(self._evaluator, n) for n in names]

View File

@@ -28,7 +28,7 @@ def deep_ast_copy(obj, new_elements_default=None, check_first=False):
new_obj = copy.copy(obj) new_obj = copy.copy(obj)
new_elements[obj] = new_obj new_elements[obj] = new_obj
if isinstance(obj, pr.Statement): if isinstance(obj, pr.ExprStmt):
# Need to set _set_vars, otherwise the cache is not working # Need to set _set_vars, otherwise the cache is not working
# correctly, don't know exactly why. # correctly, don't know exactly why.
obj.get_defined_names() obj.get_defined_names()
@@ -50,7 +50,7 @@ def deep_ast_copy(obj, new_elements_default=None, check_first=False):
except AttributeError: except AttributeError:
pass pass
if isinstance(obj, pr.Statement): if isinstance(obj, pr.ExprStmt):
# We need to process something with priority for statements, # We need to process something with priority for statements,
# because there are several references that don't walk the whole # because there are several references that don't walk the whole
# tree in there. # tree in there.

View File

@@ -90,7 +90,7 @@ class Arguments(pr.Base):
named_index = None named_index = None
new_args = [] new_args = []
for i, stmt in enumerate(var_args): for i, stmt in enumerate(var_args):
if isinstance(stmt, pr.Statement): if isinstance(stmt, pr.ExprStmt):
if named_index is None and stmt.assignment_details: if named_index is None and stmt.assignment_details:
named_index = i named_index = i
@@ -362,7 +362,7 @@ def _unpack_var_args(evaluator, var_args, func):
# `var_args` is typically an Array, and not a list. # `var_args` is typically an Array, and not a list.
for stmt in _reorder_var_args(var_args.iterate()): for stmt in _reorder_var_args(var_args.iterate()):
if not isinstance(stmt, pr.Statement): if not isinstance(stmt, pr.ExprStmt):
if stmt is None: if stmt is None:
argument_list.append((None, [])) argument_list.append((None, []))
# TODO generate warning? # TODO generate warning?

View File

@@ -367,6 +367,8 @@ class Parser(object):
return "<%s: %s>" % (type(self).__name__, self.module) return "<%s: %s>" % (type(self).__name__, self.module)
def _check_user_stmt(self, simple): def _check_user_stmt(self, simple):
# TODO REMOVE (not used and called)
# this is not user checking, just update the used_names # this is not user checking, just update the used_names
for tok_name in self.module.temp_used_names: for tok_name in self.module.temp_used_names:
try: try:
@@ -374,7 +376,7 @@ class Parser(object):
except KeyError: except KeyError:
self.module.used_names[tok_name] = set([simple]) self.module.used_names[tok_name] = set([simple])
self.module.temp_used_names = [] self.module.temp_used_names = []
if isinstance(simple, pt.Statement): if isinstance(simple, pt.ExprStmt):
for name, calls in simple.get_names_dict().items(): for name, calls in simple.get_names_dict().items():
self._scope.add_name_calls(name, calls) self._scope.add_name_calls(name, calls)

View File

@@ -41,7 +41,6 @@ See also :attr:`Scope.subscopes` and :attr:`Scope.statements`.
import os import os
import re import re
from inspect import cleandoc from inspect import cleandoc
from collections import defaultdict
from itertools import chain from itertools import chain
import textwrap import textwrap
@@ -234,13 +233,13 @@ class Whitespace(LeafWithNewLines):
"""Contains NEWLINE and ENDMARKER tokens.""" """Contains NEWLINE and ENDMARKER tokens."""
class Name(Leaf): class Name(Leaf):
""" """
A string. Sometimes it is important to know if the string belongs to a name A string. Sometimes it is important to know if the string belongs to a name
or not. or not.
""" """
type = 'name' type = 'name'
def __str__(self): def __str__(self):
return self.value return self.value
@@ -335,6 +334,7 @@ class String(Literal):
class Operator(Leaf): class Operator(Leaf):
type = 'operator' type = 'operator'
def __str__(self): def __str__(self):
return self.value return self.value
@@ -358,6 +358,7 @@ class Operator(Leaf):
class Keyword(Leaf): class Keyword(Leaf):
type = 'keyword' type = 'keyword'
def __eq__(self, other): def __eq__(self, other):
""" """
Make comparisons with strings easy. Make comparisons with strings easy.
@@ -892,6 +893,7 @@ class Lambda(Function):
Lambdas are basically trimmed functions, so give it the same interface. Lambdas are basically trimmed functions, so give it the same interface.
""" """
type = 'lambda' type = 'lambda'
def __init__(self, children): def __init__(self, children):
super(Function, self).__init__(children) super(Function, self).__init__(children)
self.listeners = set() # not used here, but in evaluation. self.listeners = set() # not used here, but in evaluation.
@@ -914,6 +916,7 @@ class Flow(Simple):
class IfStmt(Flow): class IfStmt(Flow):
type = 'if_stmt' type = 'if_stmt'
def check_nodes(self): def check_nodes(self):
""" """
Returns all the `test` nodes that are defined as x, here: Returns all the `test` nodes that are defined as x, here:
@@ -969,6 +972,7 @@ class TryStmt(Flow):
class WithStmt(Flow): class WithStmt(Flow):
type = 'with_stmt' type = 'with_stmt'
def get_defined_names(self): def get_defined_names(self):
names = [] names = []
for with_item in self.children[1:-2:2]: for with_item in self.children[1:-2:2]:
@@ -1011,6 +1015,7 @@ class Import(Simple):
class ImportFrom(Import): class ImportFrom(Import):
type = 'import_from' type = 'import_from'
def get_defined_names(self): def get_defined_names(self):
return [alias or name for name, alias in self._as_name_tuples()] return [alias or name for name, alias in self._as_name_tuples()]
@@ -1135,12 +1140,14 @@ class KeywordStatement(Simple):
class AssertStmt(KeywordStatement): class AssertStmt(KeywordStatement):
type = 'assert_stmt' type = 'assert_stmt'
def assertion(self): def assertion(self):
return self.children[1] return self.children[1]
class GlobalStmt(KeywordStatement): class GlobalStmt(KeywordStatement):
type = 'global_stmt' type = 'global_stmt'
def get_defined_names(self): def get_defined_names(self):
return self.children[1::2] return self.children[1::2]
@@ -1174,22 +1181,8 @@ def _defined_names(current):
return names return names
class Statement(Simple, DocstringMixin): class ExprStmt(Simple, DocstringMixin):
""" type = 'expr_stmt'
This is the class for all the possible statements. Which means, this class
stores pretty much all the Python code, except functions, classes, imports,
and flow functions like if, for, etc.
:type token_list: list
:param token_list:
List of tokens or names. Each element is either an instance
of :class:`Name` or a tuple of token type value (e.g.,
:data:`tokenize.NUMBER`), token string (e.g., ``'='``), and
start position (e.g., ``(1, 0)``).
:type start_pos: 2-tuple of int
:param start_pos: Position (line, column) of the Statement.
"""
__slots__ = ()
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])
@@ -1200,37 +1193,6 @@ class Statement(Simple, DocstringMixin):
"""Returns the right-hand-side of the equals.""" """Returns the right-hand-side of the equals."""
return self.children[-1] return self.children[-1]
def get_names_dict(self):
"""The future of name resolution. Returns a dict(str -> Call)."""
dct = defaultdict(lambda: [])
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):
c = call
# Check if there's an execution in it, if so this is
# not a set_var.
while True:
if c.next is None or isinstance(c.next, Array):
break
c = c.next
dct[unicode(c.name)].append(call)
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())
for as_name in self.as_names:
dct[unicode(as_name)].append(Call(self._sub_module, as_name,
as_name.start_pos, as_name.end_pos, self))
return dct
def first_operation(self): def first_operation(self):
""" """
Returns `+=`, `=`, etc or None if there is no operation. Returns `+=`, `=`, etc or None if there is no operation.
@@ -1241,19 +1203,6 @@ class Statement(Simple, DocstringMixin):
return None return None
class ExprStmt(Statement):
"""
This class exists temporarily, to be able to distinguish real statements
(``small_stmt`` in Python grammar) from the so called ``test`` parts, that
may be used to defined part of an array, but are never a whole statement.
The reason for this class is purely historical. It was easier to just use
Statement nested, than to create a new class for Test (plus Jedi's fault
tolerant parser just makes things very complicated).
"""
type = 'expr_stmt'
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.