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