use of com.google.javascript.rhino.jstype.TemplatizedType in project closure-compiler by google.
the class TypeInference method maybeResolveTemplatedType.
private void maybeResolveTemplatedType(JSType paramType, JSType argType, Map<TemplateType, JSType> resolvedTypes, Set<JSType> seenTypes) {
if (paramType.isTemplateType()) {
// example: @param {T}
resolvedTemplateType(resolvedTypes, paramType.toMaybeTemplateType(), argType);
} else if (paramType.isUnionType()) {
// example: @param {Array.<T>|NodeList|Arguments|{length:number}}
UnionType unionType = paramType.toMaybeUnionType();
for (JSType alernative : unionType.getAlternates()) {
maybeResolveTemplatedType(alernative, argType, resolvedTypes, seenTypes);
}
} else if (paramType.isFunctionType()) {
FunctionType paramFunctionType = paramType.toMaybeFunctionType();
FunctionType argFunctionType = argType.restrictByNotNullOrUndefined().collapseUnion().toMaybeFunctionType();
if (argFunctionType != null && argFunctionType.isSubtype(paramType)) {
// infer from return type of the function type
maybeResolveTemplatedType(paramFunctionType.getTypeOfThis(), argFunctionType.getTypeOfThis(), resolvedTypes, seenTypes);
// infer from return type of the function type
maybeResolveTemplatedType(paramFunctionType.getReturnType(), argFunctionType.getReturnType(), resolvedTypes, seenTypes);
// infer from parameter types of the function type
maybeResolveTemplateTypeFromNodes(paramFunctionType.getParameters(), argFunctionType.getParameters(), resolvedTypes, seenTypes);
}
} else if (paramType.isRecordType() && !paramType.isNominalType()) {
// example: @param {{foo:T}}
if (seenTypes.add(paramType)) {
ObjectType paramRecordType = paramType.toObjectType();
ObjectType argObjectType = argType.restrictByNotNullOrUndefined().toObjectType();
if (argObjectType != null && !argObjectType.isUnknownType() && !argObjectType.isEmptyType()) {
Set<String> names = paramRecordType.getPropertyNames();
for (String name : names) {
if (paramRecordType.hasOwnProperty(name) && argObjectType.hasProperty(name)) {
maybeResolveTemplatedType(paramRecordType.getPropertyType(name), argObjectType.getPropertyType(name), resolvedTypes, seenTypes);
}
}
}
seenTypes.remove(paramType);
}
} else if (paramType.isTemplatizedType()) {
// example: @param {Array<T>}
TemplatizedType templatizedParamType = paramType.toMaybeTemplatizedType();
int keyCount = templatizedParamType.getTemplateTypes().size();
// types with no type arguments.
if (keyCount > 0) {
ObjectType referencedParamType = templatizedParamType.getReferencedType();
JSType argObjectType = argType.restrictByNotNullOrUndefined().collapseUnion();
if (argObjectType.isSubtypeOf(referencedParamType)) {
// If the argument type is a subtype of the parameter type, resolve any
// template types amongst their templatized types.
TemplateTypeMap paramTypeMap = paramType.getTemplateTypeMap();
ImmutableList<TemplateType> keys = paramTypeMap.getTemplateKeys();
TemplateTypeMap argTypeMap = argObjectType.getTemplateTypeMap();
for (int index = keys.size() - keyCount; index < keys.size(); index++) {
TemplateType key = keys.get(index);
maybeResolveTemplatedType(paramTypeMap.getResolvedTemplateType(key), argTypeMap.getResolvedTemplateType(key), resolvedTypes, seenTypes);
}
}
}
}
}
use of com.google.javascript.rhino.jstype.TemplatizedType in project closure-compiler by google.
the class TypeCheck method isReasonableObjectPropertyKey.
/**
* Checks whether type is useful as the key of an object property access.
* This means it should be either stringifiable or a symbol.
* Stringifiable types are types that can be converted to string
* and give unique results for different objects. For example objects have native toString()
* method that on chrome returns "[object Object]" for all objects making it useless when used
* as keys. At the same time native types like numbers can be safely converted to strings and
* used as keys. Also user might have provided custom toString() methods for a class making it
* suitable for using as key.
*/
private boolean isReasonableObjectPropertyKey(JSType type) {
// Check built-in types
if (type.isUnknownType() || type.isNumber() || type.isString() || type.isSymbol() || type.isBooleanObjectType() || type.isBooleanValueType() || type.isDateType() || type.isRegexpType() || type.isInterface() || type.isRecordType() || type.isNullType() || type.isVoidType()) {
return true;
}
// For enums check that underlying type is stringifiable.
if (type.toMaybeEnumElementType() != null) {
return isReasonableObjectPropertyKey(type.toMaybeEnumElementType().getPrimitiveType());
}
// Bad: Array.<!Object>
if (type.isArrayType()) {
return true;
}
if (type.isTemplatizedType()) {
TemplatizedType templatizedType = type.toMaybeTemplatizedType();
if (templatizedType.getReferencedType().isArrayType()) {
return isReasonableObjectPropertyKey(templatizedType.getTemplateTypes().get(0));
}
}
// in @typedef annotation.
if (type instanceof NamedType) {
return isReasonableObjectPropertyKey(((NamedType) type).getReferencedType());
}
// For union type every alternate must be stringifiable.
if (type.isUnionType()) {
for (JSType alternateType : type.toMaybeUnionType().getAlternates()) {
if (!isReasonableObjectPropertyKey(alternateType)) {
return false;
}
}
return true;
}
// Handle interfaces and classes.
if (type.isObject()) {
ObjectType objectType = type.toMaybeObjectType();
JSType constructor = objectType.getConstructor();
// classes-implementations.
if (constructor != null && constructor.isInterface()) {
return true;
}
// This is user-defined class so check if it has custom toString() method.
return classHasToString(objectType);
}
return false;
}
Aggregations