@Override public JSType collapseUnion() { JSType currentValue = null; ObjectType currentCommonSuper = null; for (int i = 0; i < alternatesRetainingStructuralSubtypes.size(); i++) { JSType a = alternatesRetainingStructuralSubtypes.get(i); if (a.isUnknownType()) { return getNativeType(JSTypeNative.UNKNOWN_TYPE); } ObjectType obj = a.toObjectType(); if (obj == null) { if (currentValue == null && currentCommonSuper == null) { // If obj is not an object, then it must be a value. currentValue = a; } else { // Multiple values and objects will always collapse to the ALL_TYPE. return getNativeType(JSTypeNative.ALL_TYPE); } } else if (currentValue != null) { // Values and objects will always collapse to the ALL_TYPE. return getNativeType(JSTypeNative.ALL_TYPE); } else if (currentCommonSuper == null) { currentCommonSuper = obj; } else { currentCommonSuper = registry.findCommonSuperObject(currentCommonSuper, obj); } } return currentCommonSuper; }
@Override public JSType collapseUnion() { JSType currentValue = null; ObjectType currentCommonSuper = null; for (JSType a : alternatesWithoutStucturalTyping) { if (a.isUnknownType()) { return getNativeType(JSTypeNative.UNKNOWN_TYPE); } ObjectType obj = a.toObjectType(); if (obj == null) { if (currentValue == null && currentCommonSuper == null) { // If obj is not an object, then it must be a value. currentValue = a; } else { // Multiple values and objects will always collapse to the ALL_TYPE. return getNativeType(JSTypeNative.ALL_TYPE); } } else if (currentValue != null) { // Values and objects will always collapse to the ALL_TYPE. return getNativeType(JSTypeNative.ALL_TYPE); } else if (currentCommonSuper == null) { currentCommonSuper = obj; } else { currentCommonSuper = registry.findCommonSuperObject(currentCommonSuper, obj); } } return currentCommonSuper; }
@Override public Boolean caseUnionType(UnionType thisType, JSType thatType) { boolean visited = false; for (JSType type : thisType.getAlternates()) { if (type.isVoidType() || type.isNullType()) { // Don't allow if the only match between the types is null or void, // otherwise any nullable type would be castable to any other nullable // type and we don't want that. } else { visited = true; if (type.visit(this, thatType)) { return true; } } } // Special case the "null|undefined" union and allow it to be cast // to any cast to any type containing allowing either null|undefined. if (!visited) { JSType NULL_TYPE = thisType.getNativeType(JSTypeNative.NULL_TYPE); JSType VOID_TYPE = thisType.getNativeType(JSTypeNative.VOID_TYPE); return NULL_TYPE.visit(this, thatType) || VOID_TYPE.visit(this, thatType); } return false; }
@Override public Boolean caseUnionType(UnionType thisType, JSType thatType) { boolean visited = false; for (JSType type : thisType.getAlternates()) { if (type.isVoidType() || type.isNullType()) { // Don't allow if the only match between the types is null or void, // otherwise any nullable type would be castable to any other nullable // type and we don't want that. } else { visited = true; if (type.visit(this, thatType)) { return true; } } } // Special case the "null|undefined" union and allow it to be cast // to any cast to any type containing allowing either null|undefined. if (!visited) { JSType NULL_TYPE = thisType.getNativeType(JSTypeNative.NULL_TYPE); JSType VOID_TYPE = thisType.getNativeType(JSTypeNative.VOID_TYPE); return NULL_TYPE.visit(this, thatType) || VOID_TYPE.visit(this, thatType); } return false; }
JSType meet(JSType that) { UnionTypeBuilder builder = UnionTypeBuilder.create(registry); for (int i = 0; i < alternatesRetainingStructuralSubtypes.size(); i++) { JSType alternate = alternatesRetainingStructuralSubtypes.get(i); if (alternate.isSubtypeOf(that)) { builder.addAlternate(alternate); } } if (that.isUnionType()) { List<JSType> thoseAlternatesWithoutStucturalTyping = that.toMaybeUnionType().alternatesRetainingStructuralSubtypes; for (int i = 0; i < thoseAlternatesWithoutStucturalTyping.size(); i++) { JSType otherAlternate = thoseAlternatesWithoutStucturalTyping.get(i); if (otherAlternate.isSubtypeOf(this)) { builder.addAlternate(otherAlternate); } } } else if (that.isSubtypeOf(this)) { builder.addAlternate(that); } JSType result = builder.build(); if (!result.isNoType()) { return result; } else if (this.isObject() && (that.isObject() && !that.isNoType())) { return getNativeType(JSTypeNative.NO_OBJECT_TYPE); } else { return getNativeType(JSTypeNative.NO_TYPE); } }
JSType meet(JSType that) { UnionTypeBuilder builder = new UnionTypeBuilder(registry); for (JSType alternate : alternatesWithoutStucturalTyping) { if (alternate.isSubtype(that)) { builder.addAlternate(alternate); } } if (that.isUnionType()) { for (JSType otherAlternate : that.toMaybeUnionType().alternatesWithoutStucturalTyping) { if (otherAlternate.isSubtype(this)) { builder.addAlternate(otherAlternate); } } } else if (that.isSubtype(this)) { builder.addAlternate(that); } JSType result = builder.build(); if (!result.isNoType()) { return result; } else if (this.isObject() && (that.isObject() && !that.isNoType())) { return getNativeType(JSTypeNative.NO_OBJECT_TYPE); } else { return getNativeType(JSTypeNative.NO_TYPE); } }