diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 68fa81e7..d93632eb 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -183,7 +183,7 @@ class Evaluator(object): return types elif pr.is_node(element, 'testlist_star_expr', 'testlist'): # The implicit tuple in statements. - return [iterable.Array(self, element, pr.Array.TUPLE)] + return [iterable.ImplicitTuple(self, element)] elif pr.is_node(element, 'not_test') or pr.is_node(element, 'factor'): types = self.eval_element(element.children[-1]) for operator in element.children[:-1]: @@ -206,15 +206,12 @@ class Evaluator(object): elif isinstance(atom, pr.Literal): return [compiled.create(self, atom.eval())] else: - mapping = {'(': pr.Array.TUPLE, - '[': pr.Array.LIST, - '{': pr.Array.DICT} c = atom.children # Parentheses without commas are not tuples. if c[0] == '(' and (not pr.is_node(c[1], 'testlist_comp') or c[1].children[1] != ','): return self.eval_element(c[1]) - return [iterable.Array(self, c[1], mapping[c[0]])] + return [iterable.Array(self, atom)] def _eval_trailer(self, types, trailer): trailer_op, node = trailer.children[:2] diff --git a/jedi/evaluate/iterable.py b/jedi/evaluate/iterable.py index f6508d5f..d7dc46e2 100644 --- a/jedi/evaluate/iterable.py +++ b/jedi/evaluate/iterable.py @@ -124,10 +124,14 @@ class Array(IterableWrapper): Used as a mirror to pr.Array, if needed. It defines some getter methods which are important in this module. """ - def __init__(self, evaluator, array_node, type): + mapping = {'(': pr.Array.TUPLE, + '[': pr.Array.LIST, + '{': pr.Array.DICT} + + def __init__(self, evaluator, atom): self._evaluator = evaluator - self._array_node = array_node - self.type = type + self._atom = atom + self.type = Array.mapping[atom.children[0]] @property def name(self): @@ -204,7 +208,7 @@ class Array(IterableWrapper): if name not in ['start_pos', 'get_only_subelement', 'parent', 'get_parent_until', 'items']: raise AttributeError('Strange access on %s: %s.' % (self, name)) - return getattr(self._array_node, name) + return getattr(self._atom, name) def _values(self): if self.type == pr.Array.DICT: @@ -213,11 +217,16 @@ class Array(IterableWrapper): return self._items() def _items(self): - if pr.is_node(self._array_node, 'testlist_comp', 'testlist_star_expr', 'testlist'): - return self._array_node.children[::2] - elif pr.is_node(self._array_node, 'dictorsetmaker'): + c = self._atom.children + array_node = c[1] + if array_node in (']', '}', ')'): + return [] # Direct closing bracket, doesn't contain items. + + if pr.is_node(array_node, 'testlist_comp', 'testlist_star_expr', 'testlist'): + return array_node.children[::2] + elif pr.is_node(array_node, 'dictorsetmaker'): kv = [] - iterator = iter(self._array_node.children) + iterator = iter(array_node.children) for key in iterator: op = next(iterator, None) if op is None or op == ',': @@ -229,18 +238,30 @@ class Array(IterableWrapper): raise NotImplementedError('dict/set comprehensions') return kv else: - return [self._array_node] + return [array_node] def __iter__(self): return iter(self._items()) def __repr__(self): - return "" % (type(self).__name__, self._array_node) + return "" % (type(self).__name__, self._atom) + + +class ImplicitTuple(Array): + def __init__(self, evaluator, testlist): + self._evaluator = evaluator + self.type = pr.Array.TUPLE + self._testlist = testlist + + def _items(self): + return self._testlist.children[::2] class FakeSequence(Array): def __init__(self, evaluator, sequence_values, type): - super(FakeSequence, self).__init__(evaluator, None, type) + # Intentionally don't call the parent __init__. + self._evaluator = evaluator + self.type = type self._sequence_values = sequence_values def _items(self): @@ -253,7 +274,8 @@ class FakeSequence(Array): class FakeDict(Array): def __init__(self, evaluator, dct): - super(FakeDict, self).__init__(evaluator, None, pr.Array.DICT) + self._evaluator = evaluator + self.type = pr.Array.DICT self._dct = dct def get_exact_index_types(self, index):