Search in sources :

Example 6 with JSType

use of com.google.javascript.rhino.jstype.JSType in project closure-compiler by google.

the class TypeInference method tightenTypesAfterAssertions.

private FlowScope tightenTypesAfterAssertions(FlowScope scope, Node callNode) {
    Node left = callNode.getFirstChild();
    Node firstParam = left.getNext();
    AssertionFunctionSpec assertionFunctionSpec = assertionFunctionsMap.get(left.getQualifiedName());
    if (assertionFunctionSpec == null || firstParam == null) {
        return scope;
    }
    Node assertedNode = assertionFunctionSpec.getAssertedParam(firstParam);
    if (assertedNode == null) {
        return scope;
    }
    JSType assertedType = assertionFunctionSpec.getAssertedOldType(callNode, registry);
    String assertedNodeName = assertedNode.getQualifiedName();
    JSType narrowed;
    // Handle assertions that enforce expressions evaluate to true.
    if (assertedType == null) {
        // Handle arbitrary expressions within the assert.
        scope = reverseInterpreter.getPreciserScopeKnowingConditionOutcome(assertedNode, scope, true);
        // Build the result of the assertExpression
        narrowed = getJSType(assertedNode).restrictByNotNullOrUndefined();
    } else {
        // Handle assertions that enforce expressions are of a certain type.
        JSType type = getJSType(assertedNode);
        if (assertedType.isUnknownType() || type.isUnknownType()) {
            narrowed = assertedType;
        } else {
            narrowed = type.getGreatestSubtype(assertedType);
        }
        if (assertedNodeName != null && type.differsFrom(narrowed)) {
            scope = narrowScope(scope, assertedNode, narrowed);
        }
    }
    callNode.setJSType(narrowed);
    return scope;
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) AssertionFunctionSpec(com.google.javascript.jscomp.CodingConvention.AssertionFunctionSpec)

Example 7 with JSType

use of com.google.javascript.rhino.jstype.JSType in project closure-compiler by google.

the class TypeInference method updateScopeForTypeChange.

/**
 * Updates the scope according to the result of a type change, like
 * an assignment or a type cast.
 */
private void updateScopeForTypeChange(FlowScope scope, Node left, JSType leftType, JSType resultType) {
    checkNotNull(resultType);
    Node right = NodeUtil.getRValueOfLValue(left);
    if (isPossibleMixinApplication(left, right)) {
        addMissingInterfaceProperties(leftType);
    }
    switch(left.getToken()) {
        case NAME:
            String varName = left.getString();
            TypedVar var = currentScope.getVar(varName);
            JSType varType = var == null ? null : var.getType();
            boolean isVarDeclaration = left.hasChildren() && varType != null && !var.isTypeInferred() && var.getNameNode() != null;
            boolean isTypelessConstDecl = isVarDeclaration && NodeUtil.isConstantDeclaration(compiler.getCodingConvention(), var.getJSDocInfo(), var.getNameNode()) && !(var.getJSDocInfo() != null && var.getJSDocInfo().hasType());
            // When looking at VAR initializers for declared VARs, we tend
            // to use the declared type over the type it's being
            // initialized to in the global scope.
            // 
            // For example,
            // /** @param {number} */ var f = goog.abstractMethod;
            // it's obvious that the programmer wants you to use
            // the declared function signature, not the inferred signature.
            // 
            // Or,
            // /** @type {Object.<string>} */ var x = {};
            // the one-time anonymous object on the right side
            // is as narrow as it can possibly be, but we need to make
            // sure we back-infer the <string> element constraint on
            // the left hand side, so we use the left hand side.
            boolean isVarTypeBetter = isVarDeclaration && // Makes it easier to check for NPEs.
            !resultType.isNullType() && !resultType.isVoidType() && // because this type was computed from the RHS
            !isTypelessConstDecl;
            if (isVarTypeBetter) {
                redeclareSimpleVar(scope, left, varType);
            } else {
                redeclareSimpleVar(scope, left, resultType);
            }
            left.setJSType(resultType);
            if (var != null && var.isTypeInferred()) {
                JSType oldType = var.getType();
                var.setType(oldType == null ? resultType : oldType.getLeastSupertype(resultType));
            } else if (isTypelessConstDecl) {
                // /** @const */ var x = y;
                // should be redeclared, so that the type of y
                // gets propagated to inner scopes.
                var.setType(resultType);
            }
            break;
        case GETPROP:
            if (left.isQualifiedName()) {
                String qualifiedName = left.getQualifiedName();
                boolean declaredSlotType = false;
                JSType rawObjType = left.getFirstChild().getJSType();
                if (rawObjType != null) {
                    ObjectType objType = ObjectType.cast(rawObjType.restrictByNotNullOrUndefined());
                    if (objType != null) {
                        String propName = left.getLastChild().getString();
                        declaredSlotType = objType.isPropertyTypeDeclared(propName);
                    }
                }
                JSType safeLeftType = leftType == null ? unknownType : leftType;
                scope.inferQualifiedSlot(left, qualifiedName, safeLeftType, resultType, declaredSlotType);
            }
            left.setJSType(resultType);
            ensurePropertyDefined(left, resultType);
            break;
        default:
            break;
    }
}
Also used : ObjectType(com.google.javascript.rhino.jstype.ObjectType) JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node)

Example 8 with JSType

use of com.google.javascript.rhino.jstype.JSType in project closure-compiler by google.

the class TypeInference method traverseNew.

private FlowScope traverseNew(Node n, FlowScope scope) {
    scope = traverseChildren(n, scope);
    Node constructor = n.getFirstChild();
    JSType constructorType = constructor.getJSType();
    JSType type = null;
    if (constructorType != null) {
        constructorType = constructorType.restrictByNotNullOrUndefined();
        if (constructorType.isUnknownType()) {
            type = unknownType;
        } else {
            FunctionType ct = constructorType.toMaybeFunctionType();
            if (ct == null && constructorType instanceof FunctionType) {
                // If constructorType is a NoObjectType, then toMaybeFunctionType will
                // return null. But NoObjectType implements the FunctionType
                // interface, precisely because it can validly construct objects.
                ct = (FunctionType) constructorType;
            }
            if (ct != null && ct.isConstructor()) {
                backwardsInferenceFromCallSite(n, ct);
                // If necessary, create a TemplatizedType wrapper around the instance
                // type, based on the types of the constructor parameters.
                ObjectType instanceType = ct.getInstanceType();
                Map<TemplateType, JSType> inferredTypes = inferTemplateTypesFromParameters(ct, n);
                if (inferredTypes.isEmpty()) {
                    type = instanceType;
                } else {
                    type = registry.createTemplatizedType(instanceType, inferredTypes);
                }
            }
        }
    }
    n.setJSType(type);
    return scope;
}
Also used : ObjectType(com.google.javascript.rhino.jstype.ObjectType) JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) FunctionType(com.google.javascript.rhino.jstype.FunctionType) TemplateType(com.google.javascript.rhino.jstype.TemplateType)

Example 9 with JSType

use of com.google.javascript.rhino.jstype.JSType in project closure-compiler by google.

the class TypeInference method traverseSuper.

private void traverseSuper(Node superNode) {
    // We only need to handle cases of super() constructor calls for now.
    // All super.method() uses are transpiled away before this pass.
    JSType jsType = functionScope.getRootNode().getJSType();
    FunctionType constructorType = (jsType == null) ? null : jsType.toMaybeFunctionType();
    FunctionType superConstructorType = (constructorType == null) ? null : constructorType.getSuperClassConstructor();
    if (superConstructorType != null) {
        // Treat super() like a function with the same signature as the
        // superclass constructor, but don't require 'new' or 'this'.
        superNode.setJSType(new FunctionBuilder(registry).copyFromOtherFunction(superConstructorType).setIsConstructor(false).withIsAbstract(// 
        false).withTypeOfThis(null).build());
    } else {
        superNode.setJSType(unknownType);
    }
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) FunctionBuilder(com.google.javascript.rhino.jstype.FunctionBuilder) FunctionType(com.google.javascript.rhino.jstype.FunctionType)

Example 10 with JSType

use of com.google.javascript.rhino.jstype.JSType in project closure-compiler by google.

the class TypeInference method traverseCatch.

/**
 * Any value can be thrown, so it's really impossible to determine the type
 * of a CATCH param. Treat it as the UNKNOWN type.
 */
private FlowScope traverseCatch(Node catchNode, FlowScope scope) {
    Node name = catchNode.getFirstChild();
    JSType type;
    // If the catch expression name was declared in the catch use that type,
    // otherwise use "unknown".
    JSDocInfo info = name.getJSDocInfo();
    if (info != null && info.hasType()) {
        type = info.getType().evaluate(currentScope, registry);
    } else {
        type = getNativeType(JSTypeNative.UNKNOWN_TYPE);
    }
    redeclareSimpleVar(scope, name, type);
    name.setJSType(type);
    return scope;
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) Node(com.google.javascript.rhino.Node) JSDocInfo(com.google.javascript.rhino.JSDocInfo)

Aggregations

JSType (com.google.javascript.rhino.jstype.JSType)189 Node (com.google.javascript.rhino.Node)60 FunctionType (com.google.javascript.rhino.jstype.FunctionType)38 ObjectType (com.google.javascript.rhino.jstype.ObjectType)37 JSDocInfo (com.google.javascript.rhino.JSDocInfo)9 FlowScope (com.google.javascript.jscomp.type.FlowScope)7 TemplateType (com.google.javascript.rhino.jstype.TemplateType)6 TemplateTypeMap (com.google.javascript.rhino.jstype.TemplateTypeMap)5 UnionType (com.google.javascript.rhino.jstype.UnionType)4 ArrayList (java.util.ArrayList)4 EnumType (com.google.javascript.rhino.jstype.EnumType)3 JSTypeRegistry (com.google.javascript.rhino.jstype.JSTypeRegistry)3 TemplateTypeMapReplacer (com.google.javascript.rhino.jstype.TemplateTypeMapReplacer)3 ImmutableMap (com.google.common.collect.ImmutableMap)2 Branch (com.google.javascript.jscomp.ControlFlowGraph.Branch)2 Scope (com.google.javascript.jscomp.Scope)2 Token (com.google.javascript.rhino.Token)2 FunctionBuilder (com.google.javascript.rhino.jstype.FunctionBuilder)2 TemplatizedType (com.google.javascript.rhino.jstype.TemplatizedType)2 HashMap (java.util.HashMap)2