Search in sources :

Example 41 with PyExpr

use of com.google.template.soy.pysrc.restricted.PyExpr in project closure-templates by google.

the class MsgFuncGenerator method pyFuncForPluralMsg.

private PyStringExpr pyFuncForPluralMsg() {
    SoyMsgPluralPart pluralPart = (SoyMsgPluralPart) msgParts.get(0);
    MsgPluralNode pluralNode = msgNode.getRepPluralNode(pluralPart.getPluralVarName());
    Map<PyExpr, PyExpr> nodePyVarToPyExprMap = collectVarNameListAndToPyExprMap();
    Map<PyExpr, PyExpr> caseSpecStrToMsgTexts = new LinkedHashMap<>();
    for (Case<SoyMsgPluralCaseSpec> pluralCase : pluralPart.getCases()) {
        caseSpecStrToMsgTexts.put(new PyStringExpr("'" + pluralCase.spec() + "'"), new PyStringExpr("'" + processMsgPartsHelper(pluralCase.parts(), escaperForIcuSection) + "'"));
    }
    prepareFunc.addArg(msgId).addArg(PyExprUtils.convertMapToPyExpr(caseSpecStrToMsgTexts)).addArg(PyExprUtils.convertIterableToPyTupleExpr(nodePyVarToPyExprMap.keySet()));
    // Translates {@link MsgPluralNode#pluralExpr} into a Python lookup expression.
    // Note that pluralExpr represent the Soy expression inside the attributes of a plural tag.
    PyExpr pluralPyExpr = translateToPyExprVisitor.exec(pluralNode.getExpr());
    return renderFunc.addArg(prepareFunc.asPyExpr()).addArg(pluralPyExpr).addArg(PyExprUtils.convertMapToPyExpr(nodePyVarToPyExprMap)).asPyStringExpr();
}
Also used : SoyMsgPluralCaseSpec(com.google.template.soy.msgs.restricted.SoyMsgPluralCaseSpec) PyExpr(com.google.template.soy.pysrc.restricted.PyExpr) SoyMsgPluralPart(com.google.template.soy.msgs.restricted.SoyMsgPluralPart) PyStringExpr(com.google.template.soy.pysrc.restricted.PyStringExpr) MsgPluralNode(com.google.template.soy.soytree.MsgPluralNode) LinkedHashMap(java.util.LinkedHashMap)

Example 42 with PyExpr

use of com.google.template.soy.pysrc.restricted.PyExpr in project closure-templates by google.

the class GenPyCallExprVisitor method genObjToPass.

/**
 * Generates the Python expression for the object to pass in a given call. This expression will be
 * a combination of passed data and additional content params. If both are passed, they'll be
 * combined into one dictionary.
 *
 * @param callNode The call to generate code for.
 * @return The Python expression for the object to pass in the call.
 */
public String genObjToPass(CallNode callNode) {
    TranslateToPyExprVisitor translator = new TranslateToPyExprVisitor(localVarStack, errorReporter);
    // Generate the expression for the original data to pass.
    String dataToPass;
    if (callNode.isPassingAllData()) {
        dataToPass = "data";
    } else if (callNode.isPassingData()) {
        dataToPass = translator.exec(callNode.getDataExpr()).getText();
    } else {
        dataToPass = "{}";
    }
    // Case 1: No additional params.
    if (callNode.numChildren() == 0) {
        return dataToPass;
    }
    // Build an object literal containing the additional params.
    Map<PyExpr, PyExpr> additionalParams = new LinkedHashMap<>();
    for (CallParamNode child : callNode.getChildren()) {
        PyExpr key = new PyStringExpr("'" + child.getKey().identifier() + "'");
        if (child instanceof CallParamValueNode) {
            CallParamValueNode cpvn = (CallParamValueNode) child;
            additionalParams.put(key, translator.exec(cpvn.getExpr()));
        } else {
            CallParamContentNode cpcn = (CallParamContentNode) child;
            PyExpr valuePyExpr;
            if (isComputableAsPyExprVisitor.exec(cpcn)) {
                valuePyExpr = PyExprUtils.concatPyExprs(genPyExprsVisitorFactory.create(localVarStack, errorReporter).exec(cpcn));
            } else {
                // This is a param with content that cannot be represented as Python expressions, so we
                // assume that code has been generated to define the temporary variable 'param<n>'.
                String paramExpr = "param" + cpcn.getId();
                // The param can be assumed to be a list at this point since it was created as an output
                // variable.
                valuePyExpr = new PyListExpr(paramExpr, Integer.MAX_VALUE);
            }
            // Param content nodes require a content kind in strict autoescaping, so the content must be
            // wrapped as SanitizedContent.
            valuePyExpr = InternalPyExprUtils.wrapAsSanitizedContent(cpcn.getContentKind(), valuePyExpr.toPyString());
            additionalParams.put(key, valuePyExpr);
        }
    }
    PyExpr additionalParamsExpr = PyExprUtils.convertMapToPyExpr(additionalParams);
    // Cases 2 and 3: Additional params with and without original data to pass.
    if (callNode.isPassingData()) {
        // make a shallow copy so we don't accidentally modify the param
        dataToPass = "dict(" + dataToPass + ")";
        return "runtime.merge_into_dict(" + dataToPass + ", " + additionalParamsExpr.getText() + ")";
    } else {
        return additionalParamsExpr.getText();
    }
}
Also used : PyExpr(com.google.template.soy.pysrc.restricted.PyExpr) CallParamContentNode(com.google.template.soy.soytree.CallParamContentNode) CallParamNode(com.google.template.soy.soytree.CallParamNode) PyListExpr(com.google.template.soy.pysrc.restricted.PyListExpr) CallParamValueNode(com.google.template.soy.soytree.CallParamValueNode) PyStringExpr(com.google.template.soy.pysrc.restricted.PyStringExpr) LinkedHashMap(java.util.LinkedHashMap)

Example 43 with PyExpr

use of com.google.template.soy.pysrc.restricted.PyExpr 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 44 with PyExpr

use of com.google.template.soy.pysrc.restricted.PyExpr 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 45 with PyExpr

use of com.google.template.soy.pysrc.restricted.PyExpr in project closure-templates by google.

the class GenPyExprsVisitor method visitIfNode.

/**
 * If all the children are computable as expressions, the IfNode can be written as a ternary
 * conditional expression.
 */
@Override
protected void visitIfNode(IfNode node) {
    // Create another instance of this visitor for generating Python expressions from children.
    GenPyExprsVisitor genPyExprsVisitor = genPyExprsVisitorFactory.create(localVarExprs, errorReporter);
    TranslateToPyExprVisitor translator = new TranslateToPyExprVisitor(localVarExprs, errorReporter);
    StringBuilder pyExprTextSb = new StringBuilder();
    boolean hasElse = false;
    for (SoyNode child : node.getChildren()) {
        if (child instanceof IfCondNode) {
            IfCondNode icn = (IfCondNode) child;
            // Python ternary conditional expressions modify the order of the conditional from
            // <conditional> ? <true> : <false> to
            // <true> if <conditional> else <false>
            PyExpr condBlock = PyExprUtils.concatPyExprs(genPyExprsVisitor.exec(icn)).toPyString();
            condBlock = PyExprUtils.maybeProtect(condBlock, PyExprUtils.pyPrecedenceForOperator(Operator.CONDITIONAL));
            pyExprTextSb.append(condBlock.getText());
            // Append the conditional and if/else syntax.
            PyExpr condPyExpr = translator.exec(icn.getExpr());
            pyExprTextSb.append(" if ").append(condPyExpr.getText()).append(" else ");
        } else if (child instanceof IfElseNode) {
            hasElse = true;
            IfElseNode ien = (IfElseNode) child;
            PyExpr elseBlock = PyExprUtils.concatPyExprs(genPyExprsVisitor.exec(ien)).toPyString();
            pyExprTextSb.append(elseBlock.getText());
        } else {
            throw new AssertionError("Unexpected if child node type. Child: " + child);
        }
    }
    if (!hasElse) {
        pyExprTextSb.append("''");
    }
    // By their nature, inline'd conditionals can only contain output strings, so they can be
    // treated as a string type with a conditional precedence.
    pyExprs.add(new PyStringExpr(pyExprTextSb.toString(), PyExprUtils.pyPrecedenceForOperator(Operator.CONDITIONAL)));
}
Also used : IfElseNode(com.google.template.soy.soytree.IfElseNode) SoyNode(com.google.template.soy.soytree.SoyNode) ParentSoyNode(com.google.template.soy.soytree.SoyNode.ParentSoyNode) IfCondNode(com.google.template.soy.soytree.IfCondNode) PyExpr(com.google.template.soy.pysrc.restricted.PyExpr) PyStringExpr(com.google.template.soy.pysrc.restricted.PyStringExpr)

Aggregations

PyExpr (com.google.template.soy.pysrc.restricted.PyExpr)82 Test (org.junit.Test)58 PyStringExpr (com.google.template.soy.pysrc.restricted.PyStringExpr)21 PyFunctionExprBuilder (com.google.template.soy.pysrc.restricted.PyFunctionExprBuilder)6 LinkedHashMap (java.util.LinkedHashMap)4 SoyPySrcPrintDirective (com.google.template.soy.pysrc.restricted.SoyPySrcPrintDirective)3 SoyPrintDirective (com.google.template.soy.shared.restricted.SoyPrintDirective)3 SoyNode (com.google.template.soy.soytree.SoyNode)3 ExprNode (com.google.template.soy.exprtree.ExprNode)2 ExprRootNode (com.google.template.soy.exprtree.ExprRootNode)2 PyListExpr (com.google.template.soy.pysrc.restricted.PyListExpr)2 MsgPluralNode (com.google.template.soy.soytree.MsgPluralNode)2 PrintNode (com.google.template.soy.soytree.PrintNode)2 SoyFileSetNode (com.google.template.soy.soytree.SoyFileSetNode)2 ParentSoyNode (com.google.template.soy.soytree.SoyNode.ParentSoyNode)2 Supplier (com.google.common.base.Supplier)1 ImmutableList (com.google.common.collect.ImmutableList)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