use of com.google.template.soy.soytree.CallParamContentNode 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();
}
}
use of com.google.template.soy.soytree.CallParamContentNode in project closure-templates by google.
the class TemplateParserTest method testParseBasicCallStmt.
@SuppressWarnings({ "ConstantConditions" })
@Test
public void testParseBasicCallStmt() throws Exception {
String templateBody = "{@param too : ?}{@param animals: ?}\n" + " {call .booTemplate_ /}\n" + " {call foo.goo.mooTemplate data=\"all\" /}\n" + " {call .booTemplate_ /}\n" + " {call .zooTemplate data=\"$animals\"}\n" + " {param yoo: round($too) /}\n" + " {param woo kind=\"html\"}poo{/param}\n" + " {param zoo: 0 /}\n" + " {param doo kind=\"html\"}doopoo{/param}\n" + " {/call}\n";
List<StandaloneNode> nodes = parseTemplateContent(templateBody, FAIL).getChildren();
assertThat(nodes).hasSize(4);
CallBasicNode cn0 = (CallBasicNode) nodes.get(0);
assertEquals("brittle.test.ns.booTemplate_", cn0.getCalleeName());
assertEquals(".booTemplate_", cn0.getSourceCalleeName());
assertEquals(false, cn0.isPassingData());
assertEquals(false, cn0.isPassingAllData());
assertEquals(null, cn0.getDataExpr());
assertEquals("XXX", cn0.genBasePhName());
assertEquals(0, cn0.numChildren());
CallBasicNode cn1 = (CallBasicNode) nodes.get(1);
assertEquals("foo.goo.mooTemplate", cn1.getCalleeName());
assertEquals("foo.goo.mooTemplate", cn1.getSourceCalleeName());
assertEquals(true, cn1.isPassingData());
assertEquals(true, cn1.isPassingAllData());
assertEquals(null, cn1.getDataExpr());
assertFalse(cn1.genSamenessKey().equals(cn0.genSamenessKey()));
assertEquals(0, cn1.numChildren());
CallBasicNode cn2 = (CallBasicNode) nodes.get(2);
assertEquals("brittle.test.ns.booTemplate_", cn2.getCalleeName());
assertEquals(".booTemplate_", cn2.getSourceCalleeName());
assertFalse(cn2.isPassingData());
assertEquals(false, cn2.isPassingAllData());
assertEquals(null, cn2.getDataExpr());
assertEquals("XXX", cn2.genBasePhName());
assertEquals(0, cn2.numChildren());
CallBasicNode cn3 = (CallBasicNode) nodes.get(3);
assertEquals("brittle.test.ns.zooTemplate", cn3.getCalleeName());
assertEquals(".zooTemplate", cn3.getSourceCalleeName());
assertEquals(true, cn3.isPassingData());
assertEquals(false, cn3.isPassingAllData());
assertTrue(cn3.getDataExpr().getRoot() != null);
assertEquals("$animals", cn3.getDataExpr().toSourceString());
assertEquals(4, cn3.numChildren());
{
final CallParamValueNode cn4cpvn0 = (CallParamValueNode) cn3.getChild(0);
assertEquals("yoo", cn4cpvn0.getKey().identifier());
assertEquals("round($too)", cn4cpvn0.getExpr().toSourceString());
assertTrue(cn4cpvn0.getExpr().getRoot() instanceof FunctionNode);
}
{
final CallParamContentNode cn4cpcn1 = (CallParamContentNode) cn3.getChild(1);
assertEquals("woo", cn4cpcn1.getKey().identifier());
assertEquals(SanitizedContentKind.HTML, cn4cpcn1.getContentKind());
assertEquals("poo", ((RawTextNode) cn4cpcn1.getChild(0)).getRawText());
}
{
final CallParamValueNode cn4cpvn2 = (CallParamValueNode) cn3.getChild(2);
assertEquals("zoo", cn4cpvn2.getKey().identifier());
assertEquals("0", cn4cpvn2.getExpr().toSourceString());
}
{
final CallParamContentNode cn4cpcn3 = (CallParamContentNode) cn3.getChild(3);
assertEquals("doo", cn4cpcn3.getKey().identifier());
assertNotNull(cn4cpcn3.getContentKind());
assertEquals(SanitizedContentKind.HTML, cn4cpcn3.getContentKind());
assertEquals("doopoo", ((RawTextNode) cn4cpcn3.getChild(0)).getRawText());
}
}
use of com.google.template.soy.soytree.CallParamContentNode in project closure-templates by google.
the class TemplateParserTest method testParseDelegateCallStmt.
@SuppressWarnings({ "ConstantConditions" })
@Test
public void testParseDelegateCallStmt() throws Exception {
String templateBody = "{@param animals : ?}{@param too : ?}\n" + " {delcall booTemplate /}\n" + " {delcall foo.goo.mooTemplate data=\"all\" /}\n" + " {delcall MySecretFeature.zooTemplate data=\"$animals\"}\n" + " {param yoo: round($too) /}\n" + " {param woo kind=\"html\"}poo{/param}\n" + " {/delcall}\n";
List<StandaloneNode> nodes = parseTemplateContent(templateBody, FAIL).getChildren();
assertEquals(3, nodes.size());
CallDelegateNode cn0 = (CallDelegateNode) nodes.get(0);
assertEquals("booTemplate", cn0.getDelCalleeName());
assertEquals(false, cn0.isPassingData());
assertEquals(false, cn0.isPassingAllData());
assertEquals(null, cn0.getDataExpr());
assertEquals("XXX", cn0.genBasePhName());
assertEquals(0, cn0.numChildren());
CallDelegateNode cn1 = (CallDelegateNode) nodes.get(1);
assertEquals("foo.goo.mooTemplate", cn1.getDelCalleeName());
assertEquals(true, cn1.isPassingData());
assertEquals(true, cn1.isPassingAllData());
assertEquals(null, cn1.getDataExpr());
assertFalse(cn1.genSamenessKey().equals(cn0.genSamenessKey()));
assertEquals(0, cn1.numChildren());
CallDelegateNode cn2 = (CallDelegateNode) nodes.get(2);
assertEquals("MySecretFeature.zooTemplate", cn2.getDelCalleeName());
assertEquals(true, cn2.isPassingData());
assertEquals(false, cn2.isPassingAllData());
assertTrue(cn2.getDataExpr().getRoot() != null);
assertEquals("$animals", cn2.getDataExpr().toSourceString());
assertEquals(2, cn2.numChildren());
CallParamValueNode cn2cpvn0 = (CallParamValueNode) cn2.getChild(0);
assertEquals("yoo", cn2cpvn0.getKey().identifier());
assertEquals("round($too)", cn2cpvn0.getExpr().toSourceString());
assertTrue(cn2cpvn0.getExpr().getRoot() instanceof FunctionNode);
CallParamContentNode cn2cpcn1 = (CallParamContentNode) cn2.getChild(1);
assertEquals("woo", cn2cpcn1.getKey().identifier());
assertEquals("poo", ((RawTextNode) cn2cpcn1.getChild(0)).getRawText());
}
use of com.google.template.soy.soytree.CallParamContentNode in project closure-templates by google.
the class SoyNodeCompiler method prepareParamsHelper.
private Expression prepareParamsHelper(CallNode node, Label reattachPoint) {
if (node.numChildren() == 0) {
// Easy, just use the data attribute
return getDataExpression(node, reattachPoint);
} else {
// Otherwise we need to build a dictionary from {param} statements.
Expression paramStoreExpression = getParamStoreExpression(node, reattachPoint);
for (CallParamNode child : node.getChildren()) {
String paramKey = child.getKey().identifier();
Expression valueExpr;
if (child instanceof CallParamContentNode) {
valueExpr = lazyClosureCompiler.compileLazyContent("param", (CallParamContentNode) child, paramKey);
} else {
valueExpr = lazyClosureCompiler.compileLazyExpression("param", child, paramKey, ((CallParamValueNode) child).getExpr());
}
// ParamStore.setField return 'this' so we can just chain the invocations together.
paramStoreExpression = MethodRef.PARAM_STORE_SET_FIELD.invoke(paramStoreExpression, BytecodeUtils.constant(paramKey), valueExpr);
}
return paramStoreExpression;
}
}
Aggregations