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);
}
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)));
}
}
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);
}
}
}
}
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;
}
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));
}
}
}
}
Aggregations