diff --git a/src/com/google/javascript/rhino/jstype/JSType.java b/src/com/google/javascript/rhino/jstype/JSType.java
index e595959c69d..98e30edaa4c 100644
--- a/src/com/google/javascript/rhino/jstype/JSType.java
+++ b/src/com/google/javascript/rhino/jstype/JSType.java
@@ -44,14 +44,13 @@
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.collect.HashBasedTable;
-import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableList;
import com.google.javascript.rhino.ErrorReporter;
import com.google.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.TypeI;
import java.io.Serializable;
import java.util.Comparator;
import java.util.IdentityHashMap;
-import java.util.List;
/**
* Represents JavaScript value types.
@@ -79,8 +78,8 @@ public abstract class JSType implements TypeI, Serializable {
private static final CanCastToVisitor CAN_CAST_TO_VISITOR =
new CanCastToVisitor();
- private static final ImmutableSet COVARIANT_TYPES =
- ImmutableSet.of("Object", "IArrayLike", "Array");
+ private static final ImmutableList COVARIANT_TYPES =
+ ImmutableList.of("Object", "IArrayLike", "Array");
/**
* Total ordering on types based on their textual representation.
@@ -303,9 +302,7 @@ public boolean containsArray() {
// Check if this is a union that contains an array
if (this.isUnionType()) {
JSType arrayType = registry.getNativeType(JSTypeNative.ARRAY_TYPE);
- List alternates = this.toMaybeUnionType().getAlternates();
- for (int i = 0; i < alternates.size(); i++) {
- JSType alternate = alternates.get(i);
+ for (JSType alternate : this.toMaybeUnionType().getAlternates()) {
if (alternate.isSubtype(arrayType)) {
return true;
}
@@ -1129,9 +1126,7 @@ static JSType filterNoResolvedType(JSType type) {
} else if (type.isUnionType()) {
UnionType unionType = type.toMaybeUnionType();
boolean needsFiltering = false;
- List alternates = unionType.getAlternates();
- for (int i = 0; i < alternates.size(); i++) {
- JSType alt = alternates.get(i);
+ for (JSType alt : unionType.getAlternates()) {
if (alt.isNoResolvedType()) {
needsFiltering = true;
break;
@@ -1411,10 +1406,8 @@ static boolean isSubtypeHelper(JSType thisType, JSType thatType,
// unions
if (thatType.isUnionType()) {
UnionType union = thatType.toMaybeUnionType();
- List alternates = union.alternatesWithoutStucturalTyping;
- // use indexed iteration to avoid iterator allocations
- for (int i = 0; i < alternates.size(); i++) {
- if (thisType.isSubtype(alternates.get(i), implicitImplCache, subtypingMode)) {
+ for (JSType element : union.alternatesWithoutStucturalTyping) {
+ if (thisType.isSubtype(element, implicitImplCache, subtypingMode)) {
return true;
}
}
diff --git a/src/com/google/javascript/rhino/jstype/UnionType.java b/src/com/google/javascript/rhino/jstype/UnionType.java
index 1d640203d82..0b852d92aed 100644
--- a/src/com/google/javascript/rhino/jstype/UnionType.java
+++ b/src/com/google/javascript/rhino/jstype/UnionType.java
@@ -44,7 +44,9 @@
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.javascript.rhino.ErrorReporter;
+
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -60,29 +62,26 @@
* statement is captured by making {@code (String,boolean)} and
* {@code (boolean,String)} equal.
*
- *
* The implementation of this class prevents the creation of nested
* unions.
*/
public class UnionType extends JSType {
private static final long serialVersionUID = 1L;
- // NOTE: to avoid allocating iterators, all the loops below iterate over alternates by index
- // instead of using the for-each loop idiom.
-
// alternates without merging structural interfaces and their subtypes
- List alternatesWithoutStucturalTyping;
+ Collection alternatesWithoutStucturalTyping;
// alternates under structural typing
- List alternates;
+ Collection alternates;
private int hashcode;
/**
* Creates a union type.
*
- * @param alternatesWithoutStructuralTyping the alternates of the union without structural typing
- * subtype
+ * @param alternatesWithoutStructuralTyping the alternates of the union without
+ * structural typing subtype
*/
- UnionType(JSTypeRegistry registry, List alternatesWithoutStructuralTyping) {
+ UnionType(JSTypeRegistry registry,
+ Collection alternatesWithoutStructuralTyping) {
super(registry);
this.alternatesWithoutStucturalTyping = alternatesWithoutStructuralTyping;
@@ -96,12 +95,11 @@ public class UnionType extends JSType {
/**
* Gets the alternate types of this union type.
- *
- * @return The alternate types of this union type. The returned set is immutable.
+ * @return The alternate types of this union type. The returned set is
+ * immutable.
*/
- public List getAlternates() {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType t = alternatesWithoutStucturalTyping.get(i);
+ public Collection getAlternates() {
+ for (JSType t : alternatesWithoutStucturalTyping) {
if (t.isUnionType()) {
rebuildAlternates();
break;
@@ -111,14 +109,13 @@ public List getAlternates() {
}
/**
- * Gets the alternate types of this union type, including structural interfaces and implicit
- * implementations as are distinct alternates.
- *
- * @return The alternate types of this union type. The returned set is immutable.
+ * Gets the alternate types of this union type, including structural interfaces
+ * and implicit implementations as are distinct alternates.
+ * @return The alternate types of this union type. The returned set is
+ * immutable.
*/
- public List getAlternatesWithoutStructuralTyping() {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType t = alternatesWithoutStucturalTyping.get(i);
+ public Collection getAlternatesWithoutStructuralTyping() {
+ for (JSType t : alternatesWithoutStucturalTyping) {
if (t.isUnionType()) {
rebuildAlternates();
break;
@@ -238,8 +235,7 @@ public JSType findPropertyType(String propertyName) {
@Override
public boolean canBeCalled() {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType t = alternatesWithoutStucturalTyping.get(i);
+ for (JSType t : alternatesWithoutStucturalTyping) {
if (!t.canBeCalled()) {
return false;
}
@@ -250,8 +246,7 @@ public boolean canBeCalled() {
@Override
public JSType autobox() {
UnionTypeBuilder restricted = new UnionTypeBuilder(registry);
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType t = alternatesWithoutStucturalTyping.get(i);
+ for (JSType t : alternatesWithoutStucturalTyping) {
restricted.addAlternate(t.autobox());
}
return restricted.build();
@@ -260,8 +255,7 @@ public JSType autobox() {
@Override
public JSType restrictByNotNullOrUndefined() {
UnionTypeBuilder restricted = new UnionTypeBuilder(registry);
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType t = alternatesWithoutStucturalTyping.get(i);
+ for (JSType t : alternatesWithoutStucturalTyping) {
restricted.addAlternate(t.restrictByNotNullOrUndefined());
}
return restricted.build();
@@ -270,8 +264,7 @@ public JSType restrictByNotNullOrUndefined() {
@Override
public TernaryValue testForEquality(JSType that) {
TernaryValue result = null;
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType t = alternatesWithoutStucturalTyping.get(i);
+ for (JSType t : alternatesWithoutStucturalTyping) {
TernaryValue test = t.testForEquality(that);
if (result == null) {
result = test;
@@ -292,8 +285,7 @@ public TernaryValue testForEquality(JSType that) {
*/
@Override
public boolean isNullable() {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType t = alternatesWithoutStucturalTyping.get(i);
+ for (JSType t : alternatesWithoutStucturalTyping) {
if (t.isNullable()) {
return true;
}
@@ -306,8 +298,7 @@ public boolean isNullable() {
*/
@Override
public boolean isVoidable() {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType t = alternatesWithoutStucturalTyping.get(i);
+ for (JSType t : alternatesWithoutStucturalTyping) {
if (t.isVoidable()) {
return true;
}
@@ -320,8 +311,7 @@ public boolean isVoidable() {
*/
@Override
public boolean isExplicitlyVoidable() {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType t = alternatesWithoutStucturalTyping.get(i);
+ for (JSType t : alternatesWithoutStucturalTyping) {
if (t.isExplicitlyVoidable()) {
return true;
}
@@ -331,8 +321,7 @@ public boolean isExplicitlyVoidable() {
@Override
public boolean isUnknownType() {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType t = alternatesWithoutStucturalTyping.get(i);
+ for (JSType t : alternatesWithoutStucturalTyping) {
if (t.isUnknownType()) {
return true;
}
@@ -342,9 +331,7 @@ public boolean isUnknownType() {
@Override
public boolean isStruct() {
- List alternates = getAlternates();
- for (int i = 0; i < alternates.size(); i++) {
- JSType typ = alternates.get(i);
+ for (JSType typ : getAlternates()) {
if (typ.isStruct()) {
return true;
}
@@ -354,9 +341,7 @@ public boolean isStruct() {
@Override
public boolean isDict() {
- List alternates = getAlternates();
- for (int i = 0; i < alternates.size(); i++) {
- JSType typ = alternates.get(i);
+ for (JSType typ : getAlternates()) {
if (typ.isDict()) {
return true;
}
@@ -367,8 +352,7 @@ public boolean isDict() {
@Override
public JSType getLeastSupertype(JSType that) {
if (!that.isUnknownType() && !that.isUnionType()) {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType alternate = alternatesWithoutStucturalTyping.get(i);
+ for (JSType alternate : alternatesWithoutStucturalTyping) {
if (!alternate.isUnknownType() && that.isSubtype(alternate)) {
return this;
}
@@ -380,18 +364,14 @@ public JSType getLeastSupertype(JSType that) {
JSType meet(JSType that) {
UnionTypeBuilder builder = new UnionTypeBuilder(registry);
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType alternate = alternatesWithoutStucturalTyping.get(i);
+ for (JSType alternate : alternatesWithoutStucturalTyping) {
if (alternate.isSubtype(that)) {
builder.addAlternate(alternate);
}
}
if (that.isUnionType()) {
- List thoseAlternatesWithoutStucturalTyping =
- that.toMaybeUnionType().alternatesWithoutStucturalTyping;
- for (int i = 0; i < thoseAlternatesWithoutStucturalTyping.size(); i++) {
- JSType otherAlternate = thoseAlternatesWithoutStucturalTyping.get(i);
+ for (JSType otherAlternate : that.toMaybeUnionType().alternatesWithoutStucturalTyping) {
if (otherAlternate.isSubtype(this)) {
builder.addAlternate(otherAlternate);
}
@@ -415,14 +395,13 @@ JSType meet(JSType that) {
*/
boolean checkUnionEquivalenceHelper(
UnionType that, EquivalenceMethod eqMethod, EqCache eqCache) {
- List thatAlternates = that.getAlternatesWithoutStructuralTyping();
+ Collection thatAlternates = that.getAlternatesWithoutStructuralTyping();
if (eqMethod == EquivalenceMethod.IDENTITY
&& getAlternatesWithoutStructuralTyping().size() != thatAlternates.size()) {
return false;
}
- for (int i = 0; i < thatAlternates.size(); i++) {
- JSType thatAlternate = thatAlternates.get(i);
- if (!hasAlternate(thatAlternate, eqMethod, eqCache)) {
+ for (JSType alternate : thatAlternates) {
+ if (!hasAlternate(alternate, eqMethod, eqCache)) {
return false;
}
}
@@ -431,9 +410,7 @@ && getAlternatesWithoutStructuralTyping().size() != thatAlternates.size()) {
private boolean hasAlternate(JSType type, EquivalenceMethod eqMethod,
EqCache eqCache) {
- List alternatesWithoutStructuralTyping = getAlternatesWithoutStructuralTyping();
- for (int i = 0; i < alternatesWithoutStructuralTyping.size(); i++) {
- JSType alternate = alternatesWithoutStructuralTyping.get(i);
+ for (JSType alternate : getAlternatesWithoutStructuralTyping()) {
if (alternate.checkEquivalenceHelper(type, eqMethod, eqCache)) {
return true;
}
@@ -443,8 +420,7 @@ private boolean hasAlternate(JSType type, EquivalenceMethod eqMethod,
@Override
public boolean hasProperty(String pname) {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType alternate = alternatesWithoutStucturalTyping.get(i);
+ for (JSType alternate : alternatesWithoutStucturalTyping) {
if (alternate.hasProperty(pname)) {
return true;
}
@@ -464,8 +440,7 @@ public UnionType toMaybeUnionType() {
@Override
public boolean isObject() {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType alternate = alternatesWithoutStucturalTyping.get(i);
+ for (JSType alternate : alternatesWithoutStucturalTyping) {
if (!alternate.isObject()) {
return false;
}
@@ -482,8 +457,7 @@ public boolean isObject() {
* @return {@code true} if the alternate is in the union
*/
public boolean contains(JSType type) {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType alt = alternatesWithoutStucturalTyping.get(i);
+ for (JSType alt : alternatesWithoutStucturalTyping) {
if (alt.isEquivalentTo(type)) {
return true;
}
@@ -507,8 +481,7 @@ public boolean contains(JSType type) {
*/
public JSType getRestrictedUnion(JSType type) {
UnionTypeBuilder restricted = new UnionTypeBuilder(registry);
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType t = alternatesWithoutStucturalTyping.get(i);
+ for (JSType t : alternatesWithoutStucturalTyping) {
// Keep all unknown/unresolved types.
if (t.isUnknownType() || t.isNoResolvedType() || !t.isSubtype(type)) {
restricted.addAlternate(t);
@@ -551,8 +524,7 @@ protected boolean isSubtype(JSType that,
if (that.isAllType()) {
return true;
}
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType element = alternatesWithoutStucturalTyping.get(i);
+ for (JSType element : alternatesWithoutStucturalTyping) {
if (subtypingMode == SubtypingMode.IGNORE_NULL_UNDEFINED
&& (element.isNullType() || element.isVoidType())) {
continue;
@@ -568,8 +540,7 @@ protected boolean isSubtype(JSType that,
public JSType getRestrictedTypeGivenToBooleanOutcome(boolean outcome) {
// gather elements after restriction
UnionTypeBuilder restricted = new UnionTypeBuilder(registry);
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType element = alternatesWithoutStucturalTyping.get(i);
+ for (JSType element : alternatesWithoutStucturalTyping) {
restricted.addAlternate(
element.getRestrictedTypeGivenToBooleanOutcome(outcome));
}
@@ -579,8 +550,7 @@ public JSType getRestrictedTypeGivenToBooleanOutcome(boolean outcome) {
@Override
public BooleanLiteralSet getPossibleToBooleanOutcomes() {
BooleanLiteralSet literals = BooleanLiteralSet.EMPTY;
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType element = alternatesWithoutStucturalTyping.get(i);
+ for (JSType element : alternatesWithoutStucturalTyping) {
literals = literals.union(element.getPossibleToBooleanOutcomes());
if (literals == BooleanLiteralSet.BOTH) {
break;
@@ -593,8 +563,7 @@ public BooleanLiteralSet getPossibleToBooleanOutcomes() {
public TypePair getTypesUnderEquality(JSType that) {
UnionTypeBuilder thisRestricted = new UnionTypeBuilder(registry);
UnionTypeBuilder thatRestricted = new UnionTypeBuilder(registry);
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType element = alternatesWithoutStucturalTyping.get(i);
+ for (JSType element : alternatesWithoutStucturalTyping) {
TypePair p = element.getTypesUnderEquality(that);
if (p.typeA != null) {
thisRestricted.addAlternate(p.typeA);
@@ -612,8 +581,7 @@ public TypePair getTypesUnderEquality(JSType that) {
public TypePair getTypesUnderInequality(JSType that) {
UnionTypeBuilder thisRestricted = new UnionTypeBuilder(registry);
UnionTypeBuilder thatRestricted = new UnionTypeBuilder(registry);
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType element = alternatesWithoutStucturalTyping.get(i);
+ for (JSType element : alternatesWithoutStucturalTyping) {
TypePair p = element.getTypesUnderInequality(that);
if (p.typeA != null) {
thisRestricted.addAlternate(p.typeA);
@@ -631,8 +599,7 @@ public TypePair getTypesUnderInequality(JSType that) {
public TypePair getTypesUnderShallowInequality(JSType that) {
UnionTypeBuilder thisRestricted = new UnionTypeBuilder(registry);
UnionTypeBuilder thatRestricted = new UnionTypeBuilder(registry);
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType element = alternatesWithoutStucturalTyping.get(i);
+ for (JSType element : alternatesWithoutStucturalTyping) {
TypePair p = element.getTypesUnderShallowInequality(that);
if (p.typeA != null) {
thisRestricted.addAlternate(p.typeA);
@@ -659,8 +626,9 @@ public T visit(Visitor visitor) {
JSType resolveInternal(ErrorReporter t, StaticTypedScope scope) {
setResolvedTypeInternal(this); // for circularly defined types.
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType alternate = alternatesWithoutStucturalTyping.get(i);
+ // Just resolve the alternates, but do not update as that breaks some error
+ // reporting cases.
+ for (JSType alternate : alternatesWithoutStucturalTyping) {
alternate.resolve(t, scope);
}
// Ensure the union is in a normalized state.
@@ -679,8 +647,7 @@ public String toDebugHashCodeString() {
@Override
public boolean setValidator(Predicate validator) {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType a = alternatesWithoutStucturalTyping.get(i);
+ for (JSType a : alternatesWithoutStucturalTyping) {
a.setValidator(validator);
}
return true;
@@ -690,8 +657,7 @@ public boolean setValidator(Predicate validator) {
public JSType collapseUnion() {
JSType currentValue = null;
ObjectType currentCommonSuper = null;
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType a = alternatesWithoutStucturalTyping.get(i);
+ for (JSType a : alternatesWithoutStucturalTyping) {
if (a.isUnknownType()) {
return getNativeType(JSTypeNative.UNKNOWN_TYPE);
}
@@ -720,16 +686,14 @@ public JSType collapseUnion() {
@Override
public void matchConstraint(JSType constraint) {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType alternate = alternatesWithoutStucturalTyping.get(i);
+ for (JSType alternate : alternatesWithoutStucturalTyping) {
alternate.matchConstraint(constraint);
}
}
@Override
public boolean hasAnyTemplateTypesInternal() {
- for (int i = 0; i < alternatesWithoutStucturalTyping.size(); i++) {
- JSType alternate = alternatesWithoutStucturalTyping.get(i);
+ for (JSType alternate : alternatesWithoutStucturalTyping) {
if (alternate.hasAnyTemplateTypes()) {
return true;
}
diff --git a/src/com/google/javascript/rhino/jstype/UnionTypeBuilder.java b/src/com/google/javascript/rhino/jstype/UnionTypeBuilder.java
index 3a223d3398c..0ab70652e15 100644
--- a/src/com/google/javascript/rhino/jstype/UnionTypeBuilder.java
+++ b/src/com/google/javascript/rhino/jstype/UnionTypeBuilder.java
@@ -48,8 +48,10 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.javascript.rhino.jstype.JSType.SubtypingMode;
+
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -108,7 +110,7 @@ public UnionTypeBuilder(JSTypeRegistry registry) {
this.maxUnionSize = maxUnionSize;
}
- List getAlternates() {
+ Collection getAlternates() {
JSType specialCaseType = reduceAlternatesWithoutUnion();
if (specialCaseType != null) {
return ImmutableList.of(specialCaseType);
@@ -159,10 +161,7 @@ public UnionTypeBuilder addAlternate(JSType alternate, boolean isStructural) {
if (!isAllType && !isNativeUnknownType) {
if (alternate.isUnionType()) {
UnionType union = alternate.toMaybeUnionType();
- List alternatesWithoutStructuralTyping =
- union.getAlternatesWithoutStructuralTyping();
- for (int i = 0; i < alternatesWithoutStructuralTyping.size(); i++) {
- JSType unionAlt = alternatesWithoutStructuralTyping.get(i);
+ for (JSType unionAlt : union.getAlternatesWithoutStructuralTyping()) {
addAlternate(unionAlt);
}
} else {