Search in sources :

Example 11 with SoyPrintDirective

use of com.google.template.soy.shared.restricted.SoyPrintDirective in project closure-templates by google.

the class GenPyCallExprVisitor method escapeCall.

/**
 * Escaping directives might apply to the output of the call node, so wrap the output with all
 * required directives.
 *
 * @param callExpr The expression text of the call itself.
 * @param directives The list of the directives to be applied to the call.
 * @return A PyExpr containing the call expression with all directives applied.
 */
private PyExpr escapeCall(String callExpr, ImmutableList<SoyPrintDirective> directives) {
    PyExpr escapedExpr = new PyExpr(callExpr, Integer.MAX_VALUE);
    if (directives.isEmpty()) {
        return escapedExpr;
    }
    // Successively wrap each escapedExpr in various directives.
    for (SoyPrintDirective directive : directives) {
        Preconditions.checkState(directive instanceof SoyPySrcPrintDirective, "Autoescaping produced a bogus directive: %s", directive.getName());
        escapedExpr = ((SoyPySrcPrintDirective) directive).applyForPySrc(escapedExpr, ImmutableList.<PyExpr>of());
    }
    return escapedExpr;
}
Also used : PyExpr(com.google.template.soy.pysrc.restricted.PyExpr) SoyPySrcPrintDirective(com.google.template.soy.pysrc.restricted.SoyPySrcPrintDirective) SoyPrintDirective(com.google.template.soy.shared.restricted.SoyPrintDirective)

Example 12 with SoyPrintDirective

use of com.google.template.soy.shared.restricted.SoyPrintDirective in project closure-templates by google.

the class GenPyExprsVisitor method visitMsgFallbackGroupNode.

@Override
protected void visitMsgFallbackGroupNode(MsgFallbackGroupNode node) {
    PyExpr msg = generateMsgFunc(node.getMsg());
    // MsgFallbackGroupNode could only have one child or two children. See MsgFallbackGroupNode.
    if (node.hasFallbackMsg()) {
        StringBuilder pyExprTextSb = new StringBuilder();
        PyExpr fallbackMsg = generateMsgFunc(node.getFallbackMsg());
        // Build Python ternary expression: a if cond else c
        pyExprTextSb.append(msg.getText()).append(" if ");
        // The fallback message is only used if the first message is not available, but the fallback
        // is. So availability of both messages must be tested.
        long firstId = MsgUtils.computeMsgIdForDualFormat(node.getMsg());
        long secondId = MsgUtils.computeMsgIdForDualFormat(node.getFallbackMsg());
        pyExprTextSb.append(PyExprUtils.TRANSLATOR_NAME).append(".is_msg_available(").append(firstId).append(")").append(" or not ").append(PyExprUtils.TRANSLATOR_NAME).append(".is_msg_available(").append(secondId).append(")");
        pyExprTextSb.append(" else ").append(fallbackMsg.getText());
        msg = new PyStringExpr(pyExprTextSb.toString(), PyExprUtils.pyPrecedenceForOperator(Operator.CONDITIONAL));
    }
    // Escaping directives apply to messages, especially in attribute context.
    for (SoyPrintDirective directive : node.getEscapingDirectives()) {
        Preconditions.checkState(directive instanceof SoyPySrcPrintDirective, "Contextual autoescaping produced a bogus directive: %s", directive.getName());
        msg = ((SoyPySrcPrintDirective) directive).applyForPySrc(msg, ImmutableList.<PyExpr>of());
    }
    pyExprs.add(msg);
}
Also used : PyExpr(com.google.template.soy.pysrc.restricted.PyExpr) SoyPySrcPrintDirective(com.google.template.soy.pysrc.restricted.SoyPySrcPrintDirective) SoyPrintDirective(com.google.template.soy.shared.restricted.SoyPrintDirective) PyStringExpr(com.google.template.soy.pysrc.restricted.PyStringExpr)

Example 13 with SoyPrintDirective

use of com.google.template.soy.shared.restricted.SoyPrintDirective in project closure-templates by google.

the class PerformDeprecatedNonContextualAutoescapeVisitor method visitPrintNode.

@Override
protected void visitPrintNode(PrintNode node) {
    if (autoescapeMode != AutoescapeMode.NONCONTEXTUAL) {
        // that this pass is never used without first running the contextual autoescaper.
        if (node.getChildren().isEmpty()) {
            throw new IllegalStateException(String.format("Internal error: A contextual or strict template has a print node that was never " + "assigned any escape directives: %s at %s", node.toSourceString(), node.getSourceLocation()));
        }
        return;
    }
    // Traverse the list to (a) record whether we saw any directive that cancels autoescape
    // (including 'noAutoescape' of course) and (b) remove 'noAutoescape' directives.
    boolean shouldCancelAutoescape = false;
    for (PrintDirectiveNode directiveNode : ImmutableList.copyOf(node.getChildren())) {
        SoyPrintDirective directive = directiveNode.getPrintDirective();
        if (directive != null && directive.shouldCancelAutoescape()) {
            shouldCancelAutoescape = true;
            break;
        }
    }
    // ideally should migrate off of deprecated-noncontextual autoescape.
    if (autoescapeMode == AutoescapeMode.NONCONTEXTUAL && !shouldCancelAutoescape) {
        PrintDirectiveNode newEscapeHtmlDirectiveNode = new PrintDirectiveNode(nodeIdGen.genId(), node.getSourceLocation(), ImmutableList.<ExprNode>of(), new EscapeHtmlDirective(), /* isSynthetic= */
        true);
        node.addChild(0, newEscapeHtmlDirectiveNode);
    }
}
Also used : EscapeHtmlDirective(com.google.template.soy.coredirectives.EscapeHtmlDirective) PrintDirectiveNode(com.google.template.soy.soytree.PrintDirectiveNode) SoyPrintDirective(com.google.template.soy.shared.restricted.SoyPrintDirective)

Example 14 with SoyPrintDirective

use of com.google.template.soy.shared.restricted.SoyPrintDirective in project closure-templates by google.

the class MsgCompiler method handleTranslationWithPlaceholders.

/**
 * Handles a complex message with placeholders.
 */
private Statement handleTranslationWithPlaceholders(MsgNode msg, ImmutableList<SoyPrintDirective> escapingDirectives, Expression soyMsgParts, Expression locale, ImmutableList<SoyMsgPart> parts) {
    // We need to render placeholders into a buffer and then pack them into a map to pass to
    // Runtime.renderSoyMsgWithPlaceholders.
    Expression placeholderMap = variables.getMsgPlaceholderMapField().accessor(thisVar);
    Map<String, Statement> placeholderNameToPutStatement = new LinkedHashMap<>();
    putPlaceholdersIntoMap(placeholderMap, msg, parts, placeholderNameToPutStatement);
    // sanity check
    checkState(!placeholderNameToPutStatement.isEmpty());
    variables.setMsgPlaceholderMapMinSize(placeholderNameToPutStatement.size());
    Statement populateMap = Statement.concat(placeholderNameToPutStatement.values());
    Statement clearMap = placeholderMap.invokeVoid(MethodRef.LINKED_HASH_MAP_CLEAR);
    Statement render;
    if (areAllPrintDirectivesStreamable(escapingDirectives)) {
        // No need to save/restore since rendering a message doesn't detach.  All detaching for data
        // should have already happened as part of constructing the placholder map.
        AppendableAndOptions wrappedAppendable = applyStreamingEscapingDirectives(escapingDirectives, appendableExpression, parameterLookup.getRenderContext(), variables);
        Statement initAppendable = Statement.NULL_STATEMENT;
        Statement clearAppendable = Statement.NULL_STATEMENT;
        Expression appendableExpression = wrappedAppendable.appendable();
        if (wrappedAppendable.closeable()) {
            Scope scope = variables.enterScope();
            Variable appendableVar = scope.createTemporary("msg_appendable", wrappedAppendable.appendable());
            initAppendable = appendableVar.initializer();
            appendableExpression = appendableVar.local();
            clearAppendable = Statement.concat(appendableVar.local().checkedCast(BytecodeUtils.CLOSEABLE_TYPE).invokeVoid(MethodRef.CLOSEABLE_CLOSE), scope.exitScope());
        }
        render = Statement.concat(initAppendable, MethodRef.RUNTIME_RENDER_SOY_MSG_PARTS_WITH_PLACEHOLDERS.invokeVoid(soyMsgParts, locale, placeholderMap, appendableExpression), clearAppendable);
    } else {
        // render into the handy buffer we already have!
        Statement renderToBuffer = MethodRef.RUNTIME_RENDER_SOY_MSG_PARTS_WITH_PLACEHOLDERS.invokeVoid(soyMsgParts, locale, placeholderMap, tempBuffer());
        // N.B. the type here is always 'string'
        SoyExpression value = SoyExpression.forString(tempBuffer().invoke(MethodRef.ADVISING_STRING_BUILDER_GET_AND_CLEAR));
        for (SoyPrintDirective directive : escapingDirectives) {
            value = parameterLookup.getRenderContext().applyPrintDirective(directive, value);
        }
        render = Statement.concat(renderToBuffer, appendableExpression.appendString(value.coerceToString()).toStatement());
    }
    return Statement.concat(populateMap, render, clearMap);
}
Also used : SoyExpression(com.google.template.soy.jbcsrc.restricted.SoyExpression) Variable(com.google.template.soy.jbcsrc.TemplateVariableManager.Variable) Scope(com.google.template.soy.jbcsrc.TemplateVariableManager.Scope) SoyExpression(com.google.template.soy.jbcsrc.restricted.SoyExpression) Expression(com.google.template.soy.jbcsrc.restricted.Expression) SoyPrintDirective(com.google.template.soy.shared.restricted.SoyPrintDirective) Statement(com.google.template.soy.jbcsrc.restricted.Statement) AppendableAndOptions(com.google.template.soy.jbcsrc.restricted.SoyJbcSrcPrintDirective.Streamable.AppendableAndOptions) LinkedHashMap(java.util.LinkedHashMap)

Example 15 with SoyPrintDirective

use of com.google.template.soy.shared.restricted.SoyPrintDirective in project closure-templates by google.

the class SoyNodeCompiler method visitMsgFallbackGroupNode.

/**
 * MsgFallbackGroupNodes have either one or two children. In the 2 child case the second child is
 * the {@code {fallbackmsg}} entry. For this we generate code that looks like:
 *
 * <pre>{@code
 * if (renderContext.hasMsg(primaryId)) {
 *   <render primary msg>
 * } else {
 *   <render fallback msg>
 * }
 * }</pre>
 *
 * <p>All of the logic for actually rendering {@code msg} nodes is handled by the {@link
 * MsgCompiler}.
 */
@Override
protected Statement visitMsgFallbackGroupNode(MsgFallbackGroupNode node) {
    MsgNode msg = node.getMsg();
    MsgPartsAndIds idAndParts = MsgUtils.buildMsgPartsAndComputeMsgIdForDualFormat(msg);
    ImmutableList<SoyPrintDirective> escapingDirectives = node.getEscapingDirectives();
    Statement renderDefault = getMsgCompiler().compileMessage(idAndParts, msg, escapingDirectives);
    // need to check for presence.
    if (node.hasFallbackMsg()) {
        MsgNode fallback = node.getFallbackMsg();
        MsgPartsAndIds fallbackIdAndParts = MsgUtils.buildMsgPartsAndComputeMsgIdForDualFormat(fallback);
        // TODO(lukes): consider changing the control flow here by 'inlining' the usePrimaryMsg logic
        // it would save some lookups.  Right now we will do to 2- 3 calls to
        // SoyMsgBundle.getMsgParts (each of which requires a binary search).  We could reduce that
        // to 1-2 in the worse case by inlining and storing the lists in local variables.
        IfBlock ifAvailableRenderDefault = IfBlock.create(parameterLookup.getRenderContext().usePrimaryMsg(idAndParts.id, fallbackIdAndParts.id), renderDefault);
        return ControlFlow.ifElseChain(ImmutableList.of(ifAvailableRenderDefault), Optional.of(getMsgCompiler().compileMessage(fallbackIdAndParts, fallback, escapingDirectives)));
    } else {
        return renderDefault;
    }
}
Also used : SoyPrintDirective(com.google.template.soy.shared.restricted.SoyPrintDirective) Statement(com.google.template.soy.jbcsrc.restricted.Statement) IfBlock(com.google.template.soy.jbcsrc.ControlFlow.IfBlock) MsgPartsAndIds(com.google.template.soy.msgs.internal.MsgUtils.MsgPartsAndIds) MsgNode(com.google.template.soy.soytree.MsgNode)

Aggregations

SoyPrintDirective (com.google.template.soy.shared.restricted.SoyPrintDirective)18 CodeChunk (com.google.template.soy.jssrc.dsl.CodeChunk)4 ExprRootNode (com.google.template.soy.exprtree.ExprRootNode)3 SoyJsSrcPrintDirective (com.google.template.soy.jssrc.restricted.SoyJsSrcPrintDirective)3 PyExpr (com.google.template.soy.pysrc.restricted.PyExpr)3 SoyPySrcPrintDirective (com.google.template.soy.pysrc.restricted.SoyPySrcPrintDirective)3 PrintDirectiveNode (com.google.template.soy.soytree.PrintDirectiveNode)3 ArrayList (java.util.ArrayList)3 ImmutableSet (com.google.common.collect.ImmutableSet)2 SoyValue (com.google.template.soy.data.SoyValue)2 Expression (com.google.template.soy.jbcsrc.restricted.Expression)2 SoyExpression (com.google.template.soy.jbcsrc.restricted.SoyExpression)2 Statement (com.google.template.soy.jbcsrc.restricted.Statement)2 LinkedHashMap (java.util.LinkedHashMap)2 Set (java.util.Set)2 Test (org.junit.Test)2 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 SanitizedContentKind (com.google.template.soy.base.internal.SanitizedContentKind)1 UniqueNameGenerator (com.google.template.soy.base.internal.UniqueNameGenerator)1