diff --git a/src/main/java/net/starlark/java/eval/StarlarkList.java b/src/main/java/net/starlark/java/eval/StarlarkList.java index 659dd057024f8d..5fd95d2850088a 100644 --- a/src/main/java/net/starlark/java/eval/StarlarkList.java +++ b/src/main/java/net/starlark/java/eval/StarlarkList.java @@ -16,9 +16,15 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; -import java.util.AbstractList; +import java.util.AbstractCollection; import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.NoSuchElementException; import java.util.function.Supplier; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.starlark.java.annot.Param; import net.starlark.java.annot.ParamType; @@ -70,7 +76,7 @@ + "['a', 'b', 'c', 'd'][::2] # ['a', 'c']\n" + "['a', 'b', 'c', 'd'][3:0:-1] # ['d', 'c', 'b']" + "Lists are mutable, as in Python.") -public abstract class StarlarkList extends AbstractList +public abstract class StarlarkList extends AbstractCollection implements Sequence, StarlarkValue, Mutability.Freezable, Comparable> { // It's always possible to overeat in small bites but we'll @@ -205,6 +211,12 @@ public static StarlarkList concat( return wrap(mutability, res); } + @Nonnull + @Override + public Iterator iterator() { + return new Itr(); + } + @Override public int compareTo(StarlarkList that) { return Sequence.compare(this, that); @@ -446,4 +458,76 @@ public Object pop(Object i) throws EvalException { public StarlarkList unsafeOptimizeMemoryLayout() { return this; } + + private class Itr implements Iterator { + private int cursor = 0; + + @Override + public boolean hasNext() { + return cursor != size(); + } + + @Override + public E next() { + try { + int i = cursor; + E next = get(i); + cursor = i + 1; + return next; + } catch (IndexOutOfBoundsException e) { + throw new NoSuchElementException(); + } + } + } + + // the following List methods are deliberately left unsupported for now, but could be implemented + // if the need ever arises + + @Override + @Nonnull + public List subList(int fromIndex, int toIndex) { + throw new UnsupportedOperationException(); + } + + @Override + @Nonnull + public ListIterator listIterator() { + throw new UnsupportedOperationException(); + } + + @Override + @Nonnull + public ListIterator listIterator(int index) { + throw new UnsupportedOperationException(); + } + + @Override + public int lastIndexOf(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public int indexOf(Object o) { + throw new UnsupportedOperationException(); + } + + @Override + public E set(int index, E element) { + throw new UnsupportedOperationException(); + } + + @Override + public void add(int index, E element) { + throw new UnsupportedOperationException(); + } + + @Override + public E remove(int index) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addAll(int index, @Nonnull Collection c) { + throw new UnsupportedOperationException(); + } } diff --git a/src/test/java/net/starlark/java/eval/StarlarkMutableTest.java b/src/test/java/net/starlark/java/eval/StarlarkMutableTest.java index 66d02a851f2069..b61a8f656bb2c7 100644 --- a/src/test/java/net/starlark/java/eval/StarlarkMutableTest.java +++ b/src/test/java/net/starlark/java/eval/StarlarkMutableTest.java @@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.util.Iterator; -import java.util.List; import java.util.Map; import org.junit.Test; import org.junit.runner.RunWith; @@ -46,24 +45,13 @@ public void testListViewsCheckMutability() throws Exception { () -> it.remove()); } { - Iterator it = list.listIterator(); - it.next(); - assertThrows( - UnsupportedOperationException.class, - () -> it.remove()); + assertThrows(UnsupportedOperationException.class, list::listIterator); } { - Iterator it = list.listIterator(1); - it.next(); - assertThrows( - UnsupportedOperationException.class, - () -> it.remove()); + assertThrows(UnsupportedOperationException.class, () -> list.listIterator(1)); } { - List sublist = list.subList(1, 2); - assertThrows( - UnsupportedOperationException.class, - () -> sublist.set(0, 4)); + assertThrows(UnsupportedOperationException.class, () -> list.subList(1, 2)); } }