diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index d2edc955..b9604192 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -147,7 +147,7 @@ class Evaluator(object): for ass_expression_list, op in ass_details: new_result += finder.find_assignments(ass_expression_list[0], result, seek_name) result = new_result - return set(result) + return result def eval_expression_list(self, expression_list): """ @@ -158,11 +158,13 @@ class Evaluator(object): debug.dbg('eval_expression_list: %s', expression_list) result = [] p = precedence.create_precedence(expression_list) - return self._process_precedence_element(p) + return self._process_precedence_element(p) or [] + + # TODO remove calls_iterator = iter(expression_list) for each in calls_iterator: result += self._eval_statement_element(each) - return set(result) + return result def _process_precedence_element(self, el): if el is None: @@ -294,7 +296,7 @@ class Evaluator(object): return [] types = self.find_types(typ, current) result = imports.strip_imports(self, types) - return self.follow_path(path, set(result), scope) + return self.follow_path(path, result, scope) @debug.increase_indent def execute(self, obj, params=(), evaluate_generator=False): diff --git a/jedi/evaluate/compiled/__init__.py b/jedi/evaluate/compiled/__init__.py index ed196ae7..6503150a 100644 --- a/jedi/evaluate/compiled/__init__.py +++ b/jedi/evaluate/compiled/__init__.py @@ -8,7 +8,7 @@ import os from jedi._compatibility import builtins as _builtins from jedi import debug -from jedi.parser.representation import Base +from jedi.parser.representation import Base, IsScope from jedi.cache import underscore_memoization from jedi.evaluate.sys_path import get_sys_path from jedi.parser.representation import Param @@ -273,7 +273,7 @@ def _parse_function_doc(doc): return param_str, ret -class Builtin(CompiledObject): +class Builtin(CompiledObject, IsScope): def get_defined_names(self): # Filter None, because it's really just a keyword, nobody wants to # access it. diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 8b4bf266..12675ef8 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -247,7 +247,7 @@ class NameFinder(object): # this means that there are no default params, # so just ignore it. return res_new - return set(res_new) | evaluator.eval_statement(r, seek_name=self.name_str) + return res_new + evaluator.eval_statement(r, seek_name=self.name_str) def _handle_for_loops(self, loop): # Take the first statement (for has always only diff --git a/jedi/evaluate/helpers.py b/jedi/evaluate/helpers.py index 0bd9e576..23aa21ed 100644 --- a/jedi/evaluate/helpers.py +++ b/jedi/evaluate/helpers.py @@ -162,6 +162,13 @@ class FakeSubModule(): line_offset = 0 +class FakeArray(pr.Array): + def __init__(self, values, parent, arr_type=pr.Array.LIST): + p = (0, 0) + super(FakeArray, self).__init__(FakeSubModule, p, arr_type, parent) + self.values = values + + class FakeStatement(pr.Statement): def __init__(self, expression_list, start_pos=(0, 0)): p = start_pos diff --git a/jedi/evaluate/stdlib.py b/jedi/evaluate/stdlib.py index 733c0496..9f113bd6 100644 --- a/jedi/evaluate/stdlib.py +++ b/jedi/evaluate/stdlib.py @@ -2,11 +2,11 @@ Implementations of standard library functions, because it's not possible to understand them with Jedi. """ - from jedi._compatibility import unicode from jedi.evaluate import compiled from jedi.evaluate import representation as er from jedi.evaluate import iterable +from jedi.evaluate.helpers import FakeArray, FakeStatement from jedi.parser import representation as pr from jedi import debug @@ -82,10 +82,26 @@ def builtins_super(evaluator, obj, params): return [] +def builtins_reversed(evaluator, obj, params): + objects = _follow_param(evaluator, params, 0) + if objects: + # unpack the iterator values + objects = iterable.get_iterator_types(objects) + rev = reversed(objects) + # Repack iterator values and then run it the normal way. This is necessary, + # because `reversed` is a function and autocompletion would fail in certain + # cases like `reversed(x).__iter__` if we just returned the result + # directly. + stmts = [FakeStatement([r]) for r in rev] + objects = (FakeArray(stmts, objects[0].parent),) + return [er.Instance(evaluator, obj, objects)] + + _implemented = { 'builtins': { 'getattr': builtins_getattr, 'type': builtins_type, 'super': builtins_super, + 'reversed': builtins_reversed, } } diff --git a/test/completion/operators.py b/test/completion/operators.py index b3eee265..9c8083ac 100644 --- a/test/completion/operators.py +++ b/test/completion/operators.py @@ -67,7 +67,7 @@ class FooBar(object): raboof = 'fourtytwo' # targets should be working -target = u'' +target = '' for char in ['f', 'u', 'u']: target += char #? float()