/** * 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); } }
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; }
JSType thisType = thisMap.getResolvedTemplateType(thisKey); EquivalenceMatch thisMatch = EquivalenceMatch.NO_KEY_MATCH; JSType thatType = thatMap.getResolvedTemplateType(thatKey);
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()); }
/** * 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); }
/** * Special handling for simple typing returning polymorphic this type in TypeScript. Prefer * `func(): this` instead of `func<T>(this: T): T` when any params are not templatized. */ private boolean shouldSkipEmittingThisTemplateAndParam(FunctionType ftype) { final JSType typeOfThis = ftype.getTypeOfThis(); if (typeOfThis == null || !typeOfThis.isTemplateType() || !typeOfThis.equals(ftype.getReturnType())) { return false; } Iterator<Node> parameters = ftype.getParameters().iterator(); while (parameters.hasNext()) { final JSType paramType = parameters.next().getJSType(); if (!paramType.isTemplatizedType()) { continue; } final TemplateTypeMap templateTypeMap = paramType.getTemplateTypeMap(); for (TemplateType key : templateTypeMap.getTemplateKeys()) { if (templateTypeMap.getResolvedTemplateType(key).equals(typeOfThis)) { return false; } } } return true; }
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); } }
return registry.createTemplatizedType( objectType, templates.getResolvedTemplateType(registry.getObjectIndexKey()), templates.getResolvedTemplateType(registry.getObjectElementKey()));
JSType resolvedTemplateType = ttMap.getResolvedTemplateType(templateType); visitType(resolvedTemplateType, false, false); emit(">");
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);
.autobox() .getTemplateTypeMap() .getResolvedTemplateType(typeRegistry.getIterableTemplate());
private FlowScope traverseGetElem(Node n, FlowScope scope) { scope = traverseChildren(n, scope); Node indexKey = n.getLastChild(); JSType indexType = getJSType(indexKey); if (indexType.isSymbolValueType()) { // For now, allow symbols definitions/access on any type. In the future only allow them // on the subtypes for which they are defined. // TODO(b/77474174): Type well known symbol accesses. n.setJSType(unknownType); } else { JSType type = getJSType(n.getFirstChild()).restrictByNotNullOrUndefined(); TemplateTypeMap typeMap = type.getTemplateTypeMap(); if (typeMap.hasTemplateType(registry.getObjectElementKey())) { n.setJSType(typeMap.getResolvedTemplateType(registry.getObjectElementKey())); } } return tightenTypeAfterDereference(n.getFirstChild(), scope); }
TemplateType key = keys.get(index); maybeResolveTemplatedType( paramTypeMap.getResolvedTemplateType(key), argTypeMap.getResolvedTemplateType(key), resolvedTypes, seenTypes);
.hasTemplateKey(typeRegistry.getObjectIndexKey())) { expectCanAssignTo(t, indexNode, indexType, dereferenced .getTemplateTypeMap().getResolvedTemplateType(typeRegistry.getObjectIndexKey()), "restricted index type"); } else if (dereferenced != null && dereferenced.isArrayType()) {
JSType thisElement = thisTypeParams.getResolvedTemplateType(key); JSType thatElement = thatTypeParams.getResolvedTemplateType(key);
.hasTemplateKey(typeRegistry.getObjectIndexKey())) { expectCanAssignTo(t, indexNode, indexType, dereferenced .getTemplateTypeMap().getResolvedTemplateType(typeRegistry.getObjectIndexKey()), "restricted index type"); } else if (dereferenced != null && dereferenced.isArrayType()) {
registry, templates.getResolvedTemplateType(registry.getIThenableTemplate()));
for (TemplateType key : paramTypeMap.getTemplateKeys()) { maybeResolveTemplatedType( paramTypeMap.getResolvedTemplateType(key), argTypeMap.getResolvedTemplateType(key), resolvedTypes, seenTypes);