Search in sources :

Example 1 with SoyJsSrcPrintDirective

use of com.google.template.soy.jssrc.restricted.SoyJsSrcPrintDirective in project closure-templates by google.

the class GenCallCodeUtils method gen.

/**
 * Generates the JS expression for a given call.
 *
 * <p> Important: If there are CallParamContentNode children whose contents are not computable as
 * JS expressions, then this function assumes that, elsewhere, code has been generated to define
 * their respective 'param&lt;n&gt;' temporary variables.
 *
 * <p> Here are five example calls:
 * <pre>
 *   {call some.func data="all" /}
 *   {call some.func data="$boo.foo" /}
 *   {call some.func}
 *     {param goo = $moo /}
 *   {/call}
 *   {call some.func data="$boo"}
 *     {param goo}Blah{/param}
 *   {/call}
 *   {call some.func}
 *     {param goo}
 *       {for $i in range(3)}{$i}{/for}
 *     {/param}
 *   {/call}
 * </pre>
 * Their respective generated calls might be the following:
 * <pre>
 *   some.func(opt_data)
 *   some.func(opt_data.boo.foo)
 *   some.func({goo: opt_data.moo})
 *   some.func(soy.$$assignDefaults({goo: 'Blah'}, opt_data.boo))
 *   some.func({goo: param65})
 * </pre>
 * Note that in the last case, the param content is not computable as JS expressions, so we assume
 * that code has been generated to define the temporary variable 'param&lt;n&gt;'.
 *
 * @param callNode The call to generate code for.
 * @param templateAliases A mapping of fully qualified calls to a variable in scope.
 * @return The JS expression for the call.
 */
public CodeChunk.WithValue gen(CallNode callNode, TemplateAliases templateAliases, TranslationContext translationContext, ErrorReporter errorReporter) {
    // Build the JS CodeChunk for the callee's name.
    CodeChunk.WithValue callee;
    if (callNode instanceof CallBasicNode) {
        // Case 1: Basic call.
        // TODO(lukes): add the logic for the goog.require here.  The simplest strategy requires a
        // TemplateRegistry to detect external templates.
        callee = CodeChunk.dottedIdNoRequire(templateAliases.get(((CallBasicNode) callNode).getCalleeName()));
    } else {
        // Case 2: Delegate call.
        CallDelegateNode callDelegateNode = (CallDelegateNode) callNode;
        CodeChunk.WithValue calleeId = JsRuntime.SOY_GET_DELTEMPLATE_ID.call(stringLiteral(delTemplateNamer.getDelegateName(callDelegateNode)));
        ExprRootNode variantSoyExpr = callDelegateNode.getDelCalleeVariantExpr();
        CodeChunk.WithValue variant;
        if (variantSoyExpr == null) {
            // Case 2a: Delegate call with empty variant.
            variant = LITERAL_EMPTY_STRING;
        } else {
            // Case 2b: Delegate call with variant expression.
            variant = new TranslateExprNodeVisitor(translationContext, errorReporter).exec(variantSoyExpr);
        }
        callee = SOY_GET_DELEGATE_FN.call(calleeId, variant, callDelegateNode.allowEmptyDefault() ? LITERAL_TRUE : LITERAL_FALSE);
    }
    // Generate the data object to pass to callee
    CodeChunk.WithValue objToPass = genObjToPass(callNode, templateAliases, translationContext, errorReporter);
    // Generate the main call expression.
    CodeChunk.WithValue call = callee.call(objToPass, JsRuntime.OPT_IJ_DATA);
    if (callNode.getEscapingDirectives().isEmpty()) {
        return call;
    }
    // Apply escaping directives as necessary.
    // 
    // The print directive system continues to use JsExpr, as it is a publicly available API and
    // migrating it to CodeChunk would be a major change. Therefore, we convert our CodeChunks
    // to JsExpr and back here.
    JsExpr callResult = call.singleExprOrName();
    RequiresCollector.IntoImmutableSet collector = new RequiresCollector.IntoImmutableSet();
    call.collectRequires(collector);
    for (SoyPrintDirective directive : callNode.getEscapingDirectives()) {
        Preconditions.checkState(directive instanceof SoyJsSrcPrintDirective, "Contextual autoescaping produced a bogus directive: %s", directive.getName());
        callResult = ((SoyJsSrcPrintDirective) directive).applyForJsSrc(callResult, ImmutableList.<JsExpr>of());
        if (directive instanceof SoyLibraryAssistedJsSrcPrintDirective) {
            for (String name : ((SoyLibraryAssistedJsSrcPrintDirective) directive).getRequiredJsLibNames()) {
                collector.add(GoogRequire.create(name));
            }
        }
    }
    return fromExpr(callResult, collector.get()).withInitialStatements(call.initialStatements());
}
Also used : JsExpr(com.google.template.soy.jssrc.restricted.JsExpr) CallBasicNode(com.google.template.soy.soytree.CallBasicNode) RequiresCollector(com.google.template.soy.jssrc.dsl.CodeChunk.RequiresCollector) CallDelegateNode(com.google.template.soy.soytree.CallDelegateNode) ExprRootNode(com.google.template.soy.exprtree.ExprRootNode) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) SoyPrintDirective(com.google.template.soy.shared.restricted.SoyPrintDirective) SoyJsSrcPrintDirective(com.google.template.soy.jssrc.restricted.SoyJsSrcPrintDirective) SoyLibraryAssistedJsSrcPrintDirective(com.google.template.soy.jssrc.restricted.SoyLibraryAssistedJsSrcPrintDirective)

Example 2 with SoyJsSrcPrintDirective

use of com.google.template.soy.jssrc.restricted.SoyJsSrcPrintDirective in project closure-templates by google.

the class GenJsExprsVisitor method visitPrintNode.

/**
 * Example:
 * <pre>
 *   {$boo.foo}
 *   {$goo.moo + 5}
 * </pre>
 * might generate
 * <pre>
 *   opt_data.boo.foo
 *   gooData4.moo + 5
 * </pre>
 */
@Override
protected void visitPrintNode(PrintNode node) {
    CodeChunk.WithValue expr = translateExpr(node.getExpr());
    // Process directives.
    for (PrintDirectiveNode directiveNode : node.getChildren()) {
        // Get directive.
        SoyPrintDirective directive = directiveNode.getPrintDirective();
        if (!(directive instanceof SoyJsSrcPrintDirective)) {
            errorReporter.report(node.getSourceLocation(), UNKNOWN_SOY_JS_SRC_PRINT_DIRECTIVE, directiveNode.getName());
            return;
        }
        // Get directive args.
        List<ExprRootNode> argNodes = directiveNode.getArgs();
        // Convert args to CodeChunks.
        List<CodeChunk.WithValue> argChunks = new ArrayList<>(argNodes.size());
        for (ExprRootNode argNode : argNodes) {
            argChunks.add(translateExpr(argNode));
        }
        // Apply directive.
        expr = SoyJsPluginUtils.applyDirective(translationContext.codeGenerator(), expr, (SoyJsSrcPrintDirective) directive, argChunks);
    }
    chunks.add(expr);
}
Also used : PrintDirectiveNode(com.google.template.soy.soytree.PrintDirectiveNode) WithValue(com.google.template.soy.jssrc.dsl.CodeChunk.WithValue) CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) SoyPrintDirective(com.google.template.soy.shared.restricted.SoyPrintDirective) ArrayList(java.util.ArrayList) SoyJsSrcPrintDirective(com.google.template.soy.jssrc.restricted.SoyJsSrcPrintDirective) WithValue(com.google.template.soy.jssrc.dsl.CodeChunk.WithValue) ExprRootNode(com.google.template.soy.exprtree.ExprRootNode)

Example 3 with SoyJsSrcPrintDirective

use of com.google.template.soy.jssrc.restricted.SoyJsSrcPrintDirective in project closure-templates by google.

the class GenJsCodeVisitorAssistantForMsgs method generateMsgGroupVariable.

/**
 * Returns a code chunk representing a translated variable.
 *
 * <p>Example:
 *
 * <pre>
 *   {msg desc="Link to help content."}Learn more{/msg}
 *   {msg desc="Tells user how to access a product." hidden="true"}
 *     Click &lt;a href="}{$url}"&gt;here&lt;/a&gt; to access {$productName}.
 *   {/msg}
 * </pre>
 *
 * might return the following code chunk:
 *
 * <pre>
 *   /** @desc Link to help content. *{@literal /}
 *   var MSG_UNNAMED_9 = goog.getMsg('Learn more');
 *   var msg_s9 = MSG_UNNAMED_9;
 *   /** @desc Tells user how to access a product.
 *    *  @hidden *{@literal /}
 *   var MSG_UNNAMED_10 = goog.getMsg(
 *       'Click {$startLink}here{$endLink} to access {$productName}.',
 *       {startLink: '&lt;a href="' + opt_data.url + '"&gt;',
 *        endLink: '&lt;/a&gt;',
 *        productName: opt_data.productName});
 * </pre>
 */
public CodeChunk.WithValue generateMsgGroupVariable(MsgFallbackGroupNode node) {
    String tmpVarName = translationContext.nameGenerator().generateName("msg_s");
    CodeChunk.WithValue msg;
    if (node.numChildren() == 1) {
        translationContext.soyToJsVariableMappings().setIsPrimaryMsgInUse(node, CodeChunk.WithValue.LITERAL_TRUE);
        msg = generateSingleMsgVariable(node.getChild(0), tmpVarName);
    } else {
        // has fallbackmsg children
        msg = generateMsgGroupVariable(node, tmpVarName);
    }
    // handle escaping
    for (SoyPrintDirective printDirective : node.getEscapingDirectives()) {
        msg = SoyJsPluginUtils.applyDirective(translationContext.codeGenerator(), msg, (SoyJsSrcPrintDirective) printDirective, /* args= */
        ImmutableList.<CodeChunk.WithValue>of());
    }
    return msg;
}
Also used : CodeChunk(com.google.template.soy.jssrc.dsl.CodeChunk) SoyPrintDirective(com.google.template.soy.shared.restricted.SoyPrintDirective) SoyJsSrcPrintDirective(com.google.template.soy.jssrc.restricted.SoyJsSrcPrintDirective)

Aggregations

CodeChunk (com.google.template.soy.jssrc.dsl.CodeChunk)3 SoyJsSrcPrintDirective (com.google.template.soy.jssrc.restricted.SoyJsSrcPrintDirective)3 SoyPrintDirective (com.google.template.soy.shared.restricted.SoyPrintDirective)3 ExprRootNode (com.google.template.soy.exprtree.ExprRootNode)2 RequiresCollector (com.google.template.soy.jssrc.dsl.CodeChunk.RequiresCollector)1 WithValue (com.google.template.soy.jssrc.dsl.CodeChunk.WithValue)1 JsExpr (com.google.template.soy.jssrc.restricted.JsExpr)1 SoyLibraryAssistedJsSrcPrintDirective (com.google.template.soy.jssrc.restricted.SoyLibraryAssistedJsSrcPrintDirective)1 CallBasicNode (com.google.template.soy.soytree.CallBasicNode)1 CallDelegateNode (com.google.template.soy.soytree.CallDelegateNode)1 PrintDirectiveNode (com.google.template.soy.soytree.PrintDirectiveNode)1 ArrayList (java.util.ArrayList)1