From af303e10c8e67e6a7de45c860b0ab927da951a37 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Mon, 15 Dec 2014 16:18:09 +0100 Subject: [PATCH] Statement -> ExprStmt. --- jedi/api/classes.py | 2 +- jedi/evaluate/helpers.py | 4 +-- jedi/evaluate/param.py | 4 +-- jedi/parser/__init__.py | 4 ++- jedi/parser/tree.py | 73 ++++++---------------------------------- 5 files changed, 19 insertions(+), 68 deletions(-) diff --git a/jedi/api/classes.py b/jedi/api/classes.py index 3650a3d0..c8cf274b 100644 --- a/jedi/api/classes.py +++ b/jedi/api/classes.py @@ -334,7 +334,7 @@ class BaseDefinition(object): # Functions, classes and modules are already fixed definitions, we # cannot follow them anymore. 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) names = self._evaluator.goto(stmt_or_imp, call_path) return [Definition(self._evaluator, n) for n in names] diff --git a/jedi/evaluate/helpers.py b/jedi/evaluate/helpers.py index 52997468..2b28d7c4 100644 --- a/jedi/evaluate/helpers.py +++ b/jedi/evaluate/helpers.py @@ -28,7 +28,7 @@ def deep_ast_copy(obj, new_elements_default=None, check_first=False): new_obj = copy.copy(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 # correctly, don't know exactly why. obj.get_defined_names() @@ -50,7 +50,7 @@ def deep_ast_copy(obj, new_elements_default=None, check_first=False): except AttributeError: pass - if isinstance(obj, pr.Statement): + if isinstance(obj, pr.ExprStmt): # We need to process something with priority for statements, # because there are several references that don't walk the whole # tree in there. diff --git a/jedi/evaluate/param.py b/jedi/evaluate/param.py index 0455b36b..91b83501 100644 --- a/jedi/evaluate/param.py +++ b/jedi/evaluate/param.py @@ -90,7 +90,7 @@ class Arguments(pr.Base): named_index = None new_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: 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. 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: argument_list.append((None, [])) # TODO generate warning? diff --git a/jedi/parser/__init__.py b/jedi/parser/__init__.py index 7ea197c2..d29fea43 100644 --- a/jedi/parser/__init__.py +++ b/jedi/parser/__init__.py @@ -367,6 +367,8 @@ class Parser(object): return "<%s: %s>" % (type(self).__name__, self.module) def _check_user_stmt(self, simple): + # TODO REMOVE (not used and called) + # this is not user checking, just update the used_names for tok_name in self.module.temp_used_names: try: @@ -374,7 +376,7 @@ class Parser(object): except KeyError: self.module.used_names[tok_name] = set([simple]) self.module.temp_used_names = [] - if isinstance(simple, pt.Statement): + if isinstance(simple, pt.ExprStmt): for name, calls in simple.get_names_dict().items(): self._scope.add_name_calls(name, calls) diff --git a/jedi/parser/tree.py b/jedi/parser/tree.py index c670ce2e..70ae81f2 100644 --- a/jedi/parser/tree.py +++ b/jedi/parser/tree.py @@ -41,7 +41,6 @@ See also :attr:`Scope.subscopes` and :attr:`Scope.statements`. import os import re from inspect import cleandoc -from collections import defaultdict from itertools import chain import textwrap @@ -234,13 +233,13 @@ class Whitespace(LeafWithNewLines): """Contains NEWLINE and ENDMARKER tokens.""" - class Name(Leaf): """ A string. Sometimes it is important to know if the string belongs to a name or not. """ type = 'name' + def __str__(self): return self.value @@ -335,6 +334,7 @@ class String(Literal): class Operator(Leaf): type = 'operator' + def __str__(self): return self.value @@ -358,6 +358,7 @@ class Operator(Leaf): class Keyword(Leaf): type = 'keyword' + def __eq__(self, other): """ Make comparisons with strings easy. @@ -892,6 +893,7 @@ class Lambda(Function): Lambdas are basically trimmed functions, so give it the same interface. """ type = 'lambda' + def __init__(self, children): super(Function, self).__init__(children) self.listeners = set() # not used here, but in evaluation. @@ -914,6 +916,7 @@ class Flow(Simple): class IfStmt(Flow): type = 'if_stmt' + def check_nodes(self): """ Returns all the `test` nodes that are defined as x, here: @@ -969,6 +972,7 @@ class TryStmt(Flow): class WithStmt(Flow): type = 'with_stmt' + def get_defined_names(self): names = [] for with_item in self.children[1:-2:2]: @@ -1011,6 +1015,7 @@ class Import(Simple): class ImportFrom(Import): type = 'import_from' + def get_defined_names(self): return [alias or name for name, alias in self._as_name_tuples()] @@ -1135,12 +1140,14 @@ class KeywordStatement(Simple): class AssertStmt(KeywordStatement): type = 'assert_stmt' + def assertion(self): return self.children[1] class GlobalStmt(KeywordStatement): type = 'global_stmt' + def get_defined_names(self): return self.children[1::2] @@ -1174,22 +1181,8 @@ def _defined_names(current): return names -class Statement(Simple, DocstringMixin): - """ - 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__ = () +class ExprStmt(Simple, DocstringMixin): + type = 'expr_stmt' def get_defined_names(self): 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.""" 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): """ Returns `+=`, `=`, etc or None if there is no operation. @@ -1241,19 +1203,6 @@ class Statement(Simple, DocstringMixin): 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): """ The class which shows definitions of params of classes and functions.