Search in sources :

Example 21 with JsExpr

use of com.google.template.soy.jssrc.restricted.JsExpr 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 22 with JsExpr

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

the class TranslateExprNodeVisitor method visitV1ExpressionFunction.

private CodeChunk.WithValue visitV1ExpressionFunction(FunctionNode node) {
    StringNode expr = (StringNode) node.getChild(0);
    JsExpr jsExpr = V1JsExprTranslator.translateToJsExpr(expr.getValue(), expr.getSourceLocation(), variableMappings, errorReporter);
    return CodeChunk.fromExpr(jsExpr, ImmutableList.<GoogRequire>of());
}
Also used : JsExpr(com.google.template.soy.jssrc.restricted.JsExpr) StringNode(com.google.template.soy.exprtree.StringNode)

Example 23 with JsExpr

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

the class SoyJsPluginUtils method applyDirective.

/**
 * Applies the given print directive to {@code expr} and returns the result.
 *
 * @param generator The CodeChunk generator to use.
 * @param expr The expression to apply the print directive to.
 * @param directive The print directive to apply.
 * @param args Print directive args, if any.
 */
public static CodeChunk.WithValue applyDirective(CodeChunk.Generator generator, CodeChunk.WithValue expr, SoyJsSrcPrintDirective directive, List<CodeChunk.WithValue> args) {
    List<JsExpr> argExprs = Lists.transform(args, TO_JS_EXPR);
    JsExpr applied = directive.applyForJsSrc(expr.singleExprOrName(), argExprs);
    RequiresCollector.IntoImmutableSet collector = new RequiresCollector.IntoImmutableSet();
    expr.collectRequires(collector);
    for (CodeChunk.WithValue arg : args) {
        arg.collectRequires(collector);
    }
    if (directive instanceof SoyLibraryAssistedJsSrcPrintDirective) {
        for (String name : ((SoyLibraryAssistedJsSrcPrintDirective) directive).getRequiredJsLibNames()) {
            collector.add(GoogRequire.create(name));
        }
    }
    ImmutableList.Builder<CodeChunk> initialStatements = ImmutableList.<CodeChunk>builder().addAll(expr.initialStatements());
    for (CodeChunk.WithValue arg : args) {
        initialStatements.addAll(arg.initialStatements());
    }
    return fromExpr(applied, collector.get()).withInitialStatements(initialStatements.build());
}
Also used : JsExpr(com.google.template.soy.jssrc.restricted.JsExpr) WithValue(com.google.template.soy.jssrc.dsl.CodeChunk.WithValue) ImmutableList(com.google.common.collect.ImmutableList) RequiresCollector(com.google.template.soy.jssrc.dsl.CodeChunk.RequiresCollector) SoyLibraryAssistedJsSrcPrintDirective(com.google.template.soy.jssrc.restricted.SoyLibraryAssistedJsSrcPrintDirective)

Example 24 with JsExpr

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

the class CodeChunk method assertExpr.

/**
 * Temporary method to ease migration to the CodeChunk DSL.
 *
 * <p>Because of the recursive nature of the JS codegen system, it is generally not possible
 * to convert one codegen method at a time to use the CodeChunk DSL.
 * However, the business logic inside those methods can be migrated incrementally.
 * Methods that do not yet use the CodeChunk DSL can "unwrap" inputs using this method
 * and "wrap" results using {@link CodeChunk#fromExpr(JsExpr)}. This is safe as long as
 * each CodeChunk generated for production code is
 * {@link CodeChunk.WithValue#isRepresentableAsSingleExpression}.
 *
 * TODO(user): remove.
 */
public final JsExpr assertExpr() {
    RequiresCollector.IntoImmutableSet collector = new RequiresCollector.IntoImmutableSet();
    JsExpr expr = assertExprAndCollectRequires(collector);
    ImmutableSet<GoogRequire> requires = collector.get();
    if (!requires.isEmpty()) {
        throw new IllegalStateException("calling assertExpr() would drop requires!: " + requires);
    }
    return expr;
}
Also used : JsExpr(com.google.template.soy.jssrc.restricted.JsExpr)

Example 25 with JsExpr

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

the class FormatNumDirective method applyForJsSrc.

@Override
public JsExpr applyForJsSrc(JsExpr value, List<JsExpr> args) {
    String numberFormatType = parseFormat(args);
    StringBuilder expr = new StringBuilder();
    expr.append("(new goog.i18n.NumberFormat(" + JS_ARGS_TO_ENUM.get(numberFormatType) + "))");
    // digits for compact short and long numbers.
    if (args.size() > 2) {
        String minFractionDigits = args.get(2).getText();
        String maxFractionDigits = args.size() > 3 ? args.get(3).getText() : minFractionDigits;
        expr.append(".setMinimumFractionDigits(").append(minFractionDigits).append(")");
        expr.append(".setMaximumFractionDigits(").append(maxFractionDigits).append(")");
    } else if ("'compact_short'".equals(numberFormatType) || "'compact_long'".equals(numberFormatType)) {
        // Note that this trims trailing zeros.
        expr.append(".setSignificantDigits(3)");
    }
    expr.append(".format(" + value.getText() + ")");
    return new JsExpr(expr.toString(), Integer.MAX_VALUE);
}
Also used : JsExpr(com.google.template.soy.jssrc.restricted.JsExpr) LocaleString(com.google.template.soy.shared.restricted.ApiCallScopeBindingAnnotations.LocaleString)

Aggregations

JsExpr (com.google.template.soy.jssrc.restricted.JsExpr)64 Test (org.junit.Test)42 CodeChunk (com.google.template.soy.jssrc.dsl.CodeChunk)3 ImmutableList (com.google.common.collect.ImmutableList)2 RequiresCollector (com.google.template.soy.jssrc.dsl.CodeChunk.RequiresCollector)2 SoyLibraryAssistedJsSrcPrintDirective (com.google.template.soy.jssrc.restricted.SoyLibraryAssistedJsSrcPrintDirective)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 Truth.assertThat (com.google.common.truth.Truth.assertThat)1 SanitizedContent (com.google.template.soy.data.SanitizedContent)1 ContentKind (com.google.template.soy.data.SanitizedContent.ContentKind)1 SoyValue (com.google.template.soy.data.SoyValue)1 UnsafeSanitizedContentOrdainer (com.google.template.soy.data.UnsafeSanitizedContentOrdainer)1 SoyString (com.google.template.soy.data.restricted.SoyString)1 StringData (com.google.template.soy.data.restricted.StringData)1 ExprRootNode (com.google.template.soy.exprtree.ExprRootNode)1 StringNode (com.google.template.soy.exprtree.StringNode)1 WithValue (com.google.template.soy.jssrc.dsl.CodeChunk.WithValue)1 SoyJsSrcPrintDirective (com.google.template.soy.jssrc.restricted.SoyJsSrcPrintDirective)1