Search in sources :

Example 1 with PrimitiveNode

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

the class RewriteGlobalsPass method resolveGlobal.

private void resolveGlobal(GlobalNode global) {
    // First check to see if this global matches a proto enum.  We do this because the enums from
    // the type registry have better type information and for applications with legacy globals
    // configs there is often overlap, so the order in which we check is actually important.
    // proto enums are dotted identifiers
    String name = global.getName();
    int lastDot = name.lastIndexOf('.');
    if (lastDot > 0) {
        String enumTypeName = name.substring(0, lastDot);
        SoyType type = typeRegistry.getType(enumTypeName);
        if (type != null && type.getKind() == SoyType.Kind.PROTO_ENUM) {
            SoyProtoEnumType enumType = (SoyProtoEnumType) type;
            String enumMemberName = name.substring(lastDot + 1);
            Integer enumValue = enumType.getValue(enumMemberName);
            if (enumValue != null) {
                // TODO(lukes): consider introducing a new PrimitiveNode for enums
                global.resolve(enumType, new IntegerNode(enumValue, global.getSourceLocation()));
            } else {
                // If we found the type definition but not the value, then that's an error
                // regardless of whether we're allowing unbound globals or not.
                errorReporter.report(global.getSourceLocation(), ENUM_MEMBERSHIP_ERROR, enumMemberName, enumTypeName);
            }
            // TODO(lukes): issue a warning if a registered global also matches
            return;
        }
    }
    // if that doesn't work, see if it was registered in the globals file.
    PrimitiveData value = compileTimeGlobals.get(global.getName());
    if (value != null) {
        PrimitiveNode expr = InternalValueUtils.convertPrimitiveDataToExpr(value, global.getSourceLocation());
        global.resolve(expr.getType(), expr);
    }
}
Also used : PrimitiveNode(com.google.template.soy.exprtree.ExprNode.PrimitiveNode) PrimitiveData(com.google.template.soy.data.restricted.PrimitiveData) IntegerNode(com.google.template.soy.exprtree.IntegerNode) SoyType(com.google.template.soy.types.SoyType) SoyProtoEnumType(com.google.template.soy.types.SoyProtoEnumType)

Example 2 with PrimitiveNode

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

the class SoyUtils method parseCompileTimeGlobals.

/**
 * Parses a globals file in the format created by {@link #generateCompileTimeGlobalsFile} into a
 * map from global name to primitive value.
 *
 * @param inputSource A source that returns a reader for the globals file.
 * @return The parsed globals map.
 * @throws IOException If an error occurs while reading the globals file.
 * @throws IllegalStateException If the globals file is not in the correct format.
 */
public static ImmutableMap<String, PrimitiveData> parseCompileTimeGlobals(CharSource inputSource) throws IOException {
    Builder<String, PrimitiveData> compileTimeGlobalsBuilder = ImmutableMap.builder();
    ErrorReporter errorReporter = ErrorReporter.exploding();
    try (BufferedReader reader = inputSource.openBufferedStream()) {
        int lineNum = 1;
        for (String line = reader.readLine(); line != null; line = reader.readLine(), ++lineNum) {
            if (line.startsWith("//") || line.trim().length() == 0) {
                continue;
            }
            SourceLocation sourceLocation = new SourceLocation("globals", lineNum, 1, lineNum, 1);
            Matcher matcher = COMPILE_TIME_GLOBAL_LINE.matcher(line);
            if (!matcher.matches()) {
                errorReporter.report(sourceLocation, INVALID_FORMAT, line);
                continue;
            }
            String name = matcher.group(1);
            String valueText = matcher.group(2).trim();
            ExprNode valueExpr = SoyFileParser.parseExprOrDie(valueText);
            // TODO: Consider allowing non-primitives (e.g. list/map literals).
            if (!(valueExpr instanceof PrimitiveNode)) {
                if (valueExpr instanceof GlobalNode || valueExpr instanceof VarRefNode) {
                    errorReporter.report(sourceLocation, INVALID_VALUE, valueExpr.toSourceString());
                } else {
                    errorReporter.report(sourceLocation, NON_PRIMITIVE_VALUE, valueExpr.toSourceString());
                }
                continue;
            }
            // Default case.
            compileTimeGlobalsBuilder.put(name, InternalValueUtils.convertPrimitiveExprToData((PrimitiveNode) valueExpr));
        }
    }
    return compileTimeGlobalsBuilder.build();
}
Also used : SourceLocation(com.google.template.soy.base.SourceLocation) ExprNode(com.google.template.soy.exprtree.ExprNode) PrimitiveNode(com.google.template.soy.exprtree.ExprNode.PrimitiveNode) PrimitiveData(com.google.template.soy.data.restricted.PrimitiveData) ErrorReporter(com.google.template.soy.error.ErrorReporter) VarRefNode(com.google.template.soy.exprtree.VarRefNode) Matcher(java.util.regex.Matcher) BufferedReader(java.io.BufferedReader) GlobalNode(com.google.template.soy.exprtree.GlobalNode)

Example 3 with PrimitiveNode

use of com.google.template.soy.exprtree.ExprNode.PrimitiveNode 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 4 with PrimitiveNode

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

the class SimplifyExprVisitor method attemptPreeval.

// -----------------------------------------------------------------------------------------------
// Helpers.
/**
 * Attempts to preevaluate a node. If successful, the node is replaced with a new constant node in
 * the tree. If unsuccessful, the tree is not changed.
 */
private void attemptPreeval(ExprNode node) {
    // Note that we need to catch RenderException because preevaluation may fail, e.g. when
    // (a) the expression uses a bidi function that needs bidiGlobalDir to be in scope, but the
    // apiCallScope is not currently active,
    // (b) the expression uses an external function (Soy V1 syntax),
    // (c) other cases I haven't thought up.
    SoyValue preevalResult;
    try {
        preevalResult = preevalVisitor.exec(node);
    } catch (RenderException e) {
        // failed to preevaluate
        return;
    }
    PrimitiveNode newNode = InternalValueUtils.convertPrimitiveDataToExpr((PrimitiveData) preevalResult, node.getSourceLocation());
    if (newNode != null) {
        node.getParent().replaceChild(node, newNode);
    }
}
Also used : PrimitiveNode(com.google.template.soy.exprtree.ExprNode.PrimitiveNode) RenderException(com.google.template.soy.sharedpasses.render.RenderException) SoyValue(com.google.template.soy.data.SoyValue)

Aggregations

PrimitiveNode (com.google.template.soy.exprtree.ExprNode.PrimitiveNode)4 PrimitiveData (com.google.template.soy.data.restricted.PrimitiveData)2 ExprNode (com.google.template.soy.exprtree.ExprNode)2 ImmutableList (com.google.common.collect.ImmutableList)1 SourceLocation (com.google.template.soy.base.SourceLocation)1 SoyValue (com.google.template.soy.data.SoyValue)1 ErrorReporter (com.google.template.soy.error.ErrorReporter)1 GlobalNode (com.google.template.soy.exprtree.GlobalNode)1 IntegerNode (com.google.template.soy.exprtree.IntegerNode)1 StringNode (com.google.template.soy.exprtree.StringNode)1 VarRefNode (com.google.template.soy.exprtree.VarRefNode)1 CodeChunk (com.google.template.soy.jssrc.dsl.CodeChunk)1 WithValue (com.google.template.soy.jssrc.dsl.CodeChunk.WithValue)1 RenderException (com.google.template.soy.sharedpasses.render.RenderException)1 SoyProtoEnumType (com.google.template.soy.types.SoyProtoEnumType)1 SoyType (com.google.template.soy.types.SoyType)1 BufferedReader (java.io.BufferedReader)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 Matcher (java.util.regex.Matcher)1