Search in sources :

Example 1 with UniqueNameGenerator

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);
}
Also used : TemplateNode(com.google.template.soy.soytree.TemplateNode) SoyNode(com.google.template.soy.soytree.SoyNode) ParseResult(com.google.template.soy.SoyFileSetParser.ParseResult) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) UniqueNameGenerator(com.google.template.soy.base.internal.UniqueNameGenerator)

Example 2 with UniqueNameGenerator

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;
}
Also used : UniqueNameGenerator(com.google.template.soy.base.internal.UniqueNameGenerator)

Example 3 with UniqueNameGenerator

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()));
}
Also used : TemplateDelegateNode(com.google.template.soy.soytree.TemplateDelegateNode) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) ImmutableList(com.google.common.collect.ImmutableList) GoogRequire(com.google.template.soy.jssrc.dsl.GoogRequire) UniqueNameGenerator(com.google.template.soy.base.internal.UniqueNameGenerator) ShouldEnsureDataIsDefinedVisitor(com.google.template.soy.passes.ShouldEnsureDataIsDefinedVisitor)

Example 4 with UniqueNameGenerator

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();
}
Also used : SoyPrintDirective(com.google.template.soy.shared.restricted.SoyPrintDirective) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) SoyFileSetNode(com.google.template.soy.soytree.SoyFileSetNode) CallNode(com.google.template.soy.soytree.CallNode) UniqueNameGenerator(com.google.template.soy.base.internal.UniqueNameGenerator) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 5 with UniqueNameGenerator

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);
}
Also used : ErrorReporter(com.google.template.soy.error.ErrorReporter) SoyNode(com.google.template.soy.soytree.SoyNode) SoyFileSetNode(com.google.template.soy.soytree.SoyFileSetNode) UniqueNameGenerator(com.google.template.soy.base.internal.UniqueNameGenerator)

Aggregations

UniqueNameGenerator (com.google.template.soy.base.internal.UniqueNameGenerator)5 CodeChunk (com.google.template.soy.jssrc.dsl.CodeChunk)3 SoyFileSetNode (com.google.template.soy.soytree.SoyFileSetNode)2 SoyNode (com.google.template.soy.soytree.SoyNode)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 ParseResult (com.google.template.soy.SoyFileSetParser.ParseResult)1 ErrorReporter (com.google.template.soy.error.ErrorReporter)1 GoogRequire (com.google.template.soy.jssrc.dsl.GoogRequire)1 ShouldEnsureDataIsDefinedVisitor (com.google.template.soy.passes.ShouldEnsureDataIsDefinedVisitor)1 SoyPrintDirective (com.google.template.soy.shared.restricted.SoyPrintDirective)1 CallNode (com.google.template.soy.soytree.CallNode)1 TemplateDelegateNode (com.google.template.soy.soytree.TemplateDelegateNode)1 TemplateNode (com.google.template.soy.soytree.TemplateNode)1