Search in sources :

Example 1 with QualifiedName

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

the class NewTypeInference method analyzeLValueFwd.

private LValueResultFwd analyzeLValueFwd(Node expr, TypeEnv inEnv, JSType requiredType, boolean insideQualifiedName) {
    LValueResultFwd lvalResult = null;
    switch(expr.getToken()) {
        case THIS:
            {
                mayWarnAboutGlobalThis(expr);
                if (this.currentScope.hasThis()) {
                    lvalResult = new LValueResultFwd(inEnv, envGetType(inEnv, THIS_ID), this.currentScope.getDeclaredTypeOf(THIS_ID), new QualifiedName(THIS_ID));
                } else {
                    lvalResult = new LValueResultFwd(inEnv, UNKNOWN, null, null);
                }
                break;
            }
        case NAME:
            {
                String varName = expr.getString();
                JSType varType = analyzeExprFwd(expr, inEnv).type;
                lvalResult = new LValueResultFwd(inEnv, varType, this.currentScope.getDeclaredTypeOf(varName), varType.hasNonScalar() ? new QualifiedName(varName) : null);
                break;
            }
        case GETPROP:
        case GETELEM:
            {
                Node obj = expr.getFirstChild();
                Node prop = expr.getLastChild();
                QualifiedName pname = expr.isGetProp() || prop.isString() ? new QualifiedName(prop.getString()) : null;
                LValueResultFwd recvLvalue = analyzeReceiverLvalFwd(obj, pname, inEnv, requiredType);
                if (!recvLvalue.type.isSubtypeOf(TOP_OBJECT)) {
                    EnvTypePair pair = analyzeExprFwd(prop, recvLvalue.env, requiredType);
                    lvalResult = new LValueResultFwd(pair.env, requiredType, null, null);
                    break;
                }
                JSType indexType = recvLvalue.type.getIndexType();
                // (1) A getelem where the receiver is an IObject
                if (expr.isGetElem() && indexType != null) {
                    lvalResult = analyzeIObjectElmLvalFwd(prop, recvLvalue, indexType);
                    break;
                }
                // (2) A getelem where the prop is a string literal is like a getprop
                if (expr.isGetProp() || prop.isString()) {
                    lvalResult = analyzePropLValFwd(obj, pname, recvLvalue, requiredType, insideQualifiedName);
                    break;
                }
                // (3) All other getelems
                // TODO(dimvar): there is some recomputation here; the receiver will be
                // analyzed again. Some more refactoring can fix this.
                EnvTypePair pair = analyzeExprFwd(expr, recvLvalue.env, requiredType);
                lvalResult = new LValueResultFwd(pair.env, pair.type, null, null);
                break;
            }
        case VAR:
            {
                // Can happen iff its parent is a for/in or for/of.
                checkState(expr.getParent().isForIn() || expr.getParent().isForOf());
                Node nameNode = expr.getFirstChild();
                String name = nameNode.getString();
                // For/in and for/of can never have rhs of its VAR
                checkState(!nameNode.hasChildren());
                maybeSetTypeI(nameNode, requiredType);
                if (expr.getParent().isForIn()) {
                    return new LValueResultFwd(inEnv, STRING, null, new QualifiedName(name));
                } else {
                    JSType declType = this.currentScope.getDeclaredTypeOf(name);
                    return new LValueResultFwd(inEnv, requiredType, declType, new QualifiedName(name));
                }
            }
        default:
            {
                // Expressions that aren't lvalues should be handled because they may
                // be, e.g., the left child of a getprop.
                // We must check that they are not the direct lvalues.
                checkState(insideQualifiedName);
                EnvTypePair pair = analyzeExprFwd(expr, inEnv, requiredType);
                return new LValueResultFwd(pair.env, pair.type, null, null);
            }
    }
    maybeSetTypeI(expr, lvalResult.type);
    mayWarnAboutUnknownType(expr, lvalResult.type);
    return lvalResult;
}
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)

Example 2 with QualifiedName

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

the class NewTypeInference method isFunctionBind.

private boolean isFunctionBind(Node callee, TypeEnv env, boolean isFwd) {
    if (NodeUtil.isFunctionBind(callee)) {
        if (isFwd) {
            analyzeExprFwdIgnoreResult(callee, env);
        }
        return true;
    }
    if (!callee.isGetProp() || !callee.isQualifiedName() || !callee.getLastChild().getString().equals("bind")) {
        return false;
    }
    Node recv = callee.getFirstChild();
    JSType recvType;
    if (isFwd) {
        recvType = analyzeExprFwd(recv, env).type;
        maybeSetTypeI(callee, recvType.getProp(new QualifiedName("bind")));
    } else {
        recvType = analyzeExprBwd(recv, env).type;
    }
    return !recvType.isUnknown() && recvType.isSubtypeOf(commonTypes.topFunction());
}
Also used : JSType(com.google.javascript.jscomp.newtypes.JSType) Node(com.google.javascript.rhino.Node) DiGraphNode(com.google.javascript.jscomp.graph.DiGraph.DiGraphNode) QualifiedName(com.google.javascript.jscomp.newtypes.QualifiedName)

Example 3 with QualifiedName

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

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

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

Aggregations

QualifiedName (com.google.javascript.jscomp.newtypes.QualifiedName)23 JSType (com.google.javascript.jscomp.newtypes.JSType)18 Node (com.google.javascript.rhino.Node)15 DiGraphNode (com.google.javascript.jscomp.graph.DiGraph.DiGraphNode)14 TypeEnv (com.google.javascript.jscomp.newtypes.TypeEnv)7 DeclaredFunctionType (com.google.javascript.jscomp.newtypes.DeclaredFunctionType)6 FunctionNamespace (com.google.javascript.jscomp.newtypes.FunctionNamespace)5 FunctionType (com.google.javascript.jscomp.newtypes.FunctionType)5 Namespace (com.google.javascript.jscomp.newtypes.Namespace)5 Declaration (com.google.javascript.jscomp.newtypes.Declaration)3 ImmutableList (com.google.common.collect.ImmutableList)1 ObjectLiteralCast (com.google.javascript.jscomp.CodingConvention.ObjectLiteralCast)1 EnumType (com.google.javascript.jscomp.newtypes.EnumType)1 RawNominalType (com.google.javascript.jscomp.newtypes.RawNominalType)1 JSDocInfo (com.google.javascript.rhino.JSDocInfo)1