1
0
forked from VimPlug/jedi

reversed and for loops now produce strings in the correct order.

This commit is contained in:
Dave Halter
2015-10-14 16:50:26 +02:00
parent b27be47811
commit 62468fb402
4 changed files with 49 additions and 15 deletions

View File

@@ -147,12 +147,16 @@ class Evaluator(object):
name = str(stmt.get_defined_names()[0])
parent = self.wrap(stmt.get_parent_scope())
left = self.find_types(parent, name, stmt.start_pos, search_global=True)
if isinstance(stmt.get_parent_until(tree.ForStmt), tree.ForStmt):
for_stmt = stmt.get_parent_until(tree.ForStmt)
if isinstance(for_stmt, tree.ForStmt):
# Iterate through result and add the values, that's possible
# only in for loops without clutter, because they are
# predictable.
for r in types:
left = precedence.calculate(self, left, operator, set([r]))
for_iterable = self.eval_element(for_stmt.children[3])
ordered = iterable.ordered_elements_of_iterable(self, for_iterable, types)
for index_types in ordered:
left = precedence.calculate(self, left, operator, index_types)
types = left
else:
types = precedence.calculate(self, left, operator, types)

View File

@@ -29,6 +29,7 @@ from jedi.evaluate import compiled
from jedi.evaluate import helpers
from jedi.evaluate.cache import CachedMetaClass, memoize_default
from jedi.evaluate import analysis
from jedi.evaluate.precedence import literals_to_types
class IterableWrapper(tree.Base):
@@ -390,6 +391,28 @@ class MergedArray(_FakeArray):
return sum(len(a) for a in self._arrays)
def ordered_elements_of_iterable(evaluator, iterable_type, all_values):
"""
This function returns the ordered types of an iterable. If the input is not
an Array, we just return all types as the first and only item of the
output list.
"""
ordered = []
# Unpack the iterator values
for sequence in iterable_type:
if not isinstance(sequence, Array):
ordered = [literals_to_types(evaluator, all_values)]
break
else:
# Try
for i, types in enumerate(sequence.per_index_values()):
try:
ordered[i] |= types
except IndexError:
ordered.append(set(types))
return ordered
def get_iterator_types(evaluator, element):
"""Returns the types of any iterator (arrays, yields, __iter__, etc)."""
iterators = []

View File

@@ -23,17 +23,19 @@ COMPARISON_OPERATORS = {
}
def _literals_to_types(evaluator, result):
def literals_to_types(evaluator, result):
# Changes literals ('a', 1, 1.0, etc) to its type instances (str(),
# int(), float(), etc).
result = list(result)
for i, r in enumerate(result):
if is_literal(r):
new_result = set()
for typ in result:
if is_literal(typ):
# Literals are only valid as long as the operations are
# correct. Otherwise add a value-free instance.
cls = builtin.get_by_name(r.name.get_code())
result[i] = list(evaluator.execute(cls))[0]
return set(result)
cls = builtin.get_by_name(typ.name.get_code())
new_result.add(list(evaluator.execute(cls))[0])
else:
new_result.add(typ)
return new_result
def calculate_children(evaluator, children):
@@ -69,13 +71,13 @@ def calculate(evaluator, left_result, operator, right_result):
if not left_result or not right_result:
# illegal slices e.g. cause left/right_result to be None
result = (left_result or set()) | (right_result or set())
result = _literals_to_types(evaluator, result)
result = literals_to_types(evaluator, result)
else:
# I don't think there's a reasonable chance that a string
# operation is still correct, once we pass something like six
# objects.
if len(left_result) * len(right_result) > 6:
result = _literals_to_types(evaluator, left_result | right_result)
result = literals_to_types(evaluator, left_result | right_result)
else:
for left in left_result:
for right in right_result:

View File

@@ -155,9 +155,14 @@ def get_iterable_content(evaluator, arguments, argument_index):
@argument_clinic('sequence, /', want_obj=True, want_arguments=True)
def builtins_reversed(evaluator, sequences, obj, arguments):
# Unpack the iterator values
objects = get_iterable_content(evaluator, arguments, 0)
rev = [iterable.AlreadyEvaluated([o]) for o in reversed(list(objects))]
# While we could do without this variable (just by using sequences), we
# want static analysis to work well. Therefore we need to generated the
# values again.
all_sequence_types = get_iterable_content(evaluator, arguments, 0)
ordered = iterable.ordered_elements_of_iterable(evaluator, sequences, all_sequence_types)
rev = [iterable.AlreadyEvaluated(o) for o in reversed(ordered)]
# 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