diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 926aa80b..9c1caddc 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -170,15 +170,22 @@ class Evaluator(object): return self._eval_precedence(el) else: # normal element, no operators - return self._eval_statement_element(el) + return self.eval_statement_element(el) def _eval_precedence(self, _precedence): left = self.process_precedence_element(_precedence.left) right = self.process_precedence_element(_precedence.right) return precedence.calculate(self, left, _precedence.operator, right) - def _eval_statement_element(self, element): + def eval_statement_element(self, element): if pr.Array.is_type(element, pr.Array.NOARRAY): + try: + lst_cmp = element[0].expression_list()[0] + except IndexError: + pass + else: + if isinstance(lst_cmp, pr.ListComprehension): + return [iterable.GeneratorComprehension(self, lst_cmp)] r = list(itertools.chain.from_iterable(self.eval_statement(s) for s in element)) call_path = element.generate_call_path() diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 86e018fb..2e9e5e80 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -471,6 +471,7 @@ def get_names_of_scope(evaluator, scope, position=None, star_search=True, includ """ if isinstance(scope, iterable.ListComprehensionFlow): position = scope.list_comprehension.parent.start_pos + in_func_scope = scope non_flow = scope.get_parent_until(pr.Flow, reverse=True) while scope: diff --git a/jedi/evaluate/iterable.py b/jedi/evaluate/iterable.py index bb3e2da8..ccfeab3f 100644 --- a/jedi/evaluate/iterable.py +++ b/jedi/evaluate/iterable.py @@ -66,6 +66,13 @@ class Generator(use_metaclass(CachedMetaClass, pr.Base)): analysis.add(self._evaluator, 'type-error-generator', index_array) return [] + def get_exact_index_types(self, index): + """ + Exact lookups are used for tuple lookups, which are perfectly fine if + used with generators. + """ + return [self.iter_content()[index]] + def __getattr__(self, name): if name not in ['start_pos', 'end_pos', 'parent', 'get_imports', 'asserts', 'doc', 'docstr', 'get_parent_until', @@ -91,6 +98,15 @@ class GeneratorMethod(object): return getattr(self._builtin_func, name) +class GeneratorComprehension(Generator): + def __init__(self, evaluator, comprehension): + super(GeneratorComprehension, self).__init__(evaluator, comprehension, None) + self.comprehension = comprehension + + def iter_content(self): + return self._evaluator.eval_statement_element(self.comprehension) + + class Array(use_metaclass(CachedMetaClass, pr.Base)): """ Used as a mirror to pr.Array, if needed. It defines some getter diff --git a/test/completion/basic.py b/test/completion/basic.py index 6af20c93..844b6e9f 100644 --- a/test/completion/basic.py +++ b/test/completion/basic.py @@ -168,6 +168,15 @@ a[0] #? int() a[0][0] +# ----------------- +# generator comprehensions +# ----------------- + +left, right = (i for i in (1, '')) + +#? int() +left + # ----------------- # ternary operator # -----------------