use of com.google.template.soy.soytree.IfCondNode in project closure-templates by google.
the class GenJsCodeVisitor method generateNonExpressionIfNode.
/**
* Generates the JavaScript code for an {if} block that cannot be done as an expression.
*
* <p>TODO(user): Instead of interleaving JsCodeBuilders like this, consider refactoring
* GenJsCodeVisitor to return CodeChunks for each sub-Template level SoyNode.
*/
protected void generateNonExpressionIfNode(IfNode node) {
ConditionalBuilder conditional = null;
for (SoyNode child : node.getChildren()) {
if (child instanceof IfCondNode) {
IfCondNode condNode = (IfCondNode) child;
// Convert predicate.
CodeChunk.WithValue predicate = translateExpr(condNode.getExpr());
// Convert body.
CodeChunk consequent = visitChildrenReturningCodeChunk(condNode);
// Add if-block to conditional.
if (conditional == null) {
conditional = ifStatement(predicate, consequent);
} else {
conditional.elseif_(predicate, consequent);
}
} else if (child instanceof IfElseNode) {
// Convert body.
CodeChunk trailingElse = visitChildrenReturningCodeChunk((IfElseNode) child);
// Add else-block to conditional.
conditional.else_(trailingElse);
} else {
throw new AssertionError();
}
}
jsCodeBuilder.append(conditional.build());
}
use of com.google.template.soy.soytree.IfCondNode in project closure-templates by google.
the class GenJsExprsVisitor method visitIfNode.
/**
* Example:
* <pre>
* {if $boo}
* AAA
* {elseif $foo}
* BBB
* {else}
* CCC
* {/if}
* </pre>
* might generate
* <pre>
* (opt_data.boo) ? AAA : (opt_data.foo) ? BBB : CCC
* </pre>
*/
@Override
protected void visitIfNode(IfNode node) {
// Create another instance of this visitor class for generating JS expressions from children.
GenJsExprsVisitor genJsExprsVisitor = genJsExprsVisitorFactory.create(translationContext, templateAliases, errorReporter);
CodeChunk.Generator generator = translationContext.codeGenerator();
List<CodeChunk.WithValue> ifs = new ArrayList<>();
List<CodeChunk.WithValue> thens = new ArrayList<>();
CodeChunk.WithValue trailingElse = null;
for (SoyNode child : node.getChildren()) {
if (child instanceof IfCondNode) {
IfCondNode ifCond = (IfCondNode) child;
ifs.add(translateExpr(ifCond.getExpr()));
thens.add(CodeChunkUtils.concatChunks(genJsExprsVisitor.exec(ifCond)));
} else if (child instanceof IfElseNode) {
trailingElse = CodeChunkUtils.concatChunks(genJsExprsVisitor.exec(child));
} else {
throw new AssertionError();
}
}
Preconditions.checkState(ifs.size() == thens.size());
ConditionalExpressionBuilder builder = CodeChunk.ifExpression(ifs.get(0), thens.get(0));
for (int i = 1; i < ifs.size(); i++) {
builder.elseif_(ifs.get(i), thens.get(i));
}
CodeChunk.WithValue ifChunk = trailingElse != null ? builder.else_(trailingElse).build(generator) : builder.else_(LITERAL_EMPTY_STRING).build(generator);
chunks.add(ifChunk);
}
use of com.google.template.soy.soytree.IfCondNode in project closure-templates by google.
the class ResolveExpressionTypesVisitor method visitIfNode.
@Override
protected void visitIfNode(IfNode node) {
// TODO(user): Also support switch / case.
TypeSubstitution savedSubstitutionState = substitutions;
for (SoyNode child : node.getChildren()) {
if (child instanceof IfCondNode) {
IfCondNode icn = (IfCondNode) child;
visitExpressions(icn);
// Visit the conditional expression to compute which types can be narrowed.
TypeNarrowingConditionVisitor visitor = new TypeNarrowingConditionVisitor();
visitor.exec(icn.getExpr());
// Save the state of substitutions from the previous if block.
TypeSubstitution previousSubstitutionState = substitutions;
// Modify the current set of type substitutions for the 'true' branch
// of the if statement.
addTypeSubstitutions(visitor.positiveTypeConstraints);
visitChildren(icn);
// Rewind the substitutions back to the state before the if-condition.
// Add in the negative substitutions, which will affect subsequent blocks
// of the if statement.
// So for example if we have a variable whose type is (A|B|C) and the
// first if-block tests whether that variable is type A, then in the
// 'else' block it must be of type (B|C); If a subsequent 'elseif'
// statement tests whether it's type B, then in the following else block
// it can only be of type C.
substitutions = previousSubstitutionState;
addTypeSubstitutions(visitor.negativeTypeConstraints);
} else if (child instanceof IfElseNode) {
// For the else node, we simply inherit the previous set of subsitutions.
IfElseNode ien = (IfElseNode) child;
visitChildren(ien);
}
}
substitutions = savedSubstitutionState;
}
use of com.google.template.soy.soytree.IfCondNode in project closure-templates by google.
the class ContentSecurityPolicyNonceInjectionPass method createCspInjection.
/**
* Generates an AST fragment that looks like: {if $ij.csp_nonce}nonce="{$ij.csp_nonce}"{/if}
*
* @param insertionLocation The location where it is being inserted
* @param nodeIdGen The id generator to use
*/
private static IfNode createCspInjection(SourceLocation insertionLocation, IdGenerator nodeIdGen) {
IfNode ifNode = new IfNode(nodeIdGen.genId(), insertionLocation);
IfCondNode ifCondNode = new IfCondNode(nodeIdGen.genId(), insertionLocation, "if", referenceCspNonce(insertionLocation));
ifNode.addChild(ifCondNode);
HtmlAttributeNode nonceAttribute = new HtmlAttributeNode(nodeIdGen.genId(), insertionLocation, insertionLocation.getBeginPoint());
ifCondNode.addChild(nonceAttribute);
nonceAttribute.addChild(new RawTextNode(nodeIdGen.genId(), "nonce", insertionLocation));
HtmlAttributeValueNode attributeValue = new HtmlAttributeValueNode(nodeIdGen.genId(), insertionLocation, HtmlAttributeValueNode.Quotes.DOUBLE);
nonceAttribute.addChild(attributeValue);
// NOTE: we do not need to insert any print directives here, unlike the old implementation since
// we are running before the autoescaper, so the escaper should insert whatever print directives
// are appropriate.
PrintNode printNode = new PrintNode(nodeIdGen.genId(), insertionLocation, // Implicit. {$ij.csp_nonce} not {print $ij.csp_nonce}
true, /* isImplicit= */
referenceCspNonce(insertionLocation), /* attributes= */
ImmutableList.of(), ErrorReporter.exploding());
attributeValue.addChild(printNode);
return ifNode;
}
use of com.google.template.soy.soytree.IfCondNode in project closure-templates by google.
the class TemplateParserTest method testParseIfStmt.
@Test
public void testParseIfStmt() throws Exception {
String templateBody = "{@param zoo : ?}{@param boo: ?}{@param foo : ?}{@param moo : ?}\n" + " {if $zoo}{$zoo}{/if}\n" + " {if $boo}\n" + " Blah\n" + " {elseif $foo.goo > 2}\n" + " {$moo}\n" + " {else}\n" + " Blah {$moo}\n" + " {/if}\n";
List<StandaloneNode> nodes = parseTemplateContent(templateBody, FAIL).getChildren();
assertEquals(2, nodes.size());
IfNode in0 = (IfNode) nodes.get(0);
assertEquals(1, in0.numChildren());
IfCondNode in0icn0 = (IfCondNode) in0.getChild(0);
assertEquals("$zoo", in0icn0.getExpr().toSourceString());
assertEquals(1, in0icn0.numChildren());
assertEquals("$zoo", ((PrintNode) in0icn0.getChild(0)).getExpr().toSourceString());
assertTrue(in0icn0.getExpr().getRoot() instanceof VarRefNode);
IfNode in1 = (IfNode) nodes.get(1);
assertEquals(3, in1.numChildren());
IfCondNode in1icn0 = (IfCondNode) in1.getChild(0);
assertEquals("$boo", in1icn0.getExpr().toSourceString());
assertTrue(in1icn0.getExpr().getRoot() instanceof VarRefNode);
IfCondNode in1icn1 = (IfCondNode) in1.getChild(1);
assertEquals("$foo.goo > 2", in1icn1.getExpr().toSourceString());
assertTrue(in1icn1.getExpr().getRoot() instanceof GreaterThanOpNode);
assertEquals("{if $boo}Blah{elseif $foo.goo > 2}{$moo}{else}Blah {$moo}{/if}", in1.toSourceString());
}
Aggregations