use of com.google.template.soy.base.internal.IndentedLinesBuilder 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;
}
use of com.google.template.soy.base.internal.IndentedLinesBuilder in project closure-templates by google.
the class XliffGenerator method generateXliff.
/**
* Generates the output XLIFF file content for a given SoyMsgBundle.
*
* @param msgBundle The SoyMsgBundle to process.
* @param sourceLocaleString The source language/locale string of the messages.
* @param targetLocaleString The target language/locale string of the messages (optional). If
* specified, the resulting XLIFF file will specify this target language and will contain
* empty 'target' tags. If not specified, the resulting XLIFF file will not contain target
* language and will not contain 'target' tags.
* @return The generated XLIFF file content.
*/
static CharSequence generateXliff(SoyMsgBundle msgBundle, String sourceLocaleString, @Nullable String targetLocaleString) {
Escaper attributeEscaper = XmlEscapers.xmlAttributeEscaper();
Escaper contentEscaper = XmlEscapers.xmlContentEscaper();
boolean hasTarget = targetLocaleString != null && targetLocaleString.length() > 0;
IndentedLinesBuilder ilb = new IndentedLinesBuilder(2);
ilb.appendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
ilb.appendLine("<xliff version=\"1.2\" xmlns=\"urn:oasis:names:tc:xliff:document:1.2\">");
ilb.increaseIndent();
ilb.appendLineStart("<file original=\"SoyMsgBundle\" datatype=\"x-soy-msg-bundle\"", " xml:space=\"preserve\"", " source-language=\"", attributeEscaper.escape(sourceLocaleString), "\"");
if (hasTarget) {
ilb.appendParts(" target-language=\"", attributeEscaper.escape(targetLocaleString), "\"");
}
ilb.appendLineEnd(">");
ilb.increaseIndent();
ilb.appendLine("<body>");
ilb.increaseIndent();
for (SoyMsg msg : msgBundle) {
// Begin 'trans-unit'.
ilb.appendLineStart("<trans-unit id=\"", Long.toString(msg.getId()), "\"");
String contentType = msg.getContentType();
if (contentType != null && contentType.length() > 0) {
String xliffDatatype = CONTENT_TYPE_TO_XLIFF_DATATYPE_MAP.get(contentType);
if (xliffDatatype == null) {
// just use the contentType string
xliffDatatype = contentType;
}
ilb.appendParts(" datatype=\"", attributeEscaper.escape(xliffDatatype), "\"");
}
ilb.appendLineEnd(">");
ilb.increaseIndent();
// Source.
ilb.appendLineStart("<source>");
for (SoyMsgPart msgPart : msg.getParts()) {
if (msgPart instanceof SoyMsgRawTextPart) {
String rawText = ((SoyMsgRawTextPart) msgPart).getRawText();
ilb.append(contentEscaper.escape(rawText));
} else if (msgPart instanceof SoyMsgPlaceholderPart) {
SoyMsgPlaceholderPart placeholder = (SoyMsgPlaceholderPart) msgPart;
ilb.appendParts("<x id=\"", attributeEscaper.escape(placeholder.getPlaceholderName()), "\"" + // convention so we add it in the hope that tools will support it anyway.
(placeholder.getPlaceholderExample() != null ? " example=\"" + attributeEscaper.escape(placeholder.getPlaceholderExample()) + "\"" : "") + "/>");
} else {
throw new RuntimeException("Xliff doesn't support plurals or genders. " + msg.getSourceLocations());
}
}
ilb.appendLineEnd("</source>");
// Target.
if (hasTarget) {
ilb.appendLine("<target/>");
}
// Description and meaning.
String desc = msg.getDesc();
if (desc != null && desc.length() > 0) {
ilb.appendLine("<note priority=\"1\" from=\"description\">", contentEscaper.escape(desc), "</note>");
}
String meaning = msg.getMeaning();
if (meaning != null && meaning.length() > 0) {
ilb.appendLine("<note priority=\"1\" from=\"meaning\">", contentEscaper.escape(meaning), "</note>");
}
// End 'trans-unit'.
ilb.decreaseIndent();
ilb.appendLine("</trans-unit>");
}
ilb.decreaseIndent();
ilb.appendLine("</body>");
ilb.decreaseIndent();
ilb.appendLine("</file>");
ilb.decreaseIndent();
ilb.appendLine("</xliff>");
return ilb;
}
use of com.google.template.soy.base.internal.IndentedLinesBuilder in project closure-templates by google.
the class GenerateParseInfoVisitorTest method testAppendJavadoc.
@Test
public void testAppendJavadoc() {
String doc = "Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah" + " blah blah blah blah blah blah blahblahblahblahblahblahblahblahblahblahblahblahblah" + "blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah" + "blahblahblah.";
String expectedJavadoc = " /**\n" + " * Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah " + "blah blah blah\n" + " * blah blah blah blah blah\n" + " * blahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblahblah" + "blahblahblahb\n" + " * lahblahblahblahblahblahblahblahblahblahblahblah.\n" + " */\n";
IndentedLinesBuilder ilb = new IndentedLinesBuilder(2, 4);
GenerateParseInfoVisitor.appendJavadoc(ilb, doc, false, true);
assertEquals(expectedJavadoc, ilb.toString());
}
Aggregations