Search in sources :

Example 1 with TypeIRegistry

use of com.google.javascript.rhino.TypeIRegistry in project closure-compiler by google.

the class Es6TemplateLiterals method visitTaggedTemplateLiteral.

/**
 * Converts tag`a\tb${bar}` to:
 *   // A global (module) scoped variable
 *   var $jscomp$templatelit$0 = ["a\tb"];   // cooked string array
 *   $jscomp$templatelit$0.raw = ["a\\tb"];  // raw string array
 *   ...
 *   // A call to the tagging function
 *   tag($jscomp$templatelit$0, bar);
 *
 *   See template_literal_test.js for more examples.
 *
 * @param n A TAGGED_TEMPLATELIT node
 */
static void visitTaggedTemplateLiteral(NodeTraversal t, Node n, boolean addTypes) {
    TypeIRegistry registry = t.getCompiler().getTypeIRegistry();
    TypeI stringType = createType(addTypes, registry, JSTypeNative.STRING_TYPE);
    TypeI arrayType = createGenericType(addTypes, registry, JSTypeNative.ARRAY_TYPE, stringType);
    TypeI templateArrayType = createType(addTypes, registry, JSTypeNative.I_TEMPLATE_ARRAY_TYPE);
    Node templateLit = n.getLastChild();
    // Prepare the raw and cooked string arrays.
    Node raw = createRawStringArray(templateLit, arrayType, stringType);
    Node cooked = createCookedStringArray(templateLit, templateArrayType, stringType);
    // Specify the type of the first argument to be ITemplateArray.
    JSTypeExpression nonNullSiteObject = new JSTypeExpression(JsDocInfoParser.parseTypeString("!ITemplateArray"), "<Es6TemplateLiterals.java>");
    JSDocInfoBuilder info = new JSDocInfoBuilder(false);
    info.recordType(nonNullSiteObject);
    Node siteObject = withType(IR.cast(cooked, info.build()), templateArrayType);
    // Create a variable representing the template literal.
    Node callsiteId = withType(IR.name(TEMPLATELIT_VAR + t.getCompiler().getUniqueNameIdSupplier().get()), templateArrayType);
    Node var = IR.var(callsiteId, siteObject).useSourceInfoIfMissingFromForTree(n);
    Node script = NodeUtil.getEnclosingScript(n);
    script.addChildToFront(var);
    t.reportCodeChange(var);
    // Define the "raw" property on the introduced variable.
    Node defineRaw = IR.exprResult(withType(IR.assign(withType(IR.getprop(callsiteId.cloneNode(), withType(IR.string("raw"), stringType)), arrayType), raw), arrayType)).useSourceInfoIfMissingFromForTree(n);
    script.addChildAfter(defineRaw, var);
    // Generate the call expression.
    Node call = withType(IR.call(n.removeFirstChild(), callsiteId.cloneNode()), n.getTypeI());
    for (Node child = templateLit.getFirstChild(); child != null; child = child.getNext()) {
        if (!child.isString()) {
            call.addChildToBack(child.removeFirstChild());
        }
    }
    call.useSourceInfoIfMissingFromForTree(templateLit);
    call.putBooleanProp(Node.FREE_CALL, !call.getFirstChild().isGetProp());
    n.replaceWith(call);
    t.reportCodeChange();
}
Also used : TypeI(com.google.javascript.rhino.TypeI) Node(com.google.javascript.rhino.Node) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) TypeIRegistry(com.google.javascript.rhino.TypeIRegistry) JSDocInfoBuilder(com.google.javascript.rhino.JSDocInfoBuilder)

Example 2 with TypeIRegistry

use of com.google.javascript.rhino.TypeIRegistry in project closure-compiler by google.

the class Es6TemplateLiterals method visitTemplateLiteral.

/**
 * Converts `${a} b ${c} d ${e}` to (a + " b " + c + " d " + e)
 *
 * @param n A TEMPLATELIT node that is not prefixed with a tag
 */
static void visitTemplateLiteral(NodeTraversal t, Node n, boolean addTypes) {
    TypeIRegistry registry = t.getCompiler().getTypeIRegistry();
    TypeI stringType = createType(addTypes, registry, JSTypeNative.STRING_TYPE);
    int length = n.getChildCount();
    if (length == 0) {
        n.replaceWith(withType(IR.string("\"\""), stringType));
    } else {
        Node first = n.removeFirstChild();
        checkState(first.isString());
        if (length == 1) {
            n.replaceWith(first);
        } else {
            // Add the first string with the first substitution expression
            Node add = withType(IR.add(first, n.removeFirstChild().removeFirstChild()), n.getTypeI());
            // Process the rest of the template literal
            for (int i = 2; i < length; i++) {
                Node child = n.removeFirstChild();
                if (child.isString()) {
                    if (child.getString().isEmpty()) {
                        continue;
                    } else if (i == 2 && first.getString().isEmpty()) {
                        // So that `${hello} world` gets translated into (hello + " world")
                        // instead of ("" + hello + " world").
                        add = add.getSecondChild().detach();
                    }
                }
                add = withType(IR.add(add, child.isString() ? child : child.removeFirstChild()), n.getTypeI());
            }
            n.replaceWith(add.useSourceInfoIfMissingFromForTree(n));
        }
    }
    t.reportCodeChange();
}
Also used : TypeI(com.google.javascript.rhino.TypeI) Node(com.google.javascript.rhino.Node) TypeIRegistry(com.google.javascript.rhino.TypeIRegistry)

Example 3 with TypeIRegistry

use of com.google.javascript.rhino.TypeIRegistry in project closure-compiler by google.

the class ImplicitNullabilityCheck method visit.

/**
 * Crawls the JSDoc of the given node to find any names in JSDoc
 * that are implicitly null.
 */
@Override
public void visit(final NodeTraversal t, final Node n, final Node p) {
    final JSDocInfo info = n.getJSDocInfo();
    if (info == null) {
        return;
    }
    final TypeIRegistry registry = compiler.getTypeIRegistry();
    final List<Node> thrownTypes = transform(info.getThrownTypes(), new Function<JSTypeExpression, Node>() {

        @Override
        public Node apply(JSTypeExpression expr) {
            return expr.getRoot();
        }
    });
    final Scope scope = t.getScope();
    for (Node typeRoot : info.getTypeNodes()) {
        NodeUtil.visitPreOrder(typeRoot, new NodeUtil.Visitor() {

            @Override
            public void visit(Node node) {
                if (!node.isString()) {
                    return;
                }
                if (thrownTypes.contains(node)) {
                    return;
                }
                Node parent = node.getParent();
                if (parent != null) {
                    switch(parent.getToken()) {
                        case BANG:
                        case QMARK:
                        // The names inside function(this:Foo) and
                        case THIS:
                        case // function(new:Bar) are already non-null.
                        NEW:
                            return;
                        case PIPE:
                            {
                                // Inside a union
                                Node gp = parent.getParent();
                                if (gp != null && gp.getToken() == Token.QMARK) {
                                    // Inside an explicitly nullable union
                                    return;
                                }
                                for (Node child : parent.children()) {
                                    if ((child.isString() && child.getString().equals("null")) || child.getToken() == Token.QMARK) {
                                        // Inside a union that contains null or nullable type
                                        return;
                                    }
                                }
                                break;
                            }
                        default:
                            break;
                    }
                }
                String typeName = node.getString();
                if (typeName.equals("null") || registry.getType(scope, typeName) == null) {
                    return;
                }
                TypeI type = registry.createTypeFromCommentNode(node);
                if (type.isNullable()) {
                    reportWarning(t, node, typeName);
                }
            }
        }, Predicates.alwaysTrue());
    }
}
Also used : Node(com.google.javascript.rhino.Node) TypeI(com.google.javascript.rhino.TypeI) JSTypeExpression(com.google.javascript.rhino.JSTypeExpression) TypeIRegistry(com.google.javascript.rhino.TypeIRegistry) JSDocInfo(com.google.javascript.rhino.JSDocInfo)

Example 4 with TypeIRegistry

use of com.google.javascript.rhino.TypeIRegistry in project closure-compiler by google.

the class ProcessDefines method isValidDefineType.

/**
 * Only defines of literal number, string, or boolean are supported.
 */
private boolean isValidDefineType(JSTypeExpression expression) {
    TypeIRegistry registry = compiler.getTypeIRegistry();
    TypeI type = registry.evaluateTypeExpressionInGlobalScope(expression);
    return !type.isUnknownType() && type.isSubtypeOf(registry.getNativeType(NUMBER_STRING_BOOLEAN));
}
Also used : TypeI(com.google.javascript.rhino.TypeI) TypeIRegistry(com.google.javascript.rhino.TypeIRegistry)

Example 5 with TypeIRegistry

use of com.google.javascript.rhino.TypeIRegistry in project closure-compiler by google.

the class Es6ForOfConverter method visitForOf.

private void visitForOf(NodeTraversal t, Node node, Node parent) {
    Node variable = node.removeFirstChild();
    Node iterable = node.removeFirstChild();
    Node body = node.removeFirstChild();
    TypeI typeParam = unknownType;
    if (addTypes) {
        // TODO(sdh): This is going to be null if the iterable is nullable or unknown. We might want
        // to consider some way of unifying rather than simply looking at the nominal type.
        ObjectTypeI iterableType = iterable.getTypeI().autobox().toMaybeObjectType();
        if (iterableType != null) {
            TypeIRegistry registry = compiler.getTypeIRegistry();
            TypeI iterableBaseType = registry.getNativeType(JSTypeNative.ITERABLE_TYPE);
            typeParam = iterableType.getInstantiatedTypeArgument(iterableBaseType);
        }
    }
    TypeI iteratorType = createGenericType(JSTypeNative.ITERATOR_TYPE, typeParam);
    TypeI iIterableResultType = createGenericType(JSTypeNative.I_ITERABLE_RESULT_TYPE, typeParam);
    TypeI iteratorNextType = addTypes ? iteratorType.toMaybeObjectType().getPropertyType("next") : null;
    JSDocInfo varJSDocInfo = variable.getJSDocInfo();
    Node iterName = withType(IR.name(ITER_BASE + compiler.getUniqueNameIdSupplier().get()), iteratorType);
    iterName.makeNonIndexable();
    Node getNext = withType(IR.call(withType(IR.getprop(iterName.cloneTree(), withStringType(IR.string("next"))), iteratorNextType)), iIterableResultType);
    String variableName;
    Token declType;
    if (variable.isName()) {
        declType = Token.NAME;
        variableName = variable.getQualifiedName();
    } else {
        Preconditions.checkState(NodeUtil.isNameDeclaration(variable), "Expected var, let, or const. Got %s", variable);
        declType = variable.getToken();
        variableName = variable.getFirstChild().getQualifiedName();
    }
    Node iterResult = withType(IR.name(ITER_RESULT + variableName), iIterableResultType);
    iterResult.makeNonIndexable();
    Node call = Es6ToEs3Util.makeIterator(compiler, iterable);
    if (addTypes) {
        TypeI jscompType = t.getScope().getVar("$jscomp").getNode().getTypeI();
        TypeI makeIteratorType = jscompType.toMaybeObjectType().getPropertyType("makeIterator");
        call.getFirstChild().setTypeI(makeIteratorType);
        call.getFirstFirstChild().setTypeI(jscompType);
    }
    Node init = IR.var(iterName.cloneTree(), withType(call, iteratorType));
    Node initIterResult = iterResult.cloneTree();
    initIterResult.addChildToFront(getNext.cloneTree());
    init.addChildToBack(initIterResult);
    Node cond = withBooleanType(IR.not(withBooleanType(IR.getprop(iterResult.cloneTree(), withStringType(IR.string("done"))))));
    Node incr = withType(IR.assign(iterResult.cloneTree(), getNext.cloneTree()), iIterableResultType);
    Node declarationOrAssign;
    if (declType == Token.NAME) {
        declarationOrAssign = withType(IR.assign(withType(IR.name(variableName).useSourceInfoFrom(variable), typeParam), withType(IR.getprop(iterResult.cloneTree(), withStringType(IR.string("value"))), typeParam)), typeParam);
        declarationOrAssign.setJSDocInfo(varJSDocInfo);
        declarationOrAssign = IR.exprResult(declarationOrAssign);
    } else {
        declarationOrAssign = new Node(declType, withType(IR.name(variableName).useSourceInfoFrom(variable.getFirstChild()), typeParam));
        declarationOrAssign.getFirstChild().addChildToBack(withType(IR.getprop(iterResult.cloneTree(), withStringType(IR.string("value"))), typeParam));
        declarationOrAssign.setJSDocInfo(varJSDocInfo);
    }
    Node newBody = IR.block(declarationOrAssign, body).useSourceInfoFrom(body);
    Node newFor = IR.forNode(init, cond, incr, newBody);
    newFor.useSourceInfoIfMissingFromForTree(node);
    parent.replaceChild(node, newFor);
    compiler.reportChangeToEnclosingScope(newFor);
}
Also used : ObjectTypeI(com.google.javascript.rhino.ObjectTypeI) Node(com.google.javascript.rhino.Node) TypeI(com.google.javascript.rhino.TypeI) ObjectTypeI(com.google.javascript.rhino.ObjectTypeI) Token(com.google.javascript.rhino.Token) TypeIRegistry(com.google.javascript.rhino.TypeIRegistry) JSDocInfo(com.google.javascript.rhino.JSDocInfo)

Aggregations

TypeI (com.google.javascript.rhino.TypeI)5 TypeIRegistry (com.google.javascript.rhino.TypeIRegistry)5 Node (com.google.javascript.rhino.Node)4 JSDocInfo (com.google.javascript.rhino.JSDocInfo)2 JSTypeExpression (com.google.javascript.rhino.JSTypeExpression)2 JSDocInfoBuilder (com.google.javascript.rhino.JSDocInfoBuilder)1 ObjectTypeI (com.google.javascript.rhino.ObjectTypeI)1 Token (com.google.javascript.rhino.Token)1