use of com.google.template.soy.soytree.CallNode in project closure-templates by google.
the class MsgFuncGenerator method collectVarNameListAndToPyExprMap.
/**
* Private helper to process and collect all variables used within this msg node for code
* generation.
*
* @return A Map populated with all the variables used with in this message node, using {@link
* MsgPlaceholderInitialNode#genBasePhName}.
*/
private Map<PyExpr, PyExpr> collectVarNameListAndToPyExprMap() {
Map<PyExpr, PyExpr> nodePyVarToPyExprMap = new LinkedHashMap<>();
for (Map.Entry<String, MsgSubstUnitNode> entry : msgNode.getVarNameToRepNodeMap().entrySet()) {
MsgSubstUnitNode substUnitNode = entry.getValue();
PyExpr substPyExpr = null;
if (substUnitNode instanceof MsgPlaceholderNode) {
SoyNode phInitialNode = ((AbstractParentSoyNode<?>) substUnitNode).getChild(0);
if (phInitialNode instanceof PrintNode || phInitialNode instanceof CallNode || phInitialNode instanceof RawTextNode) {
substPyExpr = PyExprUtils.concatPyExprs(genPyExprsVisitor.exec(phInitialNode)).toPyString();
}
// when the placeholder is generated by HTML tags
if (phInitialNode instanceof MsgHtmlTagNode) {
substPyExpr = PyExprUtils.concatPyExprs(genPyExprsVisitor.execOnChildren((ParentSoyNode<?>) phInitialNode)).toPyString();
}
} else if (substUnitNode instanceof MsgPluralNode) {
// Translates {@link MsgPluralNode#pluralExpr} into a Python lookup expression.
// Note that {@code pluralExpr} represents the soy expression of the {@code plural} attr,
// i.e. the {@code $numDrafts} in {@code {plural $numDrafts}...{/plural}}.
substPyExpr = translateToPyExprVisitor.exec(((MsgPluralNode) substUnitNode).getExpr());
} else if (substUnitNode instanceof MsgSelectNode) {
substPyExpr = translateToPyExprVisitor.exec(((MsgSelectNode) substUnitNode).getExpr());
}
if (substPyExpr != null) {
nodePyVarToPyExprMap.put(new PyStringExpr("'" + entry.getKey() + "'"), substPyExpr);
}
}
return nodePyVarToPyExprMap;
}
use of com.google.template.soy.soytree.CallNode in project closure-templates by google.
the class GenJsCodeVisitorAssistantForMsgs method genGoogMsgPlaceholder.
/**
* Returns a code chunk for the given placeholder node.
*/
protected CodeChunk.WithValue genGoogMsgPlaceholder(MsgPlaceholderNode msgPhNode) {
List<CodeChunk.WithValue> contentChunks = new ArrayList<>();
for (StandaloneNode contentNode : msgPhNode.getChildren()) {
if (contentNode instanceof MsgHtmlTagNode && !isComputableAsJsExprsVisitor.exec(contentNode)) {
// This is a MsgHtmlTagNode that is not computable as JS expressions. Visit it to
// generate code to define the 'htmlTag<n>' variable.
visit(contentNode);
contentChunks.add(id("htmlTag" + contentNode.getId()));
} else if (contentNode instanceof CallNode) {
// If the CallNode has any CallParamContentNode children that are not computable as JS
// expressions, visit them to generate code to define their respective 'param<n>' variables.
CallNode callNode = (CallNode) contentNode;
for (CallParamNode grandchild : callNode.getChildren()) {
if (grandchild instanceof CallParamContentNode && !isComputableAsJsExprsVisitor.exec(grandchild)) {
visit(grandchild);
}
}
CodeChunk.WithValue call = genCallCodeUtils.gen(callNode, templateAliases, translationContext, errorReporter);
contentChunks.add(call);
} else {
List<CodeChunk.WithValue> chunks = genJsExprsVisitor.exec(contentNode);
contentChunks.add(CodeChunkUtils.concatChunks(chunks));
}
}
return CodeChunkUtils.concatChunks(contentChunks);
}
use of com.google.template.soy.soytree.CallNode in project closure-templates by google.
the class MsgCompiler method putPlaceholderIntoMap.
private void putPlaceholderIntoMap(Expression mapExpression, MsgNode originalMsg, Map<String, Statement> placeholderNameToPutStatement, SoyMsgPlaceholderPart placeholder) throws AssertionError {
String placeholderName = placeholder.getPlaceholderName();
if (!placeholderNameToPutStatement.containsKey(placeholderName)) {
MsgPlaceholderNode repPlaceholderNode = originalMsg.getRepPlaceholderNode(placeholder.getPlaceholderName());
if (repPlaceholderNode.numChildren() == 0) {
throw new IllegalStateException("empty rep node for: " + placeholderName);
}
StandaloneNode initialNode = repPlaceholderNode.getChild(0);
Statement putEntyInMap;
if (initialNode instanceof MsgHtmlTagNode) {
putEntyInMap = addHtmlTagNodeToPlaceholderMap(mapExpression, placeholderName, (MsgHtmlTagNode) initialNode);
} else if (initialNode instanceof CallNode) {
putEntyInMap = addCallNodeToPlaceholderMap(mapExpression, placeholderName, (CallNode) initialNode);
} else if (initialNode instanceof PrintNode) {
putEntyInMap = addPrintNodeToPlaceholderMap(mapExpression, placeholderName, (PrintNode) initialNode);
} else if (initialNode instanceof RawTextNode) {
putEntyInMap = addRawTextNodeToPlaceholderMap(mapExpression, placeholderName, (RawTextNode) initialNode);
} else {
// the AST for MsgNodes guarantee that these are the only options
throw new AssertionError("Unexpected child: " + initialNode.getClass());
}
placeholderNameToPutStatement.put(placeholder.getPlaceholderName(), putEntyInMap.withSourceLocation(repPlaceholderNode.getSourceLocation()));
}
}
use of com.google.template.soy.soytree.CallNode in project closure-templates by google.
the class ContextualAutoescaperTest method testStrictModeEscapesCallSites.
@Test
public void testStrictModeEscapesCallSites() {
String source = "{namespace ns}\n\n" + "{template .main}\n" + "{call .htmltemplate /}" + "<script>var x={call .htmltemplate /};</script>\n" + "<script>var x={call .jstemplate /};</script>\n" + "{call .externtemplate /}" + "\n{/template}\n\n" + "{template .htmltemplate}\n" + "Hello World" + "\n{/template}\n\n" + "{template .jstemplate kind=\"js\"}\n" + "foo()" + "\n{/template}";
TemplateNode mainTemplate = rewrite(source).getChild(0);
assertWithMessage("Sanity check").that(mainTemplate.getTemplateName()).isEqualTo("ns.main");
final List<CallNode> callNodes = SoyTreeUtils.getAllNodesOfType(mainTemplate, CallNode.class);
assertThat(callNodes).hasSize(4);
assertWithMessage("HTML->HTML escaping should be pruned").that(callNodes.get(0).getEscapingDirectives()).isEmpty();
assertWithMessage("JS -> HTML call should be escaped").that(getDirectiveNames(callNodes.get(1).getEscapingDirectives())).containsExactly("|escapeJsValue");
assertWithMessage("JS -> JS pruned").that(callNodes.get(2).getEscapingDirectives()).isEmpty();
assertWithMessage("HTML -> extern call should be escaped").that(getDirectiveNames(callNodes.get(3).getEscapingDirectives())).containsExactly("|escapeHtml");
}
use of com.google.template.soy.soytree.CallNode in project closure-templates by google.
the class ContextualAutoescaperTest method testStrictModeOptimizesDelegates.
@Test
public void testStrictModeOptimizesDelegates() {
String source = "{namespace ns}\n\n" + "{template .main}\n" + "{delcall ns.delegateHtml /}" + "{delcall ns.delegateText /}" + "\n{/template}\n\n" + "/** A delegate returning HTML. */\n" + "{deltemplate ns.delegateHtml}\n" + "Hello World" + "\n{/deltemplate}\n\n" + "/** A delegate returning JS. */\n" + "{deltemplate ns.delegateText kind=\"text\"}\n" + "Hello World" + "\n{/deltemplate}";
TemplateNode mainTemplate = rewrite(source).getChild(0);
assertWithMessage("Sanity check").that(mainTemplate.getTemplateName()).isEqualTo("ns.main");
final List<CallNode> callNodes = SoyTreeUtils.getAllNodesOfType(mainTemplate, CallNode.class);
assertThat(callNodes).hasSize(2);
assertWithMessage("We're compiling a complete set; we can optimize based on usages.").that(callNodes.get(0).getEscapingDirectives()).isEmpty();
assertWithMessage("HTML -> TEXT requires escaping").that(getDirectiveNames(callNodes.get(1).getEscapingDirectives())).containsExactly("|escapeHtml");
}
Aggregations