Search in sources :

Example 16 with JSType

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

the class NewTypeInference method analyzePropLValBwd.

private LValueResultBwd analyzePropLValBwd(Node obj, QualifiedName pname, TypeEnv outEnv, JSType type, boolean doSlicing) {
    checkArgument(pname.isIdentifier());
    JSType reqObjType = pickReqObjType(obj.getParent()).withProperty(pname, type);
    LValueResultBwd lvalue = analyzeLValueBwd(obj, outEnv, reqObjType, false, true);
    if (lvalue.ptr != null) {
        lvalue.ptr = QualifiedName.join(lvalue.ptr, pname);
        if (doSlicing) {
            String objName = lvalue.ptr.getLeftmostName();
            QualifiedName props = lvalue.ptr.getAllButLeftmost();
            JSType objType = envGetType(lvalue.env, objName);
            // withoutProperty only removes inferred properties
            JSType slicedObjType = objType.withoutProperty(props);
            lvalue.env = envPutType(lvalue.env, objName, slicedObjType);
        }
    }
    lvalue.type = lvalue.type.mayHaveProp(pname) ? lvalue.type.getProp(pname) : UNKNOWN;
    return lvalue;
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) QualifiedName(com.google.javascript.jscomp.newtypes.QualifiedName)

Example 17 with JSType

use of com.google.javascript.jscomp.newtypes.JSType 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 18 with JSType

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

the class NewTypeInference method checkTaggedFunctionFirstParam.

/**
 * Check that the first argument of a tagged function is a ITemplateArray.
 * If the argument is missing, return Function, to avoid giving two warnings for the same issue.
 */
private FunctionType checkTaggedFunctionFirstParam(Node taggedLit, Node funcName, FunctionType funType) {
    JSType firstArgType = funType.getFormalType(0);
    JSType templateArray = this.commonTypes.getITemplateArrayType();
    if (firstArgType == null) {
        warnings.add(JSError.make(taggedLit, TEMPLATE_ARGUMENT_MISSING));
        return this.commonTypes.qmarkFunction().getFunTypeIfSingletonObj();
    } else if (!templateArray.isSubtypeOf(firstArgType)) {
        JSError error = JSError.make(taggedLit, TEMPLATE_ARGUMENT_MISMATCH, getReadableCalleeName(funcName), errorMsgWithTypeDiff(templateArray, firstArgType));
        registerMismatchAndWarn(error, firstArgType, templateArray);
    }
    return funType;
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType)

Example 19 with JSType

use of com.google.javascript.jscomp.newtypes.JSType 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 20 with JSType

use of com.google.javascript.jscomp.newtypes.JSType 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)

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