/** * Returns the template type argument in this type's map corresponding to the supertype's template * parameter, or the UNKNOWN_TYPE if the supertype template key is not present. * * <p>Note: this only supports arguments that have a singleton list of template keys, and will * throw an exception for arguments with zero or multiple or template keys. */ public JSType getInstantiatedTypeArgument(JSType supertype) { TemplateType templateType = Iterables.getOnlyElement(supertype.getTemplateTypeMap().getTemplateKeys()); return getTemplateTypeMap().getResolvedTemplateType(templateType); } }
/** * Creates a template type map from the specified list of template keys and * template value types. */ public TemplateTypeMap createTemplateTypeMap( ImmutableList<TemplateType> templateKeys, ImmutableList<JSType> templateValues) { templateKeys = templateKeys == null ? ImmutableList.<TemplateType>of() : templateKeys; templateValues = templateValues == null ? ImmutableList.<JSType>of() : templateValues; return (templateKeys.isEmpty() && templateValues.isEmpty()) ? emptyTemplateTypeMap : new TemplateTypeMap(this, templateKeys, templateValues); }
public boolean checkEquivalenceHelper(TemplateTypeMap that, EquivalenceMethod eqMethod, EqCache eqCache) { boolean result = false; if (!this.inRecursiveEquivalenceCheck && !that.inRecursiveEquivalenceCheck) { this.inRecursiveEquivalenceCheck = true; that.inRecursiveEquivalenceCheck = true; result = checkEquivalenceHelper(eqMethod, this, that, eqCache) && checkEquivalenceHelper(eqMethod, that, this, eqCache); this.inRecursiveEquivalenceCheck = false; that.inRecursiveEquivalenceCheck = false; } return result; }
/** * Extends this TemplateTypeMap with the contents of the specified map. UNKNOWN_TYPE will be used * as the value for any missing values in the specified map. */ TemplateTypeMap extend(TemplateTypeMap other) { ImmutableList<JSType> resizedOtherValues = other.resizedToMatchKeys(other.templateValues); return registry.createTemplateTypeMap( concatImmutableLists(other.templateKeys, templateKeys), concatImmutableLists(resizedOtherValues, templateValues)); }
/** * Extends this TemplateTypeMap with the contents of the specified map. * UNKNOWN_TYPE will be used as the value for any missing values in the * specified map. */ TemplateTypeMap extend(TemplateTypeMap thatMap) { thatMap = thatMap.addUnknownValues(); return registry.createTemplateTypeMap( concatImmutableLists(thatMap.templateKeys, templateKeys), concatImmutableLists(thatMap.templateValues, templateValues)); }
/** * Returns the JSType value associated with the specified template key. If no * JSType value is associated, returns UNKNOWN_TYPE. */ public JSType getResolvedTemplateType(TemplateType key) { TemplateTypeMap resolvedMap = this.addUnknownValues(); int index = resolvedMap.getTemplateTypeIndex(key); return (index == -1) ? registry.getNativeType(JSTypeNative.UNKNOWN_TYPE) : resolvedMap.resolvedTemplateValues.get(index); }
public final ImmutableSet<JSType> getTypeParameters() { ImmutableSet.Builder<JSType> params = ImmutableSet.builder(); for (TemplateType type : getTemplateTypeMap().getTemplateKeys()) { params.add(type); } return params.build(); }
private static boolean checkEquivalenceHelper(EquivalenceMethod eqMethod, TemplateTypeMap thisMap, TemplateTypeMap thatMap, EqCache eqCache, SubtypingMode subtypingMode) { ImmutableList<TemplateType> thisKeys = thisMap.getTemplateKeys(); ImmutableList<TemplateType> thatKeys = thatMap.getTemplateKeys(); JSType thisType = thisMap.getResolvedTemplateType(thisKey); EquivalenceMatch thisMatch = EquivalenceMatch.NO_KEY_MATCH; JSType thatType = thatMap.getResolvedTemplateType(thatKey); if (isSameKey(thisKey, thatKey)) { EquivalenceMatch newMatchType = EquivalenceMatch.VALUE_MISMATCH; if (thisType.checkEquivalenceHelper(thatType, eqMethod, eqCache) if (failedEquivalenceCheck(thisMatch, eqMethod)) { return false;
/** * Returns the given `Iterable`s element type. * * <p>If the given type is not an `Iterator`, `Iterable`, `AsyncIterator`, or `AsyncIterable`, * returns the unknown type. */ static final JSType getElementType(JSType iterableOrIterator, JSTypeRegistry typeRegistry) { TemplateTypeMap templateTypeMap = iterableOrIterator // Remember that `string` will box to a `Iterable`. .autobox() .getTemplateTypeMap(); if (templateTypeMap.hasTemplateKey(typeRegistry.getIterableTemplate())) { // `Iterable<SomeElementType>` or `Generator<SomeElementType>` return templateTypeMap.getResolvedTemplateType(typeRegistry.getIterableTemplate()); } else if (templateTypeMap.hasTemplateKey(typeRegistry.getIteratorTemplate())) { // `Iterator<SomeElementType>` return templateTypeMap.getResolvedTemplateType(typeRegistry.getIteratorTemplate()); } else if (templateTypeMap.hasTemplateKey(typeRegistry.getAsyncIterableTemplate())) { // `AsyncIterable<SomeElementType>` or `AsyncGenerator<SomeElementType>` return templateTypeMap.getResolvedTemplateType(typeRegistry.getAsyncIterableTemplate()); } else if (templateTypeMap.hasTemplateKey(typeRegistry.getAsyncIteratorTemplate())) { // `AsyncIterator<SomeElementType>` return templateTypeMap.getResolvedTemplateType(typeRegistry.getAsyncIteratorTemplate()); } return typeRegistry.getNativeType(UNKNOWN_TYPE); }
private static boolean checkEquivalenceHelper(EquivalenceMethod eqMethod, TemplateTypeMap thisMap, TemplateTypeMap thatMap, EqCache eqCache) { ImmutableList<TemplateType> thisKeys = thisMap.getTemplateKeys(); ImmutableList<TemplateType> thatKeys = thatMap.getTemplateKeys(); for (int i = 0; i < thisKeys.size(); i++) { TemplateType thisKey = thisKeys.get(i); JSType thisType = thisMap.getResolvedTemplateType(thisKey); EquivalenceMatch thisMatch = EquivalenceMatch.NO_KEY_MATCH; for (int j = 0; j < thatKeys.size(); j++) { TemplateType thatKey = thatKeys.get(j); JSType thatType = thatMap.getResolvedTemplateType(thatKey); // Cross-compare every key-value pair in this TemplateTypeMap with // those in that TemplateTypeMap. Update the Equivalence match for both // key-value pairs involved. if (thisKey == thatKey) { EquivalenceMatch newMatchType = EquivalenceMatch.VALUE_MISMATCH; if (thisType.checkEquivalenceHelper(thatType, eqMethod, eqCache)) { newMatchType = EquivalenceMatch.VALUE_MATCH; } if (thisMatch != EquivalenceMatch.VALUE_MATCH) { thisMatch = newMatchType; } } } if (failedEquivalenceCheck(thisMatch, eqMethod)) { return false; } } return true; }
/** * Coerces this type to an Object type, then gets the type of the property whose name is given. * * <p>Unlike {@link ObjectType#getPropertyType}, returns null if the property is not found. * * @return The property's type. {@code null} if the current type cannot have properties, or if the * type is not found. */ @Nullable public final JSType findPropertyType(String propertyName) { @Nullable JSType propertyType = findPropertyTypeWithoutConsideringTemplateTypes(propertyName); if (propertyType == null) { return null; } // Do templatized type replacing logic here, and make this method final, to prevent a subclass // from forgetting to replace template types if (getTemplateTypeMap().isEmpty() || !propertyType.hasAnyTemplateTypes()) { return propertyType; } TemplateTypeMap typeMap = getTemplateTypeMap(); TemplateTypeMapReplacer replacer = new TemplateTypeMapReplacer(registry, typeMap); return propertyType.visit(replacer); }
TemplatizedType( JSTypeRegistry registry, ObjectType objectType, ImmutableList<JSType> templateTypes) { super(registry, objectType, objectType.getTemplateTypeMap().addValues( templateTypes)); // Cache which template keys were filled, and what JSTypes they were filled // with. ImmutableList<TemplateType> filledTemplateKeys = objectType.getTemplateTypeMap().getUnfilledTemplateKeys(); ImmutableList.Builder<JSType> builder = ImmutableList.builder(); for (TemplateType filledTemplateKey : filledTemplateKeys) { builder.add(getTemplateTypeMap().getResolvedTemplateType(filledTemplateKey)); } this.templateTypes = builder.build(); replacer = new TemplateTypeMapReplacer(registry, getTemplateTypeMap()); }
TemplatizedType( JSTypeRegistry registry, ObjectType objectType, ImmutableList<JSType> templateTypes) { super( registry, objectType, objectType.getTemplateTypeMap().copyFilledWithValues(templateTypes)); ImmutableList.Builder<JSType> builder = ImmutableList.builder(); boolean maybeIsSpecializedOnlyWithUnknown = true; for (TemplateType newlyFilledTemplateKey : objectType.getTemplateTypeMap().getUnfilledTemplateKeys()) { JSType resolvedType = getTemplateTypeMap().getResolvedTemplateType(newlyFilledTemplateKey); builder.add(resolvedType); maybeIsSpecializedOnlyWithUnknown = maybeIsSpecializedOnlyWithUnknown && resolvedType.isUnknownType(); } this.templateTypes = builder.build(); this.isSpecializedOnlyWithUnknown = maybeIsSpecializedOnlyWithUnknown; this.replacer = new TemplateTypeMapReplacer(registry, getTemplateTypeMap()); }
private FlowScope traverseGetElem(Node n, FlowScope scope) { scope = traverseChildren(n, scope); JSType type = getJSType(n.getFirstChild()).restrictByNotNullOrUndefined(); TemplateTypeMap typeMap = type.getTemplateTypeMap(); if (typeMap.hasTemplateType(registry.getObjectElementKey())) { n.setJSType(typeMap.getResolvedTemplateType(registry.getObjectElementKey())); } return dereferencePointer(n.getFirstChild(), scope); }
JSType thisElement = thisTypeParams.getResolvedTemplateType(key); JSType thatElement = thatTypeParams.getResolvedTemplateType(key); JSType thisElement = thisTypeParams.getResolvedTemplateType(key); JSType thatElement = thatTypeParams.getResolvedTemplateType(key); templateMatch = thisTypeParams.checkEquivalenceHelper( thatTypeParams, EquivalenceMethod.INVARIANT, subtypingMode);
if (type.hasAnyTemplateTypes() && !type.getTemplateTypeMap().isEmpty()) { List<String> realTemplateType = new ArrayList<>(); for (TemplateType templateType : type.getTemplateTypeMap().getTemplateKeys()) { String displayName = templateType.getDisplayName();
private JSType inferObjectPatternKeyType() { JSType patternType = patternTypeSupplier.get(); if (isRest) { return inferObjectRestType(patternType); } if (patternType == null || patternType.isUnknownType()) { return registry.getNativeType(JSTypeNative.UNKNOWN_TYPE); } switch (objectPatternKey.getToken()) { case STRING_KEY: JSType propertyType = patternType.findPropertyType(objectPatternKey.getString()); return propertyType != null ? propertyType : registry.getNativeType(JSTypeNative.UNKNOWN_TYPE); case COMPUTED_PROP: return patternType != null ? patternType .getTemplateTypeMap() .getResolvedTemplateType(registry.getObjectElementKey()) : registry.getNativeType(JSTypeNative.UNKNOWN_TYPE); default: throw new IllegalStateException("Unexpected key " + objectPatternKey); } }
/** * Returns a new TemplateTypeMap whose values have been extended with the * specified list. */ TemplateTypeMap addValues(ImmutableList<JSType> newValues) { // Ignore any new template values that will not align with an existing // template key. int numUnfilledKeys = numUnfilledTemplateKeys(); if (numUnfilledKeys < newValues.size()) { newValues = newValues.subList(0, numUnfilledKeys); } return registry.createTemplateTypeMap( templateKeys, concatImmutableLists(templateValues, newValues)); }
/** * Returns true if there is a JSType value associated with the specified * template key; false otherwise. */ public boolean hasTemplateType(TemplateType key) { return getTemplateTypeIndex(key) != -1; }
/** * Extends the template type map associated with this type, merging in the * keys and values of the specified map. */ public void extendTemplateTypeMap(TemplateTypeMap otherMap) { templateTypeMap = templateTypeMap.extend(otherMap); }