Search in sources :

Example 6 with TypeEnv

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

the class NewTypeInference method analyzeEnumObjLitFwd.

private EnvTypePair analyzeEnumObjLitFwd(Node objLit, TypeEnv inEnv, JSType requiredType) {
    // so we ignore them here.
    if (objLit.getFirstChild() == null) {
        return new EnvTypePair(inEnv, requiredType);
    }
    String pname = NodeUtil.getObjectLitKeyName(objLit.getFirstChild());
    JSType enumeratedType = requiredType.getProp(new QualifiedName(pname)).getEnumeratedTypeOfEnumElement();
    if (enumeratedType == null) {
        // enumeratedType is null only if there is some other type error
        return new EnvTypePair(inEnv, requiredType);
    }
    TypeEnv env = inEnv;
    for (Node prop : objLit.children()) {
        EnvTypePair pair = analyzeExprFwd(prop, env, enumeratedType);
        if (!pair.type.isSubtypeOf(enumeratedType)) {
            warnings.add(JSError.make(prop, INVALID_OBJLIT_PROPERTY_TYPE, errorMsgWithTypeDiff(enumeratedType, pair.type)));
        }
        env = pair.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 7 with TypeEnv

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

the class NewTypeInference method analyzeFunctionBwd.

private void analyzeFunctionBwd(NTIWorkset workset) {
    for (DiGraphNode<Node, ControlFlowGraph.Branch> dn : workset.backward()) {
        Node n = dn.getValue();
        TypeEnv outEnv = checkNotNull(getOutEnv(dn));
        TypeEnv inEnv;
        println("\tBWD Statment: ", n);
        println("\t\toutEnv: ", outEnv);
        switch(n.getToken()) {
            case EXPR_RESULT:
                inEnv = analyzeExprBwd(n.getFirstChild(), outEnv, UNKNOWN).env;
                break;
            case RETURN:
                {
                    Node retExp = n.getFirstChild();
                    if (retExp == null) {
                        inEnv = outEnv;
                    } else {
                        JSType declRetType = this.currentScope.getDeclaredTypeForOwnBody().getReturnType();
                        declRetType = firstNonNull(declRetType, UNKNOWN);
                        inEnv = analyzeExprBwd(retExp, outEnv, declRetType).env;
                    }
                    break;
                }
            case VAR:
                {
                    if (NodeUtil.isTypedefDecl(n)) {
                        inEnv = outEnv;
                        break;
                    }
                    inEnv = outEnv;
                    for (Node nameNode = n.getFirstChild(); nameNode != null; nameNode = nameNode.getNext()) {
                        String varName = nameNode.getString();
                        Node rhs = nameNode.getFirstChild();
                        JSType declType = this.currentScope.getDeclaredTypeOf(varName);
                        inEnv = envPutType(inEnv, varName, UNKNOWN);
                        if (rhs == null || this.currentScope.isLocalFunDef(varName)) {
                            continue;
                        }
                        JSType inferredType = envGetType(outEnv, varName);
                        JSType requiredType;
                        if (declType == null) {
                            requiredType = inferredType;
                        } else {
                            // TODO(dimvar): look if the meet is needed
                            requiredType = JSType.meet(declType, inferredType);
                            requiredType = firstNonBottom(requiredType, UNKNOWN);
                        }
                        inEnv = analyzeExprBwd(rhs, inEnv, requiredType).env;
                    }
                    break;
                }
            case BLOCK:
            case ROOT:
            case BREAK:
            case CATCH:
            case CONTINUE:
            case DEFAULT_CASE:
            case DEBUGGER:
            case EMPTY:
            case SCRIPT:
            case TRY:
            case WITH:
                inEnv = outEnv;
                break;
            case DO:
            case FOR:
            case FOR_IN:
            case FOR_OF:
            case IF:
            case WHILE:
                Node expr = (n.isForIn() || n.isForOf()) ? n.getFirstChild() : NodeUtil.getConditionExpression(n);
                inEnv = analyzeExprBwd(expr, outEnv).env;
                break;
            case THROW:
            case CASE:
            case SWITCH:
                inEnv = analyzeExprBwd(n.getFirstChild(), outEnv).env;
                break;
            default:
                if (NodeUtil.isStatement(n)) {
                    throw new RuntimeException("Unhandled statement type: " + n.getToken());
                } else {
                    inEnv = analyzeExprBwd(n, outEnv).env;
                    break;
                }
        }
        println("\t\tinEnv: ", inEnv);
        for (DiGraphEdge<Node, ControlFlowGraph.Branch> de : dn.getInEdges()) {
            envs.put(de, inEnv);
        }
    }
}
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 8 with TypeEnv

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

the class NewTypeInference method analyzeExprBwd.

/**
 * For now, we won't emit any warnings bwd.
 */
private EnvTypePair analyzeExprBwd(Node expr, TypeEnv outEnv, JSType requiredType) {
    Preconditions.checkArgument(requiredType != null, "Required type null at: %s", expr);
    checkArgument(!requiredType.isBottom());
    switch(expr.getToken()) {
        case // can be created by a FOR with empty condition
        EMPTY:
            return new EnvTypePair(outEnv, UNKNOWN);
        case FUNCTION:
            {
                String fnName = symbolTable.getFunInternalName(expr);
                return new EnvTypePair(outEnv, envGetType(outEnv, fnName));
            }
        case FALSE:
        case NULL:
        case NUMBER:
        case STRING:
        case TRUE:
            return new EnvTypePair(outEnv, scalarValueToType(expr.getToken()));
        case OBJECTLIT:
            return analyzeObjLitBwd(expr, outEnv, requiredType);
        case THIS:
            {
                // TODO(blickly): Infer a loose type for THIS if we're in a function.
                if (!this.currentScope.hasThis()) {
                    return new EnvTypePair(outEnv, UNKNOWN);
                }
                JSType thisType = this.currentScope.getDeclaredTypeOf(THIS_ID);
                return new EnvTypePair(outEnv, thisType);
            }
        case SUPER:
            // us anything useful at the moment.
            return new EnvTypePair(outEnv, UNKNOWN);
        case NAME:
            return analyzeNameBwd(expr, outEnv, requiredType);
        case INC:
        case DEC:
        case BITNOT:
        case // Unary operations on numbers
        NEG:
            return analyzeExprBwd(expr.getFirstChild(), outEnv, NUMBER);
        case POS:
            {
                EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
                pair.type = NUMBER;
                return pair;
            }
        case TYPEOF:
            {
                EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
                pair.type = STRING;
                return pair;
            }
        case INSTANCEOF:
            {
                TypeEnv env = analyzeExprBwd(expr.getLastChild(), outEnv, commonTypes.topFunction()).env;
                EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), env);
                pair.type = BOOLEAN;
                return pair;
            }
        case BITOR:
        case BITAND:
        case BITXOR:
        case DIV:
        case EXPONENT:
        case LSH:
        case MOD:
        case MUL:
        case RSH:
        case SUB:
        case URSH:
            return analyzeBinaryNumericOpBwd(expr, outEnv);
        case ADD:
            return analyzeAddBwd(expr, outEnv, requiredType);
        case OR:
        case AND:
            return analyzeLogicalOpBwd(expr, outEnv);
        case SHEQ:
        case SHNE:
        case EQ:
        case NE:
            return analyzeEqNeBwd(expr, outEnv);
        case LT:
        case GT:
        case LE:
        case GE:
            return analyzeLtGtBwd(expr, outEnv);
        case ASSIGN:
            return analyzeAssignBwd(expr, outEnv, requiredType);
        case ASSIGN_ADD:
            return analyzeAssignAddBwd(expr, outEnv, requiredType);
        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:
            return analyzeAssignNumericOpBwd(expr, outEnv);
        case GETPROP:
            {
                checkState(!NodeUtil.isAssignmentOp(expr.getParent()) || !NodeUtil.isLValue(expr));
                if (expr.getBooleanProp(Node.ANALYZED_DURING_GTI)) {
                    return new EnvTypePair(outEnv, requiredType);
                }
                return analyzePropAccessBwd(expr.getFirstChild(), expr.getLastChild().getString(), outEnv, requiredType);
            }
        case HOOK:
            return analyzeHookBwd(expr, outEnv, requiredType);
        case CALL:
        case NEW:
        case TAGGED_TEMPLATELIT:
            return analyzeInvocationBwd(expr, outEnv, requiredType);
        case COMMA:
            {
                EnvTypePair pair = analyzeExprBwd(expr.getLastChild(), outEnv, requiredType);
                pair.env = analyzeExprBwd(expr.getFirstChild(), pair.env).env;
                return pair;
            }
        case NOT:
            {
                EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
                pair.type = pair.type.negate();
                return pair;
            }
        case GETELEM:
            return analyzeGetElemBwd(expr, outEnv, requiredType);
        case VOID:
            {
                EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
                pair.type = UNDEFINED;
                return pair;
            }
        case IN:
            return analyzeInBwd(expr, outEnv);
        case DELPROP:
            {
                EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
                pair.type = BOOLEAN;
                return pair;
            }
        case VAR:
            {
                // Can happen iff its parent is a for/in or for/of.
                Node vdecl = expr.getFirstChild();
                String name = vdecl.getString();
                // For/in and for/of can never have rhs of its VAR
                checkState(!vdecl.hasChildren());
                return new EnvTypePair(envPutType(outEnv, name, UNKNOWN), UNKNOWN);
            }
        case REGEXP:
            return new EnvTypePair(outEnv, commonTypes.getRegexpType());
        case ARRAYLIT:
            return analyzeArrayLitBwd(expr, outEnv);
        case CAST:
            {
                EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
                pair.type = (JSType) expr.getTypeI();
                return pair;
            }
        case TEMPLATELIT:
            return analyzeTemplateLitBwd(expr, outEnv);
        case TEMPLATELIT_SUB:
            return analyzeExprBwd(expr.getFirstChild(), outEnv, requiredType);
        case STRING_KEY:
            if (expr.hasChildren()) {
                return analyzeExprBwd(expr.getFirstChild(), outEnv, requiredType);
            } else {
                return analyzeNameBwd(expr, outEnv, requiredType);
            }
        case MEMBER_FUNCTION_DEF:
            return analyzeExprBwd(expr.getFirstChild(), outEnv, requiredType);
        case COMPUTED_PROP:
            TypeEnv env = analyzeExprBwd(expr.getSecondChild(), outEnv).env;
            return analyzeExprBwd(expr.getFirstChild(), env);
        case YIELD:
            {
                if (expr.hasChildren()) {
                    EnvTypePair pair = analyzeExprBwd(expr.getFirstChild(), outEnv);
                    pair.type = UNKNOWN;
                    return pair;
                } else {
                    return new EnvTypePair(outEnv, UNKNOWN);
                }
            }
        default:
            throw new RuntimeException("BWD: Unhandled expression type: " + expr.getToken() + " with parent: " + expr.getParent());
    }
}
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 9 with TypeEnv

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

the class NewTypeInference method analyzeHookFwd.

private EnvTypePair analyzeHookFwd(Node expr, TypeEnv inEnv, JSType requiredType, JSType specializedType) {
    Node cond = expr.getFirstChild();
    Node thenBranch = cond.getNext();
    Node elseBranch = thenBranch.getNext();
    TypeEnv trueEnv = analyzeExprFwd(cond, inEnv, UNKNOWN, TRUTHY).env;
    TypeEnv falseEnv = analyzeExprFwd(cond, inEnv, UNKNOWN, FALSY).env;
    EnvTypePair thenPair = analyzeExprFwd(thenBranch, trueEnv, requiredType, specializedType);
    EnvTypePair elsePair = analyzeExprFwd(elseBranch, falseEnv, requiredType, specializedType);
    return EnvTypePair.join(thenPair, elsePair);
}
Also used : Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) TypeEnv(com.google.javascript.jscomp.newtypes.TypeEnv)

Example 10 with TypeEnv

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

the class NewTypeInference method analyzeStrictComparisonFwd.

private EnvTypePair analyzeStrictComparisonFwd(Token comparisonOp, Node lhs, Node rhs, TypeEnv inEnv, JSType specializedType) {
    if (specializedType.isTrueOrTruthy() || specializedType.isFalseOrFalsy()) {
        if (lhs.isTypeOf()) {
            return analyzeSpecializedTypeof(lhs, rhs, comparisonOp, inEnv, specializedType);
        } else if (rhs.isTypeOf()) {
            return analyzeSpecializedTypeof(rhs, lhs, comparisonOp, inEnv, specializedType);
        } else if (isGoogTypeof(lhs)) {
            return analyzeGoogTypeof(lhs, rhs, inEnv, specializedType);
        } else if (isGoogTypeof(rhs)) {
            return analyzeGoogTypeof(rhs, lhs, inEnv, specializedType);
        }
    }
    EnvTypePair lhsPair = analyzeExprFwd(lhs, inEnv);
    EnvTypePair rhsPair = analyzeExprFwd(rhs, lhsPair.env);
    JSType rhstype = rhsPair.type;
    JSType lhstype = lhsPair.type;
    if (!rhstype.isNullOrUndef()) {
        if (JSType.haveCommonSubtype(lhstype, rhstype)) {
            registerImplicitUses(lhs, lhstype, rhstype);
        } else {
            JSError error = JSError.make(lhs, INCOMPATIBLE_STRICT_COMPARISON, lhstype.toString(), rhstype.toString());
            registerMismatchAndWarn(error, lhstype, rhstype);
        }
    }
    // This env may contain types that have been tightened after nullable deref.
    TypeEnv preciseEnv = rhsPair.env;
    if ((comparisonOp == Token.SHEQ && specializedType.isTrueOrTruthy()) || (comparisonOp == Token.SHNE && specializedType.isFalseOrFalsy())) {
        lhsPair = analyzeExprFwd(lhs, preciseEnv, UNKNOWN, lhsPair.type.specialize(rhsPair.type));
        rhsPair = analyzeExprFwd(rhs, lhsPair.env, UNKNOWN, rhsPair.type.specialize(lhsPair.type));
    } else if ((comparisonOp == Token.SHEQ && specializedType.isFalseOrFalsy()) || (comparisonOp == Token.SHNE && specializedType.isTrueOrTruthy())) {
        JSType lhsType = lhsPair.type;
        JSType rhsType = rhsPair.type;
        if (lhsType.isNullOrUndef()) {
            rhsType = rhsType.removeType(lhsType);
        } else if (rhsType.isNullOrUndef()) {
            lhsType = lhsType.removeType(rhsType);
        }
        lhsPair = analyzeExprFwd(lhs, preciseEnv, UNKNOWN, lhsType);
        rhsPair = analyzeExprFwd(rhs, lhsPair.env, UNKNOWN, rhsType);
    }
    rhsPair.type = BOOLEAN;
    return rhsPair;
}
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