Search in sources :

Example 81 with JSType

use of com.google.javascript.jscomp.newtypes.JSType in project closure-compiler by google.

the class NewTypeInference method analyzeNameFwd.

private EnvTypePair analyzeNameFwd(Node expr, TypeEnv inEnv, JSType requiredType, JSType specializedType) {
    String varName = expr.getString();
    if (varName.equals("undefined")) {
        return new EnvTypePair(inEnv, UNDEFINED);
    }
    JSType inferredType = envGetType(inEnv, varName);
    if (inferredType == null) {
        println("Found global variable ", varName);
        // For now, we don't warn for global variables
        return new EnvTypePair(inEnv, UNKNOWN);
    }
    println(varName, "'s inferredType: ", inferredType, " requiredType:  ", requiredType, " specializedType:  ", specializedType);
    if (!inferredType.isSubtypeOf(requiredType)) {
        // The inferred type of a variable is always an upper bound, but
        // sometimes it's also a lower bound, eg, if x was the lhs of an =
        // where we know the type of the rhs.
        // We don't track whether the inferred type is a lower bound, so we
        // conservatively assume that it always is.
        // This is why we warn when !inferredType.isSubtypeOf(requiredType).
        // In some rare cases, the inferred type is only an upper bound,
        // and we would falsely warn.
        // (These usually include the polymorphic operators += and <.)
        // We have a heuristic check to avoid the spurious warnings,
        // but we also miss some true warnings.
        JSType declType = this.currentScope.getDeclaredTypeOf(varName);
        if (tightenNameTypeAndDontWarn(varName, expr, declType, inferredType, requiredType)) {
            inferredType = inferredType.specialize(requiredType);
        } else {
            // the mismatch
            return new EnvTypePair(inEnv, inferredType);
        }
    }
    // If preciseType is bottom, there is a condition that can't be true,
    // but that's not necessarily a type error.
    JSType preciseType = inferredType.specialize(specializedType);
    if (preciseType.isBottom()) {
        preciseType = pickFallbackTypeAfterBottom(varName, inferredType, specializedType);
    }
    println(varName, "'s preciseType: ", preciseType);
    if ((this.currentScope.isUndeclaredFormal(varName) || this.currentScope.isUndeclaredOuterVar(varName)) && preciseType.hasNonScalar()) {
        // In the bwd direction, we may infer a loose type and then join w/
        // top and forget it. That's why we also loosen types going fwd.
        preciseType = preciseType.withLoose();
    }
    return EnvTypePair.addBinding(inEnv, varName, preciseType);
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType)

Example 82 with JSType

use of com.google.javascript.jscomp.newtypes.JSType in project closure-compiler by google.

the class NewTypeInference method analyzeAssignFwd.

private EnvTypePair analyzeAssignFwd(Node expr, TypeEnv inEnv, JSType requiredType, JSType specializedType) {
    if (expr.getBooleanProp(Node.ANALYZED_DURING_GTI)) {
        expr.removeProp(Node.ANALYZED_DURING_GTI);
        Node rhs = expr.getLastChild();
        if (!rhs.isQualifiedName()) {
            analyzeExprFwdIgnoreResult(rhs, inEnv);
        }
        // definitions, not just ones defining typedefs.
        if (!NodeUtil.isAliasedConstDefinition(expr.getFirstChild())) {
            markAndGetTypeOfPreanalyzedNode(expr.getFirstChild(), inEnv, true);
            markAndGetTypeOfPreanalyzedNode(rhs, inEnv, true);
        }
        return new EnvTypePair(inEnv, requiredType);
    }
    mayWarnAboutConst(expr);
    Node lhs = expr.getFirstChild();
    Node rhs = expr.getLastChild();
    if (lhs.getBooleanProp(Node.ANALYZED_DURING_GTI)) {
        lhs.removeProp(Node.ANALYZED_DURING_GTI);
        JSType declType = markAndGetTypeOfPreanalyzedNode(lhs, inEnv, true);
        if (rhs.matchesQualifiedName(ABSTRACT_METHOD_NAME) || (GlobalTypeInfoCollector.isCtorDefinedByCall(lhs) && !isFunctionBind(rhs.getFirstChild(), inEnv, true))) {
            return new EnvTypePair(inEnv, requiredType);
        }
        EnvTypePair rhsPair = analyzeExprFwd(rhs, inEnv, declType);
        if (rhsPair.type.isSubtypeOf(declType)) {
            registerImplicitUses(expr, rhsPair.type, declType);
        } else if (!NodeUtil.isPrototypeAssignment(lhs)) {
            registerMismatchAndWarn(JSError.make(expr, MISTYPED_ASSIGN_RHS, errorMsgWithTypeDiff(declType, rhsPair.type)), rhsPair.type, declType);
        }
        return rhsPair;
    }
    LValueResultFwd lvalue = analyzeLValueFwd(lhs, inEnv, requiredType);
    JSType declType = lvalue.declType;
    EnvTypePair rhsPair = analyzeExprFwd(rhs, lvalue.env, requiredType, specializedType);
    if (declType == null) {
        if (!isGlobalVariable(lhs, inEnv)) {
            rhsPair.env = updateLvalueTypeInEnv(rhsPair.env, lhs, lvalue.ptr, rhsPair.type);
        }
    } else if (rhsPair.type.isSubtypeOf(declType)) {
        registerImplicitUses(expr, rhsPair.type, declType);
        rhsPair.env = updateLvalueTypeInEnv(rhsPair.env, lhs, lvalue.ptr, rhsPair.type);
    } else {
        registerMismatchAndWarn(JSError.make(expr, MISTYPED_ASSIGN_RHS, errorMsgWithTypeDiff(declType, rhsPair.type)), rhsPair.type, declType);
    }
    return rhsPair;
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode)

Example 83 with JSType

use of com.google.javascript.jscomp.newtypes.JSType in project closure-compiler by google.

the class NewTypeInference method analyzeInvocationBwd.

private EnvTypePair analyzeInvocationBwd(Node expr, TypeEnv outEnv, JSType requiredType) {
    checkArgument(expr.isNew() || expr.isCall() || expr.isTaggedTemplateLit());
    Node callee = expr.getFirstChild();
    EnvTypePair pair = analyzeExprBwd(callee, outEnv, commonTypes.topFunction());
    TypeEnv envAfterCallee = pair.env;
    FunctionType funType = pair.type.getFunType();
    if (funType == null) {
        return analyzeInvocationArgumentsBwd(expr, expr.getFirstChild(), envAfterCallee);
    } else if (funType.isLoose()) {
        return analyzeLooseCallNodeBwd(expr, envAfterCallee, requiredType);
    } else if ((expr.isCall() && funType.isSomeConstructorOrInterface()) || (expr.isNew() && !funType.isSomeConstructorOrInterface())) {
        return analyzeInvocationArgumentsBwd(expr, expr.getFirstChild(), envAfterCallee);
    } else if (funType.isTopFunction()) {
        return analyzeInvocationArgumentsBwd(expr, expr.getFirstChild(), envAfterCallee);
    }
    if (callee.isName() && !funType.isGeneric() && (expr.isCall() || expr.isTaggedTemplateLit())) {
        createDeferredCheckBwd(expr, requiredType);
    }
    int numArgs = NodeUtil.getInvocationArgsCount(expr);
    if (numArgs < funType.getMinArity() || numArgs > funType.getMaxArity()) {
        if (expr.isTaggedTemplateLit()) {
            return analyzeInvocationArgumentsBwd(expr.getLastChild(), null, envAfterCallee);
        } else {
            return analyzeInvocationArgumentsBwd(expr, expr.getFirstChild(), envAfterCallee);
        }
    }
    if (funType.isGeneric()) {
        Map<String, JSType> typeMap = calcTypeInstantiationBwd(expr, funType, envAfterCallee);
        funType = funType.instantiateGenerics(typeMap);
    }
    TypeEnv tmpEnv = envAfterCallee;
    // In bwd direction, analyze arguments in reverse
    Node target = expr.isTaggedTemplateLit() ? null : expr.getFirstChild();
    Node start = expr.isTaggedTemplateLit() ? expr.getLastChild().getLastChild() : expr.getLastChild();
    int i = numArgs;
    for (Node arg = start; arg != target; arg = arg.getPrevious()) {
        if (expr.isTaggedTemplateLit() && !arg.isTemplateLitSub()) {
            // with the formal types of the tag function, i needs to stay unchanged here.
            continue;
        }
        i--;
        JSType formalType = funType.getFormalType(i);
        // The type of a formal can be BOTTOM as the result of a join.
        // Don't use this as a requiredType.
        formalType = firstNonBottom(formalType, UNKNOWN);
        tmpEnv = analyzeExprBwd(arg, tmpEnv, formalType).env;
    // We don't need deferred checks for args in BWD
    }
    JSType retType = expr.isNew() ? funType.getThisType() : funType.getReturnType();
    return new EnvTypePair(tmpEnv, retType);
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) FunctionType(com.google.javascript.jscomp.newtypes.FunctionType) DeclaredFunctionType(com.google.javascript.jscomp.newtypes.DeclaredFunctionType) TypeEnv(com.google.javascript.jscomp.newtypes.TypeEnv)

Example 84 with JSType

use of com.google.javascript.jscomp.newtypes.JSType in project closure-compiler by google.

the class NewTypeInference method analyzeAddFwd.

private EnvTypePair analyzeAddFwd(Node expr, TypeEnv inEnv, JSType requiredType) {
    Node lhs = expr.getFirstChild();
    Node rhs = expr.getLastChild();
    JSType operandType = requiredType.isNumber() ? NUMBER : UNKNOWN;
    EnvTypePair lhsPair = analyzeExprFwd(lhs, inEnv, operandType);
    EnvTypePair rhsPair = analyzeExprFwd(rhs, lhsPair.env, operandType);
    JSType lhsType = lhsPair.type;
    JSType rhsType = rhsPair.type;
    if (lhsType.isString() || rhsType.isString()) {
        // Return early and don't warn, since '' + expr is used for type coercions
        rhsPair.type = STRING;
        return rhsPair;
    }
    if (!commonTypes.isNumStrScalarOrObj(lhsType)) {
        warnInvalidOperand(lhs, expr.getToken(), NUMBER_OR_STRING, lhsType);
    }
    if (!commonTypes.isNumStrScalarOrObj(rhsType)) {
        warnInvalidOperand(rhs, expr.getToken(), NUMBER_OR_STRING, rhsType);
    }
    return new EnvTypePair(rhsPair.env, JSType.plus(lhsType, rhsType));
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode)

Example 85 with JSType

use of com.google.javascript.jscomp.newtypes.JSType in project closure-compiler by google.

the class NewTypeInference method mayWarnAboutNullableReferenceAndTighten.

private EnvTypePair mayWarnAboutNullableReferenceAndTighten(Node obj, JSType recvType, JSType maybeSpecType, TypeEnv inEnv) {
    if (!recvType.isUnknown() && !recvType.isTop() && (NULL.isSubtypeOf(recvType) || UNDEFINED.isSubtypeOf(recvType))) {
        JSType minusNull = recvType.removeType(NULL_OR_UNDEFINED);
        if (!minusNull.isBottom()) {
            if (this.reportNullDeref) {
                warnings.add(JSError.make(obj, NULLABLE_DEREFERENCE, recvType.toString()));
            }
            TypeEnv outEnv = inEnv;
            if (obj.isQualifiedName()) {
                QualifiedName qname = QualifiedName.fromNode(obj);
                if (maybeSpecType != null && maybeSpecType.isSubtypeOf(minusNull)) {
                    minusNull = maybeSpecType;
                }
                outEnv = updateLvalueTypeInEnv(inEnv, obj, qname, minusNull);
            }
            return new EnvTypePair(outEnv, minusNull);
        }
    }
    return new EnvTypePair(inEnv, recvType);
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) QualifiedName(com.google.javascript.jscomp.newtypes.QualifiedName) TypeEnv(com.google.javascript.jscomp.newtypes.TypeEnv)

Aggregations

JSType (com.google.javascript.jscomp.newtypes.JSType)86 Node (com.google.javascript.rhino.Node)60 DiGraphNode (com.google.javascript.jscomp.graph.DiGraph.DiGraphNode)54 TypeEnv (com.google.javascript.jscomp.newtypes.TypeEnv)28 DeclaredFunctionType (com.google.javascript.jscomp.newtypes.DeclaredFunctionType)20 QualifiedName (com.google.javascript.jscomp.newtypes.QualifiedName)18 FunctionType (com.google.javascript.jscomp.newtypes.FunctionType)16 Declaration (com.google.javascript.jscomp.newtypes.Declaration)5 FunctionTypeBuilder (com.google.javascript.jscomp.newtypes.FunctionTypeBuilder)5 FunctionNamespace (com.google.javascript.jscomp.newtypes.FunctionNamespace)4 Namespace (com.google.javascript.jscomp.newtypes.Namespace)4 ArrayList (java.util.ArrayList)4 ImmutableMap (com.google.common.collect.ImmutableMap)3 TypeI (com.google.javascript.rhino.TypeI)3 LinkedHashMap (java.util.LinkedHashMap)3 Map (java.util.Map)3 NamespaceLit (com.google.javascript.jscomp.newtypes.NamespaceLit)2 NominalType (com.google.javascript.jscomp.newtypes.NominalType)2 RawNominalType (com.google.javascript.jscomp.newtypes.RawNominalType)2 JSDocInfo (com.google.javascript.rhino.JSDocInfo)2