Search in sources :

Example 11 with JSType

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

the class SimpleInference method inferPropAccess.

private JSType inferPropAccess(Node recv, String pname, NTIScope scope) {
    if (recv.isGetProp() && recv.getLastChild().getString().equals("prototype")) {
        return inferPrototypeProperty(recv.getFirstChild(), pname, scope);
    }
    QualifiedName propQname = new QualifiedName(pname);
    JSType recvType = null;
    if (recv.isQualifiedName()) {
        QualifiedName recvQname = QualifiedName.fromNode(recv);
        Declaration decl = scope.getDeclaration(recvQname, false);
        if (decl != null) {
            EnumType et = decl.getEnum();
            if (et != null && et.enumLiteralHasKey(pname)) {
                return et.getPropType();
            }
            Namespace ns = decl.getNamespace();
            if (ns != null) {
                return inferDeclaration(ns.getDeclaration(propQname));
            }
            recvType = decl.getTypeOfSimpleDecl();
        }
    }
    if (recvType == null) {
        recvType = inferExprRecur(recv, scope);
    }
    if (recvType == null) {
        return null;
    }
    if (recvType.isScalar()) {
        recvType = recvType.autobox();
    }
    FunctionType ft = recvType.getFunTypeIfSingletonObj();
    if (ft != null && pname.equals("call")) {
        return this.commonTypes.fromFunctionType(ft.transformByCallProperty());
    } else if (ft != null && pname.equals("apply")) {
        return this.commonTypes.fromFunctionType(ft.transformByApplyProperty());
    }
    if (recvType.mayHaveProp(propQname)) {
        return recvType.getProp(propQname);
    }
    return null;
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) EnumType(com.google.javascript.jscomp.newtypes.EnumType) QualifiedName(com.google.javascript.jscomp.newtypes.QualifiedName) FunctionType(com.google.javascript.jscomp.newtypes.FunctionType) DeclaredFunctionType(com.google.javascript.jscomp.newtypes.DeclaredFunctionType) Declaration(com.google.javascript.jscomp.newtypes.Declaration) FunctionNamespace(com.google.javascript.jscomp.newtypes.FunctionNamespace) Namespace(com.google.javascript.jscomp.newtypes.Namespace)

Example 12 with JSType

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

the class SimpleInference method inferInstantiatedCallee.

FunctionType inferInstantiatedCallee(Node call, FunctionType calleeType, boolean bailForUntypedArguments, NTIScope scope) {
    Node callee = call.getFirstChild();
    Preconditions.checkArgument(calleeType.isGeneric(), "Expected generic type for %s but found %s", callee, calleeType);
    // The receiver type is useful for inference when calleeType has a @this annotation
    // that includes a type variable.
    JSType recvType = null;
    if (callee.isGetProp() && callee.getFirstChild().isQualifiedName()) {
        Node recv = callee.getFirstChild();
        QualifiedName recvQname = QualifiedName.fromNode(recv);
        Declaration decl = scope.getDeclaration(recvQname, false);
        if (decl != null) {
            recvType = decl.getTypeOfSimpleDecl();
        }
    }
    ImmutableList.Builder<JSType> argTypes = ImmutableList.builder();
    for (Node argNode = call.getSecondChild(); argNode != null; argNode = argNode.getNext()) {
        JSType t = inferExprRecur(argNode, scope);
        if (t == null) {
            if (bailForUntypedArguments && !argNode.isFunction()) {
                // Used for @const inference, where we want to be strict.
                return null;
            } else {
                // Used when inferring a signature for unannotated callbacks passed to generic
                // functions. Whatever type variable we can't infer will become unknown.
                t = this.commonTypes.BOTTOM;
            }
        }
        argTypes.add(t);
    }
    return calleeType.instantiateGenericsFromArgumentTypes(recvType, argTypes.build());
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) ImmutableList(com.google.common.collect.ImmutableList) Node(com.google.javascript.rhino.Node) QualifiedName(com.google.javascript.jscomp.newtypes.QualifiedName) Declaration(com.google.javascript.jscomp.newtypes.Declaration)

Example 13 with JSType

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

the class SimpleInference method inferGetelem.

private JSType inferGetelem(Node n, NTIScope scope) {
    checkState(n.isGetElem());
    Node recv = n.getFirstChild();
    Node propNode = n.getLastChild();
    // string literal as precisely as dot accesses.
    if (propNode.isString()) {
        JSType propType = inferPropAccess(recv, propNode.getString(), scope);
        if (propType != null) {
            return propType;
        }
    }
    JSType recvType = inferExprRecur(recv, scope);
    if (recvType != null) {
        JSType indexType = recvType.getIndexType();
        if (indexType != null) {
            JSType propType = inferExprRecur(propNode, scope);
            if (propType != null && propType.isSubtypeOf(indexType)) {
                return recvType.getIndexedType();
            }
        }
    }
    return null;
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) Node(com.google.javascript.rhino.Node)

Example 14 with JSType

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

the class SimpleInference method inferAndOr.

private JSType inferAndOr(Node n, NTIScope scope) {
    checkState(n.isOr() || n.isAnd());
    JSType lhs = inferExprRecur(n.getFirstChild(), scope);
    if (lhs == null) {
        return null;
    }
    JSType rhs = inferExprRecur(n.getSecondChild(), scope);
    if (rhs == null) {
        return null;
    }
    if (lhs.equals(rhs)) {
        return lhs;
    }
    if (n.isAnd()) {
        return JSType.join(lhs.specialize(this.commonTypes.FALSY), rhs);
    }
    return JSType.join(lhs.specialize(this.commonTypes.TRUTHY), rhs);
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType)

Example 15 with JSType

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

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