Search in sources :

Example 1 with TemplatizedType

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);
                }
            }
        }
    }
}
Also used : UnionType(com.google.javascript.rhino.jstype.UnionType) ObjectType(com.google.javascript.rhino.jstype.ObjectType) TemplateTypeMap(com.google.javascript.rhino.jstype.TemplateTypeMap) JSType(com.google.javascript.rhino.jstype.JSType) Set(java.util.Set) BooleanLiteralSet(com.google.javascript.rhino.jstype.BooleanLiteralSet) FunctionType(com.google.javascript.rhino.jstype.FunctionType) TemplateType(com.google.javascript.rhino.jstype.TemplateType) TemplatizedType(com.google.javascript.rhino.jstype.TemplatizedType)

Example 2 with TemplatizedType

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;
}
Also used : ObjectType(com.google.javascript.rhino.jstype.ObjectType) JSType(com.google.javascript.rhino.jstype.JSType) NamedType(com.google.javascript.rhino.jstype.NamedType) TemplatizedType(com.google.javascript.rhino.jstype.TemplatizedType)

Aggregations

JSType (com.google.javascript.rhino.jstype.JSType)2 ObjectType (com.google.javascript.rhino.jstype.ObjectType)2 TemplatizedType (com.google.javascript.rhino.jstype.TemplatizedType)2 BooleanLiteralSet (com.google.javascript.rhino.jstype.BooleanLiteralSet)1 FunctionType (com.google.javascript.rhino.jstype.FunctionType)1 NamedType (com.google.javascript.rhino.jstype.NamedType)1 TemplateType (com.google.javascript.rhino.jstype.TemplateType)1 TemplateTypeMap (com.google.javascript.rhino.jstype.TemplateTypeMap)1 UnionType (com.google.javascript.rhino.jstype.UnionType)1 Set (java.util.Set)1