Search in sources :

Example 16 with CodeChunk

use of com.google.template.soy.jssrc.dsl.CodeChunk 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 17 with CodeChunk

use of com.google.template.soy.jssrc.dsl.CodeChunk in project closure-templates by google.

the class GenJsCodeVisitor method visitSwitchNode.

/**
 * Example:
 *
 * <pre>
 *   {switch $boo}
 *     {case 0}
 *       ...
 *     {case 1, 2}
 *       ...
 *     {default}
 *       ...
 *   {/switch}
 * </pre>
 *
 * might generate
 *
 * <pre>
 *   switch (opt_data.boo) {
 *     case 0:
 *       ...
 *       break;
 *     case 1:
 *     case 2:
 *       ...
 *       break;
 *     default:
 *       ...
 *   }
 * </pre>
 */
@Override
protected void visitSwitchNode(SwitchNode node) {
    CodeChunk.WithValue switchOn = coerceTypeForSwitchComparison(node.getExpr());
    SwitchBuilder switchBuilder = switch_(switchOn);
    for (SoyNode child : node.getChildren()) {
        if (child instanceof SwitchCaseNode) {
            SwitchCaseNode scn = (SwitchCaseNode) child;
            ImmutableList.Builder<CodeChunk.WithValue> caseChunks = ImmutableList.builder();
            for (ExprNode caseExpr : scn.getExprList()) {
                CodeChunk.WithValue caseChunk = translateExpr(caseExpr);
                caseChunks.add(caseChunk);
            }
            CodeChunk body = visitChildrenReturningCodeChunk(scn);
            switchBuilder.case_(caseChunks.build(), body);
        } else if (child instanceof SwitchDefaultNode) {
            CodeChunk body = visitChildrenReturningCodeChunk((SwitchDefaultNode) child);
            switchBuilder.default_(body);
        } else {
            throw new AssertionError();
        }
    }
    jsCodeBuilder.append(switchBuilder.build());
}
Also used : ExprNode(com.google.template.soy.exprtree.ExprNode) ParentSoyNode(com.google.template.soy.soytree.SoyNode.ParentSoyNode) SoyNode(com.google.template.soy.soytree.SoyNode) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) SwitchBuilder(com.google.template.soy.jssrc.dsl.SwitchBuilder) ImmutableList(com.google.common.collect.ImmutableList) SwitchCaseNode(com.google.template.soy.soytree.SwitchCaseNode) SwitchDefaultNode(com.google.template.soy.soytree.SwitchDefaultNode)

Example 18 with CodeChunk

use of com.google.template.soy.jssrc.dsl.CodeChunk in project closure-templates by google.

the class GenIncrementalDomCodeVisitor method getAttributeValues.

private List<CodeChunk.WithValue> getAttributeValues(HtmlAttributeNode node) {
    if (!node.hasValue()) {
        // the runtime knows to create an attribute.
        return ImmutableList.of(LITERAL_EMPTY_STRING);
    }
    HtmlAttributeValueNode value = (HtmlAttributeValueNode) node.getChild(1);
    if (!isComputableAsJsExprsVisitor.execOnChildren(value)) {
        String outputVar = "html_attribute_" + node.getId();
        getJsCodeBuilder().pushOutputVar(outputVar).setOutputVarInited();
        SanitizedContentKind prev = getJsCodeBuilder().getContentKind();
        getJsCodeBuilder().setContentKind(SanitizedContentKind.TEXT);
        CodeChunk appends = visitChildrenReturningCodeChunk(value);
        getJsCodeBuilder().popOutputVar();
        getJsCodeBuilder().setContentKind(prev);
        return ImmutableList.of(CodeChunk.id(outputVar).withInitialStatements(ImmutableList.<CodeChunk>of(VariableDeclaration.builder(outputVar).setRhs(CodeChunk.LITERAL_EMPTY_STRING).build(), appends)));
    }
    return genJsExprsVisitor.execOnChildren(value);
}
Also used : CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) SanitizedContentKind(com.google.template.soy.base.internal.SanitizedContentKind) HtmlAttributeValueNode(com.google.template.soy.soytree.HtmlAttributeValueNode)

Example 19 with CodeChunk

use of com.google.template.soy.jssrc.dsl.CodeChunk in project closure-templates by google.

the class GenIncrementalDomCodeVisitor method generateFunctionBody.

@Override
protected CodeChunk generateFunctionBody(TemplateNode node) {
    IncrementalDomCodeBuilder jsCodeBuilder = getJsCodeBuilder();
    boolean isTextTemplate = isTextContent(node.getContentKind());
    CodeChunk typeChecks = genParamTypeChecks(node);
    // the transformation.
    if (isTextTemplate) {
        // We do our own initialization below, so mark it as such.
        jsCodeBuilder.pushOutputVar("output").setOutputVarInited();
    }
    CodeChunk body = visitChildrenReturningCodeChunk(node);
    if (isTextTemplate) {
        VariableDeclaration declare = VariableDeclaration.builder("output").setRhs(LITERAL_EMPTY_STRING).build();
        jsCodeBuilder.popOutputVar();
        body = CodeChunk.statements(declare, body, return_(sanitize(declare.ref(), node.getContentKind())));
    }
    return CodeChunk.statements(typeChecks, body);
}
Also used : CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) VariableDeclaration(com.google.template.soy.jssrc.dsl.VariableDeclaration)

Example 20 with CodeChunk

use of com.google.template.soy.jssrc.dsl.CodeChunk 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)

Aggregations

CodeChunk (com.google.template.soy.jssrc.dsl.CodeChunk)20 ImmutableList (com.google.common.collect.ImmutableList)6 VariableDeclaration (com.google.template.soy.jssrc.dsl.VariableDeclaration)4 SanitizedContentKind (com.google.template.soy.base.internal.SanitizedContentKind)3 ExprNode (com.google.template.soy.exprtree.ExprNode)3 WithValue (com.google.template.soy.jssrc.dsl.CodeChunk.WithValue)3 UniqueNameGenerator (com.google.template.soy.base.internal.UniqueNameGenerator)2 StringNode (com.google.template.soy.exprtree.StringNode)2 ConditionalBuilder (com.google.template.soy.jssrc.dsl.ConditionalBuilder)2 SwitchBuilder (com.google.template.soy.jssrc.dsl.SwitchBuilder)2 SoyPrintDirective (com.google.template.soy.shared.restricted.SoyPrintDirective)2 SoyNode (com.google.template.soy.soytree.SoyNode)2 ParentSoyNode (com.google.template.soy.soytree.SoyNode.ParentSoyNode)2 ArrayList (java.util.ArrayList)2 Map (java.util.Map)2 CheckReturnValue (javax.annotation.CheckReturnValue)2 ImmutableMap (com.google.common.collect.ImmutableMap)1 FieldDescriptor (com.google.protobuf.Descriptors.FieldDescriptor)1 PrimitiveNode (com.google.template.soy.exprtree.ExprNode.PrimitiveNode)1 ExprRootNode (com.google.template.soy.exprtree.ExprRootNode)1