Search in sources :

Example 6 with TemplateNode

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

the class GenerateParseInfoVisitor method visitTemplateNode.

@Override
protected void visitTemplateNode(TemplateNode node) {
    // Don't generate anything for private or delegate templates.
    if (node.getVisibility() != Visibility.PUBLIC || node instanceof TemplateDelegateNode) {
        return;
    }
    // First build list of all transitive params (direct and indirect).
    LinkedHashMap<String, TemplateParam> transitiveParamMap = Maps.newLinkedHashMap();
    // Direct params.
    for (TemplateParam param : node.getParams()) {
        transitiveParamMap.put(param.name(), param);
    }
    // Indirect params.
    IndirectParamsInfo indirectParamsInfo = new FindIndirectParamsVisitor(templateRegistry).exec(node);
    for (TemplateParam param : indirectParamsInfo.indirectParams.values()) {
        TemplateParam existingParam = transitiveParamMap.get(param.name());
        if (existingParam == null) {
            // Note: We don't list the description for indirect params.
            transitiveParamMap.put(param.name(), param.copyEssential());
        }
    }
    // Get info on injected params.
    IjParamsInfo ijParamsInfo = new FindIjParamsVisitor(templateRegistry).exec(node);
    // for IntelliJ
    @SuppressWarnings("ConstantConditions") String upperUnderscoreName = convertToUpperUnderscore(node.getPartialTemplateName().substring(1));
    String templateInfoClassName = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, upperUnderscoreName) + "SoyTemplateInfo";
    // ------ *SoyTemplateInfo class start. ------
    ilb.appendLine();
    ilb.appendLine();
    appendJavadoc(ilb, Optional.fromNullable(node.getSoyDocDesc()).or(""), true, false);
    ilb.appendLine("public static final class ", templateInfoClassName, " extends SoyTemplateInfo {");
    ilb.increaseIndent();
    // ------ Constants for template name. ------
    ilb.appendLine();
    ilb.appendLine("/** This template's full name. */");
    ilb.appendLine("public static final String __NAME__ = \"", node.getTemplateName(), "\";");
    ilb.appendLine("/** This template's partial name. */");
    ilb.appendLine("public static final String __PARTIAL_NAME__ = \"", node.getPartialTemplateName(), "\";");
    // ------ Param constants. ------
    boolean hasSeenFirstDirectParam = false;
    boolean hasSwitchedToIndirectParams = false;
    for (TemplateParam param : transitiveParamMap.values()) {
        if (param.desc() != null) {
            // Direct param.
            if (!hasSeenFirstDirectParam) {
                ilb.appendLine();
                hasSeenFirstDirectParam = true;
            }
            appendJavadoc(ilb, param.desc(), false, false);
        } else {
            // Indirect param.
            if (!hasSwitchedToIndirectParams) {
                ilb.appendLine();
                ilb.appendLine("// Indirect params.");
                hasSwitchedToIndirectParams = true;
            }
            // Get the list of all transitive callee names as they will appear in the generated
            // Javadoc (possibly containing both partial and full names) and sort them before
            // generating the Javadoc.
            SortedSet<String> sortedJavadocCalleeNames = Sets.newTreeSet();
            for (TemplateNode transitiveCallee : indirectParamsInfo.paramKeyToCalleesMultimap.get(param.name())) {
                String javadocCalleeName = buildTemplateNameForJavadoc(node.getParent(), transitiveCallee);
                sortedJavadocCalleeNames.add(javadocCalleeName);
            }
            // Generate the Javadoc.
            StringBuilder javadocSb = new StringBuilder();
            javadocSb.append("Listed by ");
            boolean isFirst = true;
            for (String javadocCalleeName : sortedJavadocCalleeNames) {
                if (isFirst) {
                    isFirst = false;
                } else {
                    javadocSb.append(", ");
                }
                javadocSb.append(javadocCalleeName);
            }
            javadocSb.append('.');
            appendJavadoc(ilb, javadocSb.toString(), false, true);
        }
        // The actual param field.
        ilb.appendLine("public static final String ", convertToUpperUnderscore(param.name()), " = \"", param.name(), "\";");
    }
    // ------ Constructor. ------
    ilb.appendLine();
    ilb.appendLine("private ", templateInfoClassName, "() {");
    ilb.increaseIndent();
    ilb.appendLine("super(");
    ilb.increaseIndent(2);
    ilb.appendLine("\"", node.getTemplateName(), "\",");
    if (!transitiveParamMap.isEmpty()) {
        ImmutableMap.Builder<String, String> entrySnippetPairs = ImmutableMap.builder();
        for (TemplateParam param : transitiveParamMap.values()) {
            entrySnippetPairs.put("\"" + param.name() + "\"", param.isRequired() ? "ParamRequisiteness.REQUIRED" : "ParamRequisiteness.OPTIONAL");
        }
        appendImmutableMap(ilb, "<String, ParamRequisiteness>", entrySnippetPairs.build());
        ilb.appendLineEnd(",");
    } else {
        ilb.appendLine("ImmutableMap.<String, ParamRequisiteness>of(),");
    }
    appendIjParamSet(ilb, ijParamsInfo);
    ilb.appendLineEnd(",");
    ilb.appendLine("\"", node.getAutoescapeMode().getAttributeValue(), "\");");
    ilb.decreaseIndent(2);
    ilb.decreaseIndent();
    ilb.appendLine("}");
    // ------ Singleton instance and its getter. ------
    ilb.appendLine();
    ilb.appendLine("private static final ", templateInfoClassName, " __INSTANCE__ =");
    ilb.increaseIndent(2);
    ilb.appendLine("new ", templateInfoClassName, "();");
    ilb.decreaseIndent(2);
    ilb.appendLine();
    ilb.appendLine("public static ", templateInfoClassName, " getInstance() {");
    ilb.increaseIndent();
    ilb.appendLine("return __INSTANCE__;");
    ilb.decreaseIndent();
    ilb.appendLine("}");
    // ------ *SoyTemplateInfo class end. ------
    ilb.decreaseIndent();
    ilb.appendLine("}");
    // ------ Static field with instance of *SoyTemplateInfo class. ------
    ilb.appendLine();
    ilb.appendLine("/** Same as ", templateInfoClassName, ".getInstance(). */");
    ilb.appendLine("public static final ", templateInfoClassName, " ", upperUnderscoreName, " =");
    ilb.increaseIndent(2);
    ilb.appendLine(templateInfoClassName, ".getInstance();");
    ilb.decreaseIndent(2);
}
Also used : TemplateDelegateNode(com.google.template.soy.soytree.TemplateDelegateNode) IjParamsInfo(com.google.template.soy.passes.FindIjParamsVisitor.IjParamsInfo) TemplateNode(com.google.template.soy.soytree.TemplateNode) FindIjParamsVisitor(com.google.template.soy.passes.FindIjParamsVisitor) ImmutableMap(com.google.common.collect.ImmutableMap) IndirectParamsInfo(com.google.template.soy.passes.FindIndirectParamsVisitor.IndirectParamsInfo) TemplateParam(com.google.template.soy.soytree.defn.TemplateParam) FindIndirectParamsVisitor(com.google.template.soy.passes.FindIndirectParamsVisitor)

Example 7 with TemplateNode

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

the class AddHtmlCommentsForDebugPass method rewriteTemplates.

/**
 * Actual rewrite the template nodes for adding HTML comments.
 */
private void rewriteTemplates(Set<TemplateNode> templatesToRewrite, IdGenerator nodeIdGen) {
    for (TemplateNode node : templatesToRewrite) {
        String templateName = getTemplateName(node);
        SourceLocation insertLocation = node.getSourceLocation();
        node.addChild(0, createSoyDebug(insertLocation, nodeIdGen, String.format(HTML_COMMENTS_PREFIX, templateName, insertLocation.getFilePath(), insertLocation.getBeginLine())));
        node.addChild(createSoyDebug(insertLocation, nodeIdGen, String.format(HTML_COMMENTS_SUFFIX, templateName)));
    }
}
Also used : TemplateNode(com.google.template.soy.soytree.TemplateNode) SourceLocation(com.google.template.soy.base.SourceLocation)

Example 8 with TemplateNode

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

the class AddHtmlCommentsForDebugPass method collectCallers.

/**
 * Tries to do simple BFS and mark all callers.
 */
private void collectCallers(Set<TemplateNode> templatesToRewrite, Multimap<TemplateNode, TemplateNode> strictHtmlCallers) {
    Queue<TemplateNode> queue = new ArrayDeque<>();
    queue.addAll(templatesToRewrite);
    while (!queue.isEmpty()) {
        TemplateNode node = queue.poll();
        for (TemplateNode caller : strictHtmlCallers.get(node)) {
            // Only push to queue if caller has not been visited yet.
            if (templatesToRewrite.add(caller)) {
                queue.add(caller);
            }
        }
    }
}
Also used : TemplateNode(com.google.template.soy.soytree.TemplateNode) ArrayDeque(java.util.ArrayDeque)

Example 9 with TemplateNode

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

the class Inferences method cloneTemplates.

/**
 * Clones a template, changing the name.
 *
 * @return A copy of tn, differing semantically only in name and auto-generated IDs. The new
 *     templates will be available via {@link #lookupTemplates} with the given name.
 */
public List<TemplateNode> cloneTemplates(String baseName, String derivedName, CallNode callNode) {
    if (!lookupTemplates(derivedName).isEmpty()) {
        throw new AssertionError(derivedName + " already has templates: " + lookupTemplates(derivedName));
    }
    ImmutableList.Builder<TemplateNode> b = ImmutableList.builder();
    for (TemplateNode tn : lookupTemplates(baseName)) {
        if (SoyTreeUtils.hasHtmlNodes(tn)) {
            throw SoyAutoescapeException.createWithNode("Non-strict template '" + baseName + "' contains HTML nodes but does not specify the kind. " + "This is no longer allowed, please migrate the template to strict and " + "specify a content kind by adding a kind attribute", callNode);
        }
        SoyFileHeaderInfo soyFileHeaderInfo = tn.getSoyFileHeaderInfo();
        // We trivially clone the template with new ids, this ensures that all the varrefs have proper
        // vardefns assigned.  Then we manually recopy to a new template in order to modify the name.
        // TODO(lukes): we should add direct support for swapping template names to TemplateNode
        // or just eliminate usecases for this method.
        TemplateNode trivialClonedTemplate = SoyTreeUtils.cloneWithNewIds(tn, idGen);
        int cloneId = trivialClonedTemplate.getId();
        // We need to use the unnamespaced name in the command text since we'll be inserting this
        // template into a file node that already has a namespace declaration.
        TemplateNode clone;
        if (tn instanceof TemplateBasicNode) {
            String derivedPartialName = (tn.getPartialTemplateName() != null) ? derivedName.substring(soyFileHeaderInfo.namespace.length()) : null;
            clone = new TemplateBasicNodeBuilder(soyFileHeaderInfo, ErrorReporter.exploding()).setId(cloneId).setSourceLocation(tn.getSourceLocation()).setCmdTextInfo(derivedName, derivedPartialName, tn.getVisibility(), tn.getAutoescapeMode(), tn.getContentKind(), tn.getRequiredCssNamespaces()).addParams(trivialClonedTemplate.getAllParams()).build();
            if (!(derivedName.equals(clone.getTemplateName()) && Objects.equals(derivedPartialName, clone.getPartialTemplateName()))) {
                throw new AssertionError();
            }
        } else if (tn instanceof TemplateDelegateNode) {
            TemplateDelegateNode tdn = (TemplateDelegateNode) tn;
            clone = new TemplateDelegateNodeBuilder(soyFileHeaderInfo, ErrorReporter.exploding()).setId(cloneId).setSourceLocation(tn.getSourceLocation()).setCmdTextInfo(derivedName, tdn.getDelTemplateVariant(), tdn.getDelPriority(), tn.getAutoescapeMode(), tn.getContentKind(), tn.getRequiredCssNamespaces()).addParams(trivialClonedTemplate.getAllParams()).build();
            if (!(derivedName.equals(((TemplateDelegateNode) clone).getDelTemplateName()))) {
                throw new AssertionError();
            }
        } else {
            throw new AssertionError("Unknown template node type: " + tn.getClass());
        }
        clone.addChildren(trivialClonedTemplate.getChildren());
        // Reassign all the local variable data which isn't maintained by the cloning process above.
        clone.setMaxLocalVariableTableSize(tn.getMaxLocalVariableTableSize());
        Iterator<TemplateParam> tnIterator = tn.getAllParams().iterator();
        Iterator<TemplateParam> cloneIterator = clone.getAllParams().iterator();
        while (tnIterator.hasNext()) {
            cloneIterator.next().setLocalVariableIndex(tnIterator.next().localVariableIndex());
        }
        b.add(clone);
    }
    ImmutableList<TemplateNode> clones = b.build();
    templatesByName.putAll(derivedName, clones);
    return clones;
}
Also used : TemplateNode(com.google.template.soy.soytree.TemplateNode) TemplateDelegateNode(com.google.template.soy.soytree.TemplateDelegateNode) TemplateBasicNode(com.google.template.soy.soytree.TemplateBasicNode) TemplateDelegateNodeBuilder(com.google.template.soy.soytree.TemplateDelegateNodeBuilder) ImmutableList(com.google.common.collect.ImmutableList) TemplateBasicNodeBuilder(com.google.template.soy.soytree.TemplateBasicNodeBuilder) SoyFileHeaderInfo(com.google.template.soy.soytree.TemplateNode.SoyFileHeaderInfo) TemplateParam(com.google.template.soy.soytree.defn.TemplateParam)

Example 10 with TemplateNode

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

the class BytecodeCompiler method writeSrcJar.

/**
 * Writes the source files out to a {@code -src.jar}. This places the soy files at the same
 * classpath relative location as their generated classes. Ultimately this can be used by
 * debuggers for source level debugging.
 *
 * <p>It is a little weird that the relative locations of the generated classes are not identical
 * to the input source files. This is due to the disconnect between java packages and soy
 * namespaces. We should consider using the soy namespace directly as a java package in the
 * future.
 *
 * @param registry All the templates in the current compilation unit
 * @param files The source files by file path
 * @param sink The source to write the jar file
 */
public static void writeSrcJar(TemplateRegistry registry, ImmutableMap<String, SoyFileSupplier> files, ByteSink sink) throws IOException {
    Set<SoyFileNode> seenFiles = new HashSet<>();
    try (SoyJarFileWriter writer = new SoyJarFileWriter(sink.openStream())) {
        for (TemplateNode template : registry.getAllTemplates()) {
            SoyFileNode file = template.getParent();
            if (file.getSoyFileKind() == SoyFileKind.SRC && seenFiles.add(file)) {
                String namespace = file.getNamespace();
                String fileName = file.getFileName();
                writer.writeEntry(Names.javaFileName(namespace, fileName), files.get(file.getFilePath()).asCharSource().asByteSource(UTF_8));
            }
        }
    }
}
Also used : TemplateNode(com.google.template.soy.soytree.TemplateNode) SoyJarFileWriter(com.google.template.soy.base.internal.SoyJarFileWriter) SoyFileNode(com.google.template.soy.soytree.SoyFileNode) HashSet(java.util.HashSet)

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