diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index b0459802..2e176ae8 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -69,11 +69,9 @@ backtracking algorithm. .. todo:: nonlocal statement, needed or can be ignored? (py3k) """ import copy -from itertools import tee, chain +from itertools import chain -from jedi._compatibility import next, hasattr, unicode from jedi.parser import tree as pr -from jedi.parser.tokenize import Token from jedi import debug from jedi.evaluate import representation as er from jedi.evaluate import imports @@ -86,7 +84,7 @@ from jedi.evaluate import compiled from jedi.evaluate import precedence from jedi.evaluate import param from jedi.evaluate import helpers -from jedi.evaluate.helpers import FakeStatement, deep_ast_copy, call_of_name +from jedi.evaluate.helpers import FakeStatement, call_of_name class Evaluator(object): @@ -153,13 +151,6 @@ class Evaluator(object): types = left else: types = precedence.calculate(self, left, operator, types) - elif False and len(stmt.get_defined_names()) > 1 and seek_name and ass_details: - # Assignment checking is only important if the statement defines - # multiple variables. - new_result = [] - for ass_expression_list, op in ass_details: - new_result += finder.find_assignments(ass_expression_list[0], result, seek_name) - result = new_result debug.dbg('eval_statement result %s', types) return types @@ -297,162 +288,6 @@ class Evaluator(object): debug.dbg('execute result: %s in %s', types, obj) return types - def eval_expression_list(self, expression_list): - """ - `expression_list` can be either `pr.Array` or `list of list`. - It is used to evaluate a two dimensional object, that has calls, arrays and - operators in it. - """ - debug.dbg('eval_expression_list: %s', expression_list) - p = precedence.create_precedence(expression_list) - return precedence.process_precedence_element(self, p) or [] - - def eval_statement_element(self, element): - if isinstance(element, pr.ListComprehension): - return self.eval_statement(element.stmt) - elif isinstance(element, pr.Lambda): - return [er.Function(self, element)] - # With things like params, these can also be functions... - elif isinstance(element, pr.Base) and element.isinstance( - er.Function, er.Class, er.Instance, iterable.ArrayInstance): - return [element] - # The string tokens are just operations (+, -, etc.) - elif isinstance(element, compiled.CompiledObject): - return [element] - elif isinstance(element, Token): - return [] - else: - return self.eval_call(element) - - def eval_call(self, call): - """Follow a call is following a function, variable, string, etc.""" - path = call.generate_call_path() - - # find the statement of the Scope - s = call - while not s.parent.is_scope(): - s = s.parent - scope = s.parent - return self.eval_call_path(path, scope, s.start_pos) - - def eval_call_path(self, path, scope, position): - """ - Follows a path generated by `pr.StatementElement.generate_call_path()`. - """ - current = next(path) - - if isinstance(current, pr.Array): - if current.type == pr.Array.NOARRAY: - try: - lst_cmp = current[0].expression_list()[0] - if not isinstance(lst_cmp, pr.ListComprehension): - raise IndexError - except IndexError: - types = list(chain.from_iterable(self.eval_statement(s) - for s in current)) - else: - types = [iterable.GeneratorComprehension(self, lst_cmp)] - else: - types = [iterable.Array(self, current)] - else: - if isinstance(current, pr.Name): - # This is the first global lookup. - types = self.find_types(scope, current, position=position, - search_global=True) - else: - # for pr.Literal - types = [compiled.create(self, current.value)] - types = imports.follow_imports(self, types) - - return self.follow_path(path, types, scope) - - def follow_path(self, path, types, call_scope): - """ - Follows a path like:: - - self.follow_path(iter(['Foo', 'bar']), [a_type], from_somewhere) - - to follow a call like ``module.a_type.Foo.bar`` (in ``from_somewhere``). - """ - results_new = [] - iter_paths = tee(path, len(types)) - - for i, typ in enumerate(types): - fp = self._follow_path(iter_paths[i], typ, call_scope) - if fp is not None: - results_new += fp - else: - # This means stop iteration. - return types - return results_new - - def _follow_path(self, path, typ, scope): - """ - Uses a generator and tries to complete the path, e.g.:: - - foo.bar.baz - - `_follow_path` is only responsible for completing `.bar.baz`, the rest - is done in the `follow_call` function. - """ - # current is either an Array or a Scope. - try: - current = next(path) - except StopIteration: - return None - debug.dbg('_follow_path: %s in scope %s', current, typ) - - result = [] - if isinstance(current, pr.Array): - # This must be an execution, either () or []. - if current.type == pr.Array.LIST: - if hasattr(typ, 'get_index_types'): - if isinstance(typ, compiled.CompiledObject): - # CompiledObject doesn't contain an evaluator instance. - result = typ.get_index_types(self, current) - else: - result = typ.get_index_types(current) - elif current.type not in [pr.Array.DICT]: - # Scope must be a class or func - make an instance or execution. - result = self.execute(typ, current) - else: - # Curly braces are not allowed, because they make no sense. - debug.warning('strange function call with {} %s %s', current, typ) - else: - # The function must not be decorated with something else. - if typ.isinstance(er.Function): - typ = typ.get_magic_function_scope() - else: - # This is the typical lookup while chaining things. - if filter_private_variable(typ, scope, current): - return [] - types = self.find_types(typ, current) - result = imports.follow_imports(self, types) - return self.follow_path(path, result, scope) - - @debug.increase_indent - def execute_old(self, obj, params=()): - if obj.isinstance(er.Function): - obj = obj.get_decorated_func() - - debug.dbg('execute: %s %s', obj, params) - try: - # Some stdlib functions like super(), namedtuple(), etc. have been - # hard-coded in Jedi to support them. - return stdlib.execute(self, obj, params) - except stdlib.NotInStdLib: - pass - - try: - func = obj.py__call__ - except AttributeError: - debug.warning("no execution possible %s", obj) - return [] - else: - types = func(self, params) - debug.dbg('execute result: %s in %s', types, obj) - return types - def goto_definition(self, name): def_ = name.get_definition() if def_.type == 'expr_stmt' and name in def_.get_defined_names(): @@ -513,65 +348,3 @@ class Evaluator(object): else: return self.find_types(scope, name, stmt.start_pos, search_global=True, is_goto=True) - - - if isinstance(par, pr.Import): - # Nowhere to goto for aliases - if par.alias == call_path[0]: - return [call_path[0]] - - names = par.get_all_import_names() - if par.alias: - names = names[:-1] - # Filter names that are after our Name - removed_names = len(names) - names.index(call_path[0]) - 1 - i = imports.ImportWrapper(self, par, kill_count=removed_names, - nested_resolve=True) - return i.follow(is_goto=True) - - # Return the name defined in the call_path, if it's part of the - # statement name definitions. Only return, if it's one name and one - # name only. Otherwise it's a mixture between a definition and a - # reference. In this case it's just a definition. So we stay on it. - if len(call_path) == 1 and isinstance(call_path[0], pr.Name) \ - and call_path[0] in par.get_defined_names(): - # Named params should get resolved to their param definitions. - if pr.Array.is_type(par.parent, pr.Array.TUPLE, pr.Array.NOARRAY) \ - and par.parent.previous: - call = deep_ast_copy(par.parent.previous) - # We have made a copy, so we're fine to change it. - call.next = None - while call.previous is not None: - call = call.previous - param_names = [] - named_param_name = par.get_defined_names()[0] - for typ in self.eval_call(call): - if isinstance(typ, er.Class): - params = [] - for init_method in typ.py__getattribute__('__init__'): - params += init_method.params - else: - params = typ.params - for param in params: - if unicode(param.get_name()) == unicode(named_param_name): - param_names.append(param.get_name()) - return param_names - return [call_path[0]] - - scope = par.get_parent_scope() - pos = par.start_pos - first_part, search_name_part = call_path[:-1], call_path[-1] - - if first_part: - scopes = self.eval_call_path(iter(first_part), scope, pos) - search_global = False - pos = None - else: - scopes = [scope] - search_global = True - - follow_res = [] - for s in scopes: - follow_res += self.find_types(s, search_name_part, pos, - search_global=search_global, is_goto=True) - return follow_res