Search in sources :

Example 1 with TypeEnv

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

the class NewTypeInference method analyzeReturnFwd.

private TypeEnv analyzeReturnFwd(Node n, TypeEnv inEnv) {
    if (this.currentScope.getRoot().isGeneratorFunction()) {
        JSType declRetType = getDeclaredReturnTypeOfCurrentScope(this.commonTypes.getGeneratorInstance(UNKNOWN));
        if (n.hasChildren()) {
            EnvTypePair retPair = analyzeExprFwd(n.getFirstChild(), inEnv, UNKNOWN);
            return envPutType(retPair.env, RETVAL_ID, declRetType);
        }
        return envPutType(inEnv, RETVAL_ID, declRetType);
    }
    TypeEnv outEnv;
    JSType declRetType = getDeclaredReturnTypeOfCurrentScope(UNKNOWN);
    JSType actualRetType;
    Node retExp = n.getFirstChild();
    if (retExp == null) {
        actualRetType = UNDEFINED;
        outEnv = envPutType(inEnv, RETVAL_ID, actualRetType);
    } else {
        EnvTypePair retPair = analyzeExprFwd(retExp, inEnv, declRetType);
        actualRetType = retPair.type;
        outEnv = envPutType(retPair.env, RETVAL_ID, actualRetType);
    }
    if (!actualRetType.isSubtypeOf(declRetType)) {
        registerMismatchAndWarn(JSError.make(n, RETURN_NONDECLARED_TYPE, errorMsgWithTypeDiff(declRetType, actualRetType)), actualRetType, declRetType);
    }
    return outEnv;
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) TypeEnv(com.google.javascript.jscomp.newtypes.TypeEnv)

Example 2 with TypeEnv

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

the class NewTypeInference method analyzeEnumObjLitBwd.

private EnvTypePair analyzeEnumObjLitBwd(Node objLit, TypeEnv outEnv, JSType requiredType) {
    if (objLit.getFirstChild() == null) {
        return new EnvTypePair(outEnv, requiredType);
    }
    String pname = NodeUtil.getObjectLitKeyName(objLit.getFirstChild());
    JSType enumeratedType = requiredType.getProp(new QualifiedName(pname)).getEnumeratedTypeOfEnumElement();
    if (enumeratedType == null) {
        return new EnvTypePair(outEnv, requiredType);
    }
    TypeEnv env = outEnv;
    for (Node prop = objLit.getLastChild(); prop != null; prop = prop.getPrevious()) {
        env = analyzeExprBwd(prop, env, enumeratedType).env;
    }
    return new EnvTypePair(env, requiredType);
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) QualifiedName(com.google.javascript.jscomp.newtypes.QualifiedName) Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) TypeEnv(com.google.javascript.jscomp.newtypes.TypeEnv)

Example 3 with TypeEnv

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

the class NewTypeInference method analyzeForInFwd.

private TypeEnv analyzeForInFwd(Node n, TypeEnv inEnv) {
    Node obj = n.getSecondChild();
    EnvTypePair pair = analyzeExprFwd(obj, inEnv, pickReqObjType(n));
    pair = mayWarnAboutNullableReferenceAndTighten(n, pair.type, null, inEnv);
    JSType objType = pair.type;
    if (!objType.isSubtypeOf(TOP_OBJECT)) {
        warnings.add(JSError.make(obj, FORIN_EXPECTS_OBJECT, objType.toString()));
    } else if (objType.isStruct()) {
        warnings.add(JSError.make(obj, IN_USED_WITH_STRUCT));
    }
    Node lhs = n.getFirstChild();
    LValueResultFwd lval = analyzeLValueFwd(lhs, inEnv, STRING);
    TypeEnv outEnv;
    if (lval.declType != null && !commonTypes.isStringScalarOrObj(lval.declType)) {
        warnings.add(JSError.make(lhs, FORIN_EXPECTS_STRING_KEY, lval.declType.toString()));
        outEnv = lval.env;
    } else {
        outEnv = updateLvalueTypeInEnv(lval.env, lhs, lval.ptr, STRING);
    }
    return outEnv;
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) TypeEnv(com.google.javascript.jscomp.newtypes.TypeEnv)

Example 4 with TypeEnv

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

the class NewTypeInference method analyzeArrayLitFwd.

private EnvTypePair analyzeArrayLitFwd(Node expr, TypeEnv inEnv) {
    TypeEnv env = inEnv;
    JSType elementType = BOTTOM;
    for (Node arrayElm = expr.getFirstChild(); arrayElm != null; arrayElm = arrayElm.getNext()) {
        EnvTypePair pair = analyzeExprFwd(arrayElm, env);
        env = pair.env;
        elementType = JSType.join(elementType, pair.type);
    }
    elementType = firstNonBottom(elementType, UNKNOWN);
    return new EnvTypePair(env, commonTypes.getArrayInstance(elementType));
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) TypeEnv(com.google.javascript.jscomp.newtypes.TypeEnv)

Example 5 with TypeEnv

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

the class NewTypeInference method analyzeExprFwd.

/**
 * @param requiredType The context requires this type; warn if the expression
 *                     doesn't have this type.
 * @param specializedType Used in boolean contexts to infer types of names.
 *
 * Invariant: specializedType is a subtype of requiredType.
 */
private EnvTypePair analyzeExprFwd(Node expr, TypeEnv inEnv, JSType requiredType, JSType specializedType) {
    checkArgument(requiredType != null && !requiredType.isBottom());
    EnvTypePair resultPair = null;
    switch(expr.getToken()) {
        case // can be created by a FOR with empty condition
        EMPTY:
            resultPair = new EnvTypePair(inEnv, UNKNOWN);
            break;
        case FUNCTION:
            {
                String fnName = symbolTable.getFunInternalName(expr);
                JSType fnType = envGetType(inEnv, fnName);
                Preconditions.checkState(fnType != null, "Could not find type for %s", fnName);
                TypeEnv outEnv = collectTypesForEscapedVarsFwd(expr, inEnv);
                resultPair = new EnvTypePair(outEnv, fnType);
                break;
            }
        case FALSE:
        case NULL:
        case NUMBER:
        case STRING:
        case TRUE:
            resultPair = new EnvTypePair(inEnv, scalarValueToType(expr.getToken()));
            break;
        case OBJECTLIT:
            resultPair = analyzeObjLitFwd(expr, inEnv, requiredType, specializedType);
            break;
        case THIS:
            {
                resultPair = analyzeThisFwd(expr, inEnv, requiredType, specializedType);
                break;
            }
        case SUPER:
            {
                resultPair = analyzeSuperFwd(expr, inEnv);
                break;
            }
        case NAME:
            resultPair = analyzeNameFwd(expr, inEnv, requiredType, specializedType);
            break;
        case AND:
        case OR:
            resultPair = analyzeLogicalOpFwd(expr, inEnv, requiredType, specializedType);
            break;
        case INC:
        case DEC:
            resultPair = analyzeIncDecFwd(expr, inEnv, requiredType);
            break;
        case BITNOT:
        case NEG:
            resultPair = analyzeUnaryNumFwd(expr, inEnv);
            break;
        case POS:
            {
                // We are more permissive with +, because it is used to coerce to number
                resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv);
                resultPair.type = NUMBER;
                break;
            }
        case TYPEOF:
            {
                resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv);
                resultPair.type = STRING;
                break;
            }
        case INSTANCEOF:
            resultPair = analyzeInstanceofFwd(expr, inEnv, specializedType);
            break;
        case ADD:
            resultPair = analyzeAddFwd(expr, inEnv, requiredType);
            break;
        case BITOR:
        case BITAND:
        case BITXOR:
        case DIV:
        case EXPONENT:
        case LSH:
        case MOD:
        case MUL:
        case RSH:
        case SUB:
        case URSH:
            resultPair = analyzeBinaryNumericOpFwd(expr, inEnv);
            break;
        case ASSIGN:
            resultPair = analyzeAssignFwd(expr, inEnv, requiredType, specializedType);
            break;
        case ASSIGN_ADD:
            resultPair = analyzeAssignAddFwd(expr, inEnv, requiredType);
            break;
        case ASSIGN_BITOR:
        case ASSIGN_BITXOR:
        case ASSIGN_BITAND:
        case ASSIGN_LSH:
        case ASSIGN_RSH:
        case ASSIGN_URSH:
        case ASSIGN_SUB:
        case ASSIGN_MUL:
        case ASSIGN_DIV:
        case ASSIGN_MOD:
        case ASSIGN_EXPONENT:
            resultPair = analyzeAssignNumericOpFwd(expr, inEnv);
            break;
        case SHEQ:
        case SHNE:
            resultPair = analyzeStrictComparisonFwd(expr.getToken(), expr.getFirstChild(), expr.getLastChild(), inEnv, specializedType);
            break;
        case EQ:
        case NE:
            resultPair = analyzeNonStrictComparisonFwd(expr, inEnv, specializedType);
            break;
        case LT:
        case GT:
        case LE:
        case GE:
            resultPair = analyzeLtGtFwd(expr, inEnv);
            break;
        case GETPROP:
            Preconditions.checkState(!NodeUtil.isAssignmentOp(expr.getParent()) || !NodeUtil.isLValue(expr));
            if (expr.getBooleanProp(Node.ANALYZED_DURING_GTI)) {
                if (expr.isQualifiedName() && !NodeUtil.isTypedefDecl(expr)) {
                    markAndGetTypeOfPreanalyzedNode(expr, inEnv, true);
                }
                expr.removeProp(Node.ANALYZED_DURING_GTI);
                resultPair = new EnvTypePair(inEnv, requiredType);
            } else {
                resultPair = analyzePropAccessFwd(expr.getFirstChild(), expr.getLastChild().getString(), inEnv, requiredType, specializedType);
            }
            break;
        case HOOK:
            resultPair = analyzeHookFwd(expr, inEnv, requiredType, specializedType);
            break;
        case CALL:
        case NEW:
        case TAGGED_TEMPLATELIT:
            resultPair = analyzeInvocationFwd(expr, inEnv, requiredType, specializedType);
            break;
        case COMMA:
            resultPair = analyzeExprFwd(expr.getLastChild(), analyzeExprFwd(expr.getFirstChild(), inEnv).env, requiredType, specializedType);
            break;
        case NOT:
            {
                resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv, UNKNOWN, specializedType.negate());
                resultPair.type = resultPair.type.negate().toBoolean();
                break;
            }
        case GETELEM:
            resultPair = analyzeGetElemFwd(expr, inEnv, requiredType, specializedType);
            break;
        case VOID:
            {
                resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv);
                resultPair.type = UNDEFINED;
                break;
            }
        case IN:
            resultPair = analyzeInFwd(expr, inEnv, specializedType);
            break;
        case DELPROP:
            {
                // IRFactory checks that the operand is a name, getprop or getelem.
                // analyzePropAccessFwd warns if we delete a constant property.
                resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv);
                resultPair.type = BOOLEAN;
                break;
            }
        case REGEXP:
            resultPair = new EnvTypePair(inEnv, commonTypes.getRegexpType());
            break;
        case ARRAYLIT:
            resultPair = analyzeArrayLitFwd(expr, inEnv);
            break;
        case CAST:
            resultPair = analyzeCastFwd(expr, inEnv);
            break;
        case CASE:
            // For a statement of the form: switch (exp1) { ... case exp2: ... }
            // we analyze the case as if it were (exp1 === exp2).
            // We analyze the body of the case when the test is true and the stm
            // following the body when the test is false.
            resultPair = analyzeStrictComparisonFwd(Token.SHEQ, expr.getParent().getFirstChild(), expr.getFirstChild(), inEnv, specializedType);
            break;
        case TEMPLATELIT:
            resultPair = analyzeTemplateLitFwd(expr, inEnv);
            break;
        case TEMPLATELIT_SUB:
            resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv, requiredType);
            break;
        case STRING_KEY:
            if (expr.hasChildren()) {
                resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv, requiredType, specializedType);
            } else {
                resultPair = analyzeNameFwd(expr, inEnv, requiredType, specializedType);
            }
            break;
        case MEMBER_FUNCTION_DEF:
            resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv, requiredType, specializedType);
            break;
        case COMPUTED_PROP:
            resultPair = analyzeExprFwd(expr.getFirstChild(), inEnv, requiredType, specializedType);
            resultPair = analyzeExprFwd(expr.getSecondChild(), resultPair.env, requiredType, specializedType);
            break;
        case YIELD:
            resultPair = analyzeYieldFwd(expr, inEnv);
            break;
        default:
            throw new RuntimeException("Unhandled expression type: " + expr.getToken());
    }
    JSType resultType = resultPair.type;
    mayWarnAboutUnknownType(expr, resultType);
    if (resultType.isUnresolved()) {
        resultPair.type = UNKNOWN;
    }
    maybeSetTypeI(expr, resultType);
    if (this.currentScope.isFunction()) {
        // In global scope, the env is too big and produces too much output
        println("AnalyzeExprFWD: ", expr, " ::reqtype: ", requiredType, " ::spectype: ", specializedType, " ::resulttype: ", resultType);
    }
    return resultPair;
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) TypeEnv(com.google.javascript.jscomp.newtypes.TypeEnv)

Aggregations

TypeEnv (com.google.javascript.jscomp.newtypes.TypeEnv)35 DiGraphNode (com.google.javascript.jscomp.graph.DiGraph.DiGraphNode)30 Node (com.google.javascript.rhino.Node)30 JSType (com.google.javascript.jscomp.newtypes.JSType)28 DeclaredFunctionType (com.google.javascript.jscomp.newtypes.DeclaredFunctionType)9 FunctionType (com.google.javascript.jscomp.newtypes.FunctionType)7 QualifiedName (com.google.javascript.jscomp.newtypes.QualifiedName)7 FunctionTypeBuilder (com.google.javascript.jscomp.newtypes.FunctionTypeBuilder)4 DiGraphEdge (com.google.javascript.jscomp.graph.DiGraph.DiGraphEdge)2 ArrayList (java.util.ArrayList)2 LinkedHashSet (java.util.LinkedHashSet)2 AssertionFunctionSpec (com.google.javascript.jscomp.CodingConvention.AssertionFunctionSpec)1 Bind (com.google.javascript.jscomp.CodingConvention.Bind)1 JSDocInfo (com.google.javascript.rhino.JSDocInfo)1 Token (com.google.javascript.rhino.Token)1