use of com.google.template.soy.base.internal.UniqueNameGenerator 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.base.internal.UniqueNameGenerator in project closure-templates by google.
the class JsSrcNameGenerators method forLocalVariables.
/**
* Returns a name generator suitable for generating local variable names.
*/
public static UniqueNameGenerator forLocalVariables() {
UniqueNameGenerator generator = new UniqueNameGenerator(DANGEROUS_CHARACTERS, "$$");
generator.reserve(JsSrcUtils.JS_LITERALS);
generator.reserve(JsSrcUtils.JS_RESERVED_WORDS);
return generator;
}
use of com.google.template.soy.base.internal.UniqueNameGenerator in project closure-templates by google.
the class GenJsCodeVisitor method visitTemplateNode.
/**
* Outputs a {@link TemplateNode}, generating the function open and close, along with a a debug
* template name.
*
* <p>If aliasing is not performed (which is always the case for V1 templates), this looks like:
*
* <pre>
* my.namespace.func = function(opt_data, opt_sb) {
* ...
* };
* if (goog.DEBUG) {
* my.namespace.func.soyTemplateName = 'my.namespace.func';
* }
* </pre>
*
* <p>If aliasing is performed, this looks like:
*
* <pre>
* function $func(opt_data, opt_sb) {
* ...
* }
* exports.func = $func;
* if (goog.DEBUG) {
* $func.soyTemplateName = 'my.namespace.func';
* }
* <p>Note that the alias is not exactly the function name as in may conflict with a reserved
* JavaScript identifier.
* </pre>
*/
@Override
protected void visitTemplateNode(TemplateNode node) {
// TODO(lukes): why don't we always do this? even for old style params this would be useful
boolean useStrongTyping = hasStrictParams(node);
String templateName = node.getTemplateName();
String partialName = node.getPartialTemplateName();
String alias;
boolean addToExports = jsSrcOptions.shouldGenerateGoogModules();
// TODO(lukes): does it make sense to add deltempaltes or private templates to exports?
if (addToExports && node instanceof TemplateDelegateNode) {
alias = node.getPartialTemplateName().substring(1);
} else {
alias = templateAliases.get(templateName);
}
// TODO(lukes): reserve all the namespace prefixes that are in scope
// TODO(lukes): use this for all local variable declarations
UniqueNameGenerator nameGenerator = JsSrcNameGenerators.forLocalVariables();
CodeChunk.Generator codeGenerator = CodeChunk.Generator.create(nameGenerator);
templateTranslationContext = TranslationContext.of(SoyToJsVariableMappings.forNewTemplate(), codeGenerator, nameGenerator);
genJsExprsVisitor = genJsExprsVisitorFactory.create(templateTranslationContext, templateAliases, errorReporter);
assistantForMsgs = null;
String paramsRecordType = null;
String jsDoc = null;
// ------ Generate JS Doc. ------
StringBuilder jsDocBuilder = new StringBuilder();
jsDocBuilder.append("/**\n");
jsDocBuilder.append(" * @param {");
if (useStrongTyping) {
paramsRecordType = genParamsRecordType(node);
jsDocBuilder.append(alias).append(".Params");
} else {
jsDocBuilder.append("Object<string, *>=");
}
jsDocBuilder.append("} opt_data\n");
jsDocBuilder.append(" * @param {Object<string, *>=} opt_ijData\n");
jsDocBuilder.append(" * @param {Object<string, *>=} opt_ijData_deprecated\n");
String returnType = getTemplateReturnType(node);
jsDocBuilder.append(" * @return {").append(returnType).append("}\n");
// Sometimes we will throw an error in the middle and the following code is not reachable.
jsDocBuilder.append(" * @suppress {").append("checkTypes|uselessCode").append("}\n");
if (node.getVisibility() == Visibility.PRIVATE) {
jsDocBuilder.append(" * @private\n");
}
jsDocBuilder.append(" */\n");
jsDoc = jsDocBuilder.toString();
ImmutableList.Builder<CodeChunk> bodyStatements = ImmutableList.builder();
bodyStatements.add(CodeChunk.assign("opt_ijData", CodeChunk.id("opt_ijData_deprecated").or(CodeChunk.id("opt_ijData"), codeGenerator)));
// Generate statement to ensure data is defined, if necessary.
if (new ShouldEnsureDataIsDefinedVisitor().exec(node)) {
bodyStatements.add(assign("opt_data", OPT_DATA.or(EMPTY_OBJECT_LITERAL, codeGenerator)));
}
// ------ Generate function body. ------
bodyStatements.add(generateFunctionBody(node));
CodeChunk.WithValue function = CodeChunk.function(// are too brittle.
ImmutableList.of("opt_data", "opt_ijData", "opt_ijData_deprecated"), CodeChunk.statements(bodyStatements.build()));
ImmutableList.Builder<CodeChunk> declarations = ImmutableList.builder();
if (addToExports) {
declarations.add(VariableDeclaration.builder(alias).setRhs(function).build());
declarations.add(assign("exports" + /* partialName starts with a dot */
partialName, id(alias)));
} else {
declarations.add(CodeChunk.assign(alias, function));
}
// ------ Add the @typedef of opt_data. ------
if (paramsRecordType != null) {
// TODO(b/35203585): find a way to represent jsdoc using code chunks
StringBuilder sb = new StringBuilder();
sb.append("/**\n");
sb.append(" * @typedef {").append(paramsRecordType).append("}\n");
sb.append(" */\n");
// TODO(b/35203585): find a way to represent declarations like this in codechunks
sb.append(alias).append(".Params");
declarations.add(CodeChunk.treatRawStringAsStatementLegacyOnly(sb.toString(), ImmutableList.<GoogRequire>of()));
}
// ------ Add the fully qualified template name to the function to use in debug code. ------
declarations.add(ifStatement(GOOG_DEBUG, assign(alias + ".soyTemplateName", stringLiteral(templateName))).build());
// ------ If delegate template, generate a statement to register it. ------
if (node instanceof TemplateDelegateNode) {
TemplateDelegateNode nodeAsDelTemplate = (TemplateDelegateNode) node;
declarations.add(SOY_REGISTER_DELEGATE_FN.call(SOY_GET_DELTEMPLATE_ID.call(stringLiteral(delTemplateNamer.getDelegateName(nodeAsDelTemplate))), stringLiteral(nodeAsDelTemplate.getDelTemplateVariant()), number(nodeAsDelTemplate.getDelPriority().getValue()), dottedIdNoRequire(alias)));
}
// TODO(b/35203585): find a way to represent jsdoc using code chunks
if (jsDoc != null) {
jsCodeBuilder.append(jsDoc);
}
jsCodeBuilder.append(CodeChunk.statements(declarations.build()));
}
use of com.google.template.soy.base.internal.UniqueNameGenerator in project closure-templates by google.
the class GenCallCodeUtilsTest method getCallExprTextHelper.
private static String getCallExprTextHelper(String callSource, ImmutableList<String> escapingDirectives) {
SoyFileSetNode soyTree = SoyFileSetParserBuilder.forTemplateContents(callSource).parse().fileSet();
CallNode callNode = (CallNode) SharedTestUtils.getNode(soyTree, 0);
// Manually setting the escaping directives.
ImmutableMap<String, ? extends SoyPrintDirective> directives = INJECTOR.getInstance(new Key<ImmutableMap<String, ? extends SoyPrintDirective>>() {
});
callNode.setEscapingDirectives(escapingDirectives.stream().map(directives::get).collect(toImmutableList()));
GenCallCodeUtils genCallCodeUtils = JsSrcTestUtils.createGenCallCodeUtils();
UniqueNameGenerator nameGenerator = JsSrcNameGenerators.forLocalVariables();
CodeChunk call = genCallCodeUtils.gen(callNode, AliasUtils.IDENTITY_ALIASES, TranslationContext.of(SoyToJsVariableMappings.forNewTemplate(), CodeChunk.Generator.create(nameGenerator), nameGenerator), ErrorReporter.exploding());
return call.getCode();
}
use of com.google.template.soy.base.internal.UniqueNameGenerator in project closure-templates by google.
the class GenJsExprsVisitorTest method generateChunks.
private static List<CodeChunk.WithValue> generateChunks(String soyCode, int... indicesToNode) {
ErrorReporter boom = ErrorReporter.exploding();
SoyFileSetNode soyTree = SoyFileSetParserBuilder.forTemplateContents(soyCode).errorReporter(boom).parse().fileSet();
SoyNode node = SharedTestUtils.getNode(soyTree, indicesToNode);
UniqueNameGenerator nameGenerator = JsSrcNameGenerators.forLocalVariables();
GenJsExprsVisitor visitor = JsSrcTestUtils.createGenJsExprsVisitorFactory().create(TranslationContext.of(SoyToJsVariableMappings.startingWith(LOCAL_VAR_TRANSLATIONS), CodeChunk.Generator.create(nameGenerator), nameGenerator), AliasUtils.IDENTITY_ALIASES, boom);
return visitor.exec(node);
}
Aggregations