Search in sources :

Example 1 with TemplateNode

use of com.google.template.soy.soytree.TemplateNode in project closure-templates by google.

the class GenJsCodeVisitorTest method assertGeneratedJsCode.

// -----------------------------------------------------------------------------------------------
// Helpers.
/**
 * @param soyCode The soy code.
 * @param expectedJsCode JavaScript code expected to be generated from the Soy code.
 */
private void assertGeneratedJsCode(String soyCode, String expectedJsCode) {
    ParseResult parseResult = SoyFileSetParserBuilder.forTemplateContents(soyCode).allowUnboundGlobals(true).parse();
    TemplateNode templateNode = parseResult.fileSet().getChild(0).getChild(0);
    // Setup the GenJsCodeVisitor's state before the node is visited.
    genJsCodeVisitor.jsCodeBuilder = new JsCodeBuilder();
    genJsCodeVisitor.jsCodeBuilder.pushOutputVar("output");
    genJsCodeVisitor.jsCodeBuilder.setOutputVarInited();
    UniqueNameGenerator nameGenerator = JsSrcNameGenerators.forLocalVariables();
    CodeChunk.Generator codeGenerator = CodeChunk.Generator.create(nameGenerator);
    TranslationContext translationContext = TranslationContext.of(SoyToJsVariableMappings.startingWith(LOCAL_VAR_TRANSLATIONS), codeGenerator, nameGenerator);
    genJsCodeVisitor.templateTranslationContext = translationContext;
    genJsCodeVisitor.genJsExprsVisitor = JsSrcTestUtils.createGenJsExprsVisitorFactory().create(translationContext, TEMPLATE_ALIASES, ErrorReporter.exploding());
    // will be created when used
    genJsCodeVisitor.assistantForMsgs = null;
    for (SoyNode child : templateNode.getChildren()) {
        genJsCodeVisitor.visitForTesting(child, parseResult.registry(), ErrorReporter.exploding());
    }
    String genCode = genJsCodeVisitor.jsCodeBuilder.getCode();
    assertThat(genCode).isEqualTo(expectedJsCode);
}
Also used : TemplateNode(com.google.template.soy.soytree.TemplateNode) SoyNode(com.google.template.soy.soytree.SoyNode) ParseResult(com.google.template.soy.SoyFileSetParser.ParseResult) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) UniqueNameGenerator(com.google.template.soy.base.internal.UniqueNameGenerator)

Example 2 with TemplateNode

use of com.google.template.soy.soytree.TemplateNode in project closure-templates by google.

the class TemplateAnalysisTest method runTest.

void runTest(String... lines) {
    TemplateNode template = parseTemplate(lines);
    TemplateAnalysis analysis = TemplateAnalysis.analyze(template);
    for (FunctionNode node : SoyTreeUtils.getAllNodesOfType(template, FunctionNode.class)) {
        if (node.getSoyFunction() == NOT_REFED_FUNCTION) {
            checkNotReferenced(analysis, node.getChild(0));
        } else if (node.getSoyFunction() == REFED_FUNCTION) {
            checkReferenced(analysis, node.getChild(0));
        }
    }
}
Also used : TemplateNode(com.google.template.soy.soytree.TemplateNode) FunctionNode(com.google.template.soy.exprtree.FunctionNode)

Example 3 with TemplateNode

use of com.google.template.soy.soytree.TemplateNode in project closure-templates by google.

the class GenJsCodeVisitor method visitSoyFileNode.

/**
 * Example:
 *
 * <pre>
 * // This file was automatically generated from my-templates.soy.
 * // Please don't edit this file by hand.
 *
 * if (typeof boo == 'undefined') { var boo = {}; }
 * if (typeof boo.foo == 'undefined') { boo.foo = {}; }
 *
 * ...
 * </pre>
 */
@Override
protected void visitSoyFileNode(SoyFileNode node) {
    if (node.getSoyFileKind() != SoyFileKind.SRC) {
        // don't generate code for deps
        return;
    }
    StringBuilder file = new StringBuilder();
    file.append("// This file was automatically generated from ").append(node.getFileName()).append(".\n");
    file.append("// Please don't edit this file by hand.\n");
    // Output a section containing optionally-parsed compiler directives in comments. Since these
    // are comments, they are not controlled by an option, and will be removed by minifiers that do
    // not understand them.
    file.append("\n");
    file.append("/**\n");
    String fileOverviewDescription = " Templates in namespace " + node.getNamespace() + ".";
    file.append(" * @fileoverview").append(fileOverviewDescription).append('\n');
    if (node.getDelPackageName() != null) {
        file.append(" * @modName {").append(node.getDelPackageName()).append("}\n");
    }
    addJsDocToProvideDelTemplates(file, node);
    addJsDocToRequireDelTemplates(file, node);
    addCodeToRequireCss(file, node);
    file.append(" * @public\n").append(" */\n\n");
    // Add code to define JS namespaces or add provide/require calls for Closure Library.
    templateAliases = AliasUtils.IDENTITY_ALIASES;
    jsCodeBuilder = createCodeBuilder();
    if (jsSrcOptions.shouldGenerateGoogModules()) {
        templateAliases = AliasUtils.createTemplateAliases(node);
        addCodeToDeclareGoogModule(file, node);
        addCodeToRequireGoogModules(node);
    } else if (jsSrcOptions.shouldProvideRequireSoyNamespaces()) {
        addCodeToProvideSoyNamespace(file, node);
        if (jsSrcOptions.shouldProvideBothSoyNamespacesAndJsFunctions()) {
            addCodeToProvideJsFunctions(file, node);
        }
        file.append('\n');
        addCodeToRequireSoyNamespaces(node);
    } else if (jsSrcOptions.shouldProvideRequireJsFunctions()) {
        if (jsSrcOptions.shouldProvideBothSoyNamespacesAndJsFunctions()) {
            addCodeToProvideSoyNamespace(file, node);
        }
        addCodeToProvideJsFunctions(file, node);
        file.append('\n');
        addCodeToRequireJsFunctions(node);
    } else {
        throw new AssertionError("impossible");
    }
    // Add code for each template.
    for (TemplateNode template : node.getChildren()) {
        jsCodeBuilder.appendLine().appendLine();
        visit(template);
    }
    jsCodeBuilder.appendGoogRequires(file);
    jsCodeBuilder.appendCode(file);
    jsFilesContents.add(file.toString());
    jsCodeBuilder = null;
}
Also used : TemplateNode(com.google.template.soy.soytree.TemplateNode)

Example 4 with TemplateNode

use of com.google.template.soy.soytree.TemplateNode in project closure-templates by google.

the class GenJsCodeVisitor method addCodeToRequireCss.

/**
 * Appends requirecss jsdoc tags in the file header section.
 *
 * @param soyFile The file with the templates..
 */
private static void addCodeToRequireCss(StringBuilder header, SoyFileNode soyFile) {
    SortedSet<String> requiredCssNamespaces = new TreeSet<>();
    requiredCssNamespaces.addAll(soyFile.getRequiredCssNamespaces());
    for (TemplateNode template : soyFile.getChildren()) {
        requiredCssNamespaces.addAll(template.getRequiredCssNamespaces());
    }
    // the future, this might be supported per function.
    for (String requiredCssNamespace : requiredCssNamespaces) {
        header.append(" * @requirecss {").append(requiredCssNamespace).append("}\n");
    }
}
Also used : TemplateNode(com.google.template.soy.soytree.TemplateNode) TreeSet(java.util.TreeSet)

Example 5 with TemplateNode

use of com.google.template.soy.soytree.TemplateNode in project closure-templates by google.

the class GenerateParseInfoVisitor method visitSoyFileNode.

@Override
protected void visitSoyFileNode(SoyFileNode node) {
    if (node.getSoyFileKind() != SoyFileKind.SRC) {
        // don't generate code for deps
        return;
    }
    String javaClassName = soyFileToJavaClassNameMap.get(node);
    // Collect the following:
    // + all the public basic templates (non-private, non-delegate) in a map from the
    // upper-underscore template name to the template's node,
    // + all the param keys from all templates (including private),
    // + for each param key, the list of templates that list it directly.
    // + for any params whose type is a proto, get the proto name and Java class name.
    LinkedHashMap<String, TemplateNode> publicBasicTemplateMap = Maps.newLinkedHashMap();
    List<String> deltemplates = new ArrayList<>();
    Set<String> allParamKeys = Sets.newHashSet();
    SetMultimap<String, TemplateNode> paramKeyToTemplatesMultimap = LinkedHashMultimap.create();
    SortedSet<String> protoTypes = Sets.newTreeSet();
    for (TemplateNode template : node.getChildren()) {
        if (template.getVisibility() == Visibility.PUBLIC && template instanceof TemplateBasicNode) {
            publicBasicTemplateMap.put(convertToUpperUnderscore(template.getPartialTemplateName().substring(1)), template);
        }
        if (template instanceof TemplateDelegateNode) {
            deltemplates.add("\"" + template.getTemplateName() + "\"");
        }
        for (TemplateParam param : template.getAllParams()) {
            if (!param.isInjected()) {
                allParamKeys.add(param.name());
                paramKeyToTemplatesMultimap.put(param.name(), template);
            }
            if (param instanceof HeaderParam) {
                SoyType paramType = ((HeaderParam) param).type();
                findProtoTypesRecurse(paramType, protoTypes);
            }
        }
        // Field access nodes need special handling to ensure that extension references are handled.
        for (FieldAccessNode fieldAccess : SoyTreeUtils.getAllNodesOfType(template, FieldAccessNode.class)) {
            SoyType baseType = fieldAccess.getBaseExprChild().getType();
            if (baseType.getKind() == SoyType.Kind.PROTO) {
                FieldDescriptor desc = ((SoyProtoType) baseType).getFieldDescriptor(fieldAccess.getFieldName());
                if (desc.isExtension()) {
                    protoTypes.add(ProtoUtils.getTofuExtensionImport(desc));
                }
            }
        }
        // Add enums
        for (GlobalNode global : SoyTreeUtils.getAllNodesOfType(template, GlobalNode.class)) {
            if (global.isResolved() && global.getType().getKind() == SoyType.Kind.PROTO_ENUM) {
                protoTypes.add(((SoyProtoEnumType) global.getType()).getDescriptorExpression());
            }
        }
        // Add proto init
        for (ProtoInitNode protoInit : SoyTreeUtils.getAllNodesOfType(template, ProtoInitNode.class)) {
            if (protoInit.getType().getKind() == SoyType.Kind.PROTO) {
                protoTypes.add(((SoyProtoType) protoInit.getType()).getDescriptorExpression());
            }
        }
    }
    // allParamKeysMap is a map from upper-underscore key to original key.
    SortedMap<String, String> allParamKeysMap = Maps.newTreeMap();
    for (String key : allParamKeys) {
        String upperUnderscoreKey = convertToUpperUnderscore(key);
        // stage of the compiler.
        while (allParamKeysMap.containsKey(upperUnderscoreKey)) {
            upperUnderscoreKey = upperUnderscoreKey + "_";
        }
        allParamKeysMap.put(upperUnderscoreKey, key);
        // Updates the convertedIdents here, since we might have changed the value by adding
        // prepending underscores. Without this, the generated SoyTemplateInfo still use the
        // old mapping and will fail.
        convertedIdents.put(key, upperUnderscoreKey);
    }
    ilb = new IndentedLinesBuilder(2);
    // ------ Header. ------
    ilb.appendLine("// This file was automatically generated from ", node.getFileName(), ".");
    ilb.appendLine("// Please don't edit this file by hand.");
    ilb.appendLine();
    ilb.appendLine("package ", javaPackage, ";");
    ilb.appendLine();
    ilb.appendLine("import com.google.common.collect.ImmutableList;");
    ilb.appendLine("import com.google.common.collect.ImmutableMap;");
    ilb.appendLine("import com.google.common.collect.ImmutableSortedSet;");
    if (!protoTypes.isEmpty()) {
        ilb.appendLine("import com.google.protobuf.Descriptors.GenericDescriptor;");
    }
    ilb.appendLine("import com.google.template.soy.parseinfo.SoyFileInfo;");
    ilb.appendLine("import com.google.template.soy.parseinfo.SoyTemplateInfo;");
    // ------ Class start. ------
    ilb.appendLine();
    ilb.appendLine();
    appendJavadoc(ilb, "Soy parse info for " + node.getFileName() + ".", true, false);
    ilb.appendLine("public final class ", javaClassName, " extends SoyFileInfo {");
    ilb.increaseIndent();
    // ------ Constant for namespace. ------
    ilb.appendLine();
    ilb.appendLine();
    ilb.appendLine("/** This Soy file's namespace. */");
    ilb.appendLine("public static final String __NAMESPACE__ = \"", node.getNamespace(), "\";");
    // ------ Proto types map. ------
    if (!protoTypes.isEmpty()) {
        ilb.appendLine();
        ilb.appendLine();
        ilb.appendLine("/** Protocol buffer types used by these templates. */");
        ilb.appendLine("@Override public ImmutableList<GenericDescriptor> getProtoDescriptors() {");
        ilb.increaseIndent();
        // Note we use fully-qualified names instead of imports to avoid potential collisions.
        List<String> defaultInstances = Lists.newArrayList();
        defaultInstances.addAll(protoTypes);
        appendListOrSetHelper(ilb, "return ImmutableList.<GenericDescriptor>of", defaultInstances);
        ilb.appendLineEnd(";");
        ilb.decreaseIndent();
        ilb.appendLine("}");
    }
    // ------ Template names. ------
    ilb.appendLine();
    ilb.appendLine();
    ilb.appendLine("public static final class TemplateName {");
    ilb.increaseIndent();
    ilb.appendLine("private TemplateName() {}");
    ilb.appendLine();
    for (Entry<String, TemplateNode> templateEntry : publicBasicTemplateMap.entrySet()) {
        StringBuilder javadocSb = new StringBuilder();
        javadocSb.append("The full template name of the ").append(templateEntry.getValue().getPartialTemplateName()).append(" template.");
        appendJavadoc(ilb, javadocSb.toString(), false, true);
        ilb.appendLine("public static final String ", templateEntry.getKey(), " = \"", templateEntry.getValue().getTemplateName(), "\";");
    }
    ilb.decreaseIndent();
    ilb.appendLine("}");
    // ------ Params. ------
    ilb.appendLine();
    ilb.appendLine();
    ilb.appendLine("/**");
    ilb.appendLine(" * Param names from all templates in this Soy file.");
    ilb.appendLine(" */");
    ilb.appendLine("public static final class Param {");
    ilb.increaseIndent();
    ilb.appendLine("private Param() {}");
    ilb.appendLine();
    for (Map.Entry<String, String> paramEntry : allParamKeysMap.entrySet()) {
        String upperUnderscoreKey = paramEntry.getKey();
        String key = paramEntry.getValue();
        StringBuilder javadocSb = new StringBuilder();
        javadocSb.append("Listed by ");
        boolean isFirst = true;
        for (TemplateNode template : paramKeyToTemplatesMultimap.get(key)) {
            if (isFirst) {
                isFirst = false;
            } else {
                javadocSb.append(", ");
            }
            javadocSb.append(buildTemplateNameForJavadoc(node, template));
        }
        javadocSb.append('.');
        appendJavadoc(ilb, javadocSb.toString(), false, true);
        ilb.appendLine("public static final String ", upperUnderscoreKey, " = \"", key, "\";");
    }
    ilb.decreaseIndent();
    ilb.appendLine("}");
    // ------ Templates. ------
    for (TemplateNode template : publicBasicTemplateMap.values()) {
        visit(template);
    }
    // ------ Constructor. ------
    ilb.appendLine();
    ilb.appendLine();
    ilb.appendLine("private ", javaClassName, "() {");
    ilb.increaseIndent();
    ilb.appendLine("super(");
    ilb.increaseIndent(2);
    ilb.appendLine("\"", node.getFileName(), "\",");
    ilb.appendLine("\"", node.getNamespace(), "\",");
    // Templates.
    List<String> itemSnippets = Lists.newArrayList();
    itemSnippets.addAll(publicBasicTemplateMap.keySet());
    appendImmutableList(ilb, "<SoyTemplateInfo>", itemSnippets);
    ilb.appendLineEnd(",");
    // CSS names.
    SortedMap<String, CssTagsPrefixPresence> cssNameMap = new CollectCssNamesVisitor().exec(node);
    ImmutableMap.Builder<String, String> cssTagPrefixes = ImmutableMap.builder();
    for (Map.Entry<String, CssTagsPrefixPresence> entry : cssNameMap.entrySet()) {
        cssTagPrefixes.put("\"" + entry.getKey() + "\"", "CssTagsPrefixPresence." + entry.getValue().name());
    }
    appendImmutableMap(ilb, "<String, CssTagsPrefixPresence>", cssTagPrefixes.build());
    ilb.appendLineEnd(",");
    appendImmutableList(ilb, "<String>", deltemplates);
    ilb.appendLineEnd(");");
    ilb.decreaseIndent(2);
    ilb.decreaseIndent();
    ilb.appendLine("}");
    // ------ Singleton instance and its getter. ------
    ilb.appendLine();
    ilb.appendLine();
    ilb.appendLine("private static final ", javaClassName, " __INSTANCE__ =");
    ilb.increaseIndent(2);
    ilb.appendLine("new ", javaClassName, "();");
    ilb.decreaseIndent(2);
    ilb.appendLine();
    ilb.appendLine("public static ", javaClassName, " getInstance() {");
    ilb.increaseIndent();
    ilb.appendLine("return __INSTANCE__;");
    ilb.decreaseIndent();
    ilb.appendLine("}");
    // ------ Class end. ------
    ilb.appendLine();
    ilb.decreaseIndent();
    ilb.appendLine("}");
    generatedFiles.put(javaClassName + ".java", ilb.toString());
    ilb = null;
}
Also used : TemplateBasicNode(com.google.template.soy.soytree.TemplateBasicNode) HeaderParam(com.google.template.soy.soytree.defn.HeaderParam) IndentedLinesBuilder(com.google.template.soy.base.internal.IndentedLinesBuilder) ArrayList(java.util.ArrayList) FieldDescriptor(com.google.protobuf.Descriptors.FieldDescriptor) ProtoInitNode(com.google.template.soy.exprtree.ProtoInitNode) TemplateParam(com.google.template.soy.soytree.defn.TemplateParam) TemplateNode(com.google.template.soy.soytree.TemplateNode) TemplateDelegateNode(com.google.template.soy.soytree.TemplateDelegateNode) FieldAccessNode(com.google.template.soy.exprtree.FieldAccessNode) SoyProtoType(com.google.template.soy.types.SoyProtoType) ImmutableMap(com.google.common.collect.ImmutableMap) SoyType(com.google.template.soy.types.SoyType) GlobalNode(com.google.template.soy.exprtree.GlobalNode) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) SortedMap(java.util.SortedMap) LinkedHashMap(java.util.LinkedHashMap) CssTagsPrefixPresence(com.google.template.soy.parseinfo.SoyFileInfo.CssTagsPrefixPresence)

Aggregations

TemplateNode (com.google.template.soy.soytree.TemplateNode)89 Test (org.junit.Test)59 SoyFileSetNode (com.google.template.soy.soytree.SoyFileSetNode)35 TemplateRegistry (com.google.template.soy.soytree.TemplateRegistry)19 ErrorReporter (com.google.template.soy.error.ErrorReporter)11 ParseResult (com.google.template.soy.SoyFileSetParser.ParseResult)10 TransitiveDepTemplatesInfo (com.google.template.soy.passes.FindTransitiveDepTemplatesVisitor.TransitiveDepTemplatesInfo)9 RawTextNode (com.google.template.soy.soytree.RawTextNode)9 SoyFileNode (com.google.template.soy.soytree.SoyFileNode)8 TemplateParam (com.google.template.soy.soytree.defn.TemplateParam)7 FunctionNode (com.google.template.soy.exprtree.FunctionNode)6 PrintNode (com.google.template.soy.soytree.PrintNode)5 TemplateDelegateNode (com.google.template.soy.soytree.TemplateDelegateNode)5 ImmutableMap (com.google.common.collect.ImmutableMap)4 SourceLocation (com.google.template.soy.base.SourceLocation)4 StringNode (com.google.template.soy.exprtree.StringNode)4 MsgFallbackGroupNode (com.google.template.soy.soytree.MsgFallbackGroupNode)4 ImmutableList (com.google.common.collect.ImmutableList)3 VarRefNode (com.google.template.soy.exprtree.VarRefNode)3 SoyMsgBundle (com.google.template.soy.msgs.SoyMsgBundle)3