Search in sources :

Example 21 with ExprNode

use of com.google.template.soy.exprtree.ExprNode in project closure-templates by google.

the class TranslateExprNodeVisitor method visitLegacyObjectMapLiteralNode.

/**
 * Helper to visit a LegacyObjectMapLiteralNode, with the extra option of whether to quote keys.
 */
private CodeChunk.WithValue visitLegacyObjectMapLiteralNode(LegacyObjectMapLiteralNode node, boolean doQuoteKeys) {
    // If there are only string keys, then the expression will be
    // {aa: 11, bb: 22}    or    {'aa': 11, 'bb': 22}
    // where the former is with unquoted keys and the latter with quoted keys.
    // If there are both string and nonstring keys, then the expression will be
    // (function() { var $$tmp0 = {'aa': 11}; $$tmp0[opt_data.bb] = 22; return $$tmp0; })()
    // Since we are outputting JS code to be processed by Closure Compiler, it is important that
    // any unquoted map literal keys are string literals, since Closure Compiler can rename unquoted
    // map keys and we want everything to be renamed at the same time.
    // We will divide the map literal contents into two categories.
    // 
    // Key-value pairs with StringNode keys can be included in the JS object literal.
    // Key-value pairs that are not StringNodes (VarRefs, IJ values, etc.) must be passed through
    // the soy.$$checkLegacyObjectMapLiteralKey() function, cannot be included in the JS object
    // literal, and must generate code in the form of:
    // $$map[soy.$$checkLegacyObjectMapLiteralKey(key)] = value
    LinkedHashMap<CodeChunk.WithValue, CodeChunk.WithValue> objLiteral = new LinkedHashMap<>();
    LinkedHashMap<CodeChunk.WithValue, CodeChunk.WithValue> assignments = new LinkedHashMap<>();
    for (int i = 0; i < node.numChildren(); i += 2) {
        ExprNode keyNode = node.getChild(i);
        ExprNode valueNode = node.getChild(i + 1);
        // roll it into the next case.
        if (!(keyNode instanceof StringNode) && keyNode instanceof PrimitiveNode) {
            errorReporter.report(keyNode.getSourceLocation(), CONSTANT_USED_AS_KEY_IN_MAP_LITERAL, keyNode.toSourceString());
            continue;
        }
        // since the compiler may change the names of any unquoted map keys.
        if (!doQuoteKeys && !(keyNode instanceof StringNode)) {
            errorReporter.report(keyNode.getSourceLocation(), EXPR_IN_MAP_LITERAL_REQUIRES_QUOTE_KEYS_IF_JS, keyNode.toSourceString());
            continue;
        }
        if (keyNode instanceof StringNode) {
            if (doQuoteKeys) {
                objLiteral.put(visit(keyNode), visit(valueNode));
            } else {
                String strKey = ((StringNode) keyNode).getValue();
                if (BaseUtils.isIdentifier(strKey)) {
                    objLiteral.put(id(strKey), visit(valueNode));
                } else {
                    errorReporter.report(keyNode.getSourceLocation(), MAP_LITERAL_WITH_NON_ID_KEY_REQUIRES_QUOTE_KEYS_IF_JS, keyNode.toSourceString());
                    continue;
                }
            }
        } else {
            // key is not a StringNode; key must be passed through
            // soy.$$checkLegacyObjectMapLiteralKey() and the pair cannot be included in the JS object
            // literal.
            CodeChunk.WithValue rawKey = visit(keyNode);
            assignments.put(SOY_CHECK_LEGACY_OBJECT_MAP_LITERAL_KEY.call(rawKey), visit(valueNode));
        }
    }
    // Build the map literal
    ImmutableList<CodeChunk.WithValue> keys = ImmutableList.copyOf(objLiteral.keySet());
    ImmutableList<CodeChunk.WithValue> values = ImmutableList.copyOf(objLiteral.values());
    CodeChunk.WithValue map = mapLiteral(keys, values);
    if (assignments.isEmpty()) {
        // to a tmp var.
        return map;
    }
    // Otherwise, we need to bail to a tmp var and emit assignment statements.
    CodeChunk.WithValue mapVar = codeGenerator.declarationBuilder().setRhs(map).build().ref();
    ImmutableList.Builder<CodeChunk> initialStatements = ImmutableList.builder();
    for (Map.Entry<CodeChunk.WithValue, CodeChunk.WithValue> entry : assignments.entrySet()) {
        initialStatements.add(mapVar.bracketAccess(entry.getKey()).assign(entry.getValue()));
    }
    return mapVar.withInitialStatements(initialStatements.build());
}
Also used : WithValue(com.google.template.soy.jssrc.dsl.CodeChunk.WithValue) ImmutableList(com.google.common.collect.ImmutableList) LinkedHashMap(java.util.LinkedHashMap) ExprNode(com.google.template.soy.exprtree.ExprNode) PrimitiveNode(com.google.template.soy.exprtree.ExprNode.PrimitiveNode) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) StringNode(com.google.template.soy.exprtree.StringNode) WithValue(com.google.template.soy.jssrc.dsl.CodeChunk.WithValue) Map(java.util.Map) LinkedHashMap(java.util.LinkedHashMap)

Example 22 with ExprNode

use of com.google.template.soy.exprtree.ExprNode in project closure-templates by google.

the class TranslateExprNodeVisitor method visitMapLiteralNode.

@Override
protected WithValue visitMapLiteralNode(MapLiteralNode node) {
    // Map literal nodes are much simpler to translate than legacy object map literal nodes.
    // Because they are implemented by ES6 Maps, there is no possibility that JSCompiler
    // will mistakenly rename (or not rename) its keys, and no need to ever quote a key.
    CodeChunk.WithValue map = codeGenerator.declarationBuilder().setRhs(CodeChunk.new_(id("Map")).call()).build().ref();
    ImmutableList.Builder<CodeChunk> setCalls = ImmutableList.builder();
    for (int i = 0; i < node.numChildren(); i += 2) {
        ExprNode keyNode = node.getChild(i);
        // Constructing a map literal with a null key is a runtime error.
        CodeChunk.WithValue key = SOY_CHECK_NOT_NULL.call(genMapKeyCode(keyNode));
        CodeChunk.WithValue value = visit(node.getChild(i + 1));
        setCalls.add(map.dotAccess("set").call(key, value));
    }
    return map.withInitialStatements(setCalls.build());
}
Also used : ExprNode(com.google.template.soy.exprtree.ExprNode) WithValue(com.google.template.soy.jssrc.dsl.CodeChunk.WithValue) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) ImmutableList(com.google.common.collect.ImmutableList)

Example 23 with ExprNode

use of com.google.template.soy.exprtree.ExprNode in project closure-templates by google.

the class GenJsCodeVisitor method visitSwitchNode.

/**
 * Example:
 *
 * <pre>
 *   {switch $boo}
 *     {case 0}
 *       ...
 *     {case 1, 2}
 *       ...
 *     {default}
 *       ...
 *   {/switch}
 * </pre>
 *
 * might generate
 *
 * <pre>
 *   switch (opt_data.boo) {
 *     case 0:
 *       ...
 *       break;
 *     case 1:
 *     case 2:
 *       ...
 *       break;
 *     default:
 *       ...
 *   }
 * </pre>
 */
@Override
protected void visitSwitchNode(SwitchNode node) {
    CodeChunk.WithValue switchOn = coerceTypeForSwitchComparison(node.getExpr());
    SwitchBuilder switchBuilder = switch_(switchOn);
    for (SoyNode child : node.getChildren()) {
        if (child instanceof SwitchCaseNode) {
            SwitchCaseNode scn = (SwitchCaseNode) child;
            ImmutableList.Builder<CodeChunk.WithValue> caseChunks = ImmutableList.builder();
            for (ExprNode caseExpr : scn.getExprList()) {
                CodeChunk.WithValue caseChunk = translateExpr(caseExpr);
                caseChunks.add(caseChunk);
            }
            CodeChunk body = visitChildrenReturningCodeChunk(scn);
            switchBuilder.case_(caseChunks.build(), body);
        } else if (child instanceof SwitchDefaultNode) {
            CodeChunk body = visitChildrenReturningCodeChunk((SwitchDefaultNode) child);
            switchBuilder.default_(body);
        } else {
            throw new AssertionError();
        }
    }
    jsCodeBuilder.append(switchBuilder.build());
}
Also used : ExprNode(com.google.template.soy.exprtree.ExprNode) ParentSoyNode(com.google.template.soy.soytree.SoyNode.ParentSoyNode) SoyNode(com.google.template.soy.soytree.SoyNode) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) SwitchBuilder(com.google.template.soy.jssrc.dsl.SwitchBuilder) ImmutableList(com.google.common.collect.ImmutableList) SwitchCaseNode(com.google.template.soy.soytree.SwitchCaseNode) SwitchDefaultNode(com.google.template.soy.soytree.SwitchDefaultNode)

Example 24 with ExprNode

use of com.google.template.soy.exprtree.ExprNode in project closure-templates by google.

the class SimplifyExprVisitor method visitAndOpNode.

// -----------------------------------------------------------------------------------------------
// Implementations for operators.
@Override
protected void visitAndOpNode(AndOpNode node) {
    // Recurse.
    visitChildren(node);
    // Can simplify if either child is constant. We assume no side-effects.
    SoyValue operand0 = getConstantOrNull(node.getChild(0));
    if (operand0 != null) {
        ExprNode replacementNode = operand0.coerceToBoolean() ? node.getChild(1) : node.getChild(0);
        node.getParent().replaceChild(node, replacementNode);
    }
}
Also used : ParentExprNode(com.google.template.soy.exprtree.ExprNode.ParentExprNode) ExprNode(com.google.template.soy.exprtree.ExprNode) SoyValue(com.google.template.soy.data.SoyValue)

Example 25 with ExprNode

use of com.google.template.soy.exprtree.ExprNode in project closure-templates by google.

the class SimplifyExprVisitor method visitOrOpNode.

@Override
protected void visitOrOpNode(OrOpNode node) {
    // Recurse.
    visitChildren(node);
    // Can simplify if either child is constant. We assume no side-effects.
    SoyValue operand0 = getConstantOrNull(node.getChild(0));
    if (operand0 != null) {
        ExprNode replacementNode = operand0.coerceToBoolean() ? node.getChild(0) : node.getChild(1);
        node.getParent().replaceChild(node, replacementNode);
    }
}
Also used : ParentExprNode(com.google.template.soy.exprtree.ExprNode.ParentExprNode) ExprNode(com.google.template.soy.exprtree.ExprNode) SoyValue(com.google.template.soy.data.SoyValue)

Aggregations

ExprNode (com.google.template.soy.exprtree.ExprNode)38 ParentExprNode (com.google.template.soy.exprtree.ExprNode.ParentExprNode)7 IntegerNode (com.google.template.soy.exprtree.IntegerNode)7 StringNode (com.google.template.soy.exprtree.StringNode)7 FunctionNode (com.google.template.soy.exprtree.FunctionNode)5 Test (org.junit.Test)5 ImmutableList (com.google.common.collect.ImmutableList)4 SoyValue (com.google.template.soy.data.SoyValue)4 GlobalNode (com.google.template.soy.exprtree.GlobalNode)4 VarRefNode (com.google.template.soy.exprtree.VarRefNode)4 CodeChunk (com.google.template.soy.jssrc.dsl.CodeChunk)4 SoyType (com.google.template.soy.types.SoyType)4 LinkedHashMap (java.util.LinkedHashMap)4 AbstractParentExprNode (com.google.template.soy.exprtree.AbstractParentExprNode)3 FloatNode (com.google.template.soy.exprtree.FloatNode)3 SourceLocation (com.google.template.soy.base.SourceLocation)2 ErrorReporter (com.google.template.soy.error.ErrorReporter)2 BooleanNode (com.google.template.soy.exprtree.BooleanNode)2 PrimitiveNode (com.google.template.soy.exprtree.ExprNode.PrimitiveNode)2 ExprRootNode (com.google.template.soy.exprtree.ExprRootNode)2