use of com.google.template.soy.soytree.SoyNode in project closure-templates by google.
the class CanInitOutputVarVisitorTest method runTestHelper.
/**
* @param indicesToNode Series of indices for walking down to the node we want to test.
*/
private static void runTestHelper(String soyCode, boolean isSameValueAsIsComputableAsJsExprsVisitor, int... indicesToNode) {
ErrorReporter boom = ErrorReporter.exploding();
SoyFileSetNode soyTree = SoyFileSetParserBuilder.forTemplateContents(soyCode).errorReporter(boom).parse().fileSet();
SoyNode node = SharedTestUtils.getNode(soyTree, indicesToNode);
IsComputableAsJsExprsVisitor icajev = new IsComputableAsJsExprsVisitor();
CanInitOutputVarVisitor ciovv = new CanInitOutputVarVisitor(icajev);
assertThat(ciovv.exec(node).equals(icajev.exec(node))).isEqualTo(isSameValueAsIsComputableAsJsExprsVisitor);
}
use of com.google.template.soy.soytree.SoyNode in project closure-templates by google.
the class GenJsCodeVisitorTest method assertGeneratedJsCode.
// -----------------------------------------------------------------------------------------------
// Helpers.
/**
* @param soyCode The soy code.
* @param expectedJsCode JavaScript code expected to be generated from the Soy code.
*/
private void assertGeneratedJsCode(String soyCode, String expectedJsCode) {
ParseResult parseResult = SoyFileSetParserBuilder.forTemplateContents(soyCode).allowUnboundGlobals(true).parse();
TemplateNode templateNode = parseResult.fileSet().getChild(0).getChild(0);
// Setup the GenJsCodeVisitor's state before the node is visited.
genJsCodeVisitor.jsCodeBuilder = new JsCodeBuilder();
genJsCodeVisitor.jsCodeBuilder.pushOutputVar("output");
genJsCodeVisitor.jsCodeBuilder.setOutputVarInited();
UniqueNameGenerator nameGenerator = JsSrcNameGenerators.forLocalVariables();
CodeChunk.Generator codeGenerator = CodeChunk.Generator.create(nameGenerator);
TranslationContext translationContext = TranslationContext.of(SoyToJsVariableMappings.startingWith(LOCAL_VAR_TRANSLATIONS), codeGenerator, nameGenerator);
genJsCodeVisitor.templateTranslationContext = translationContext;
genJsCodeVisitor.genJsExprsVisitor = JsSrcTestUtils.createGenJsExprsVisitorFactory().create(translationContext, TEMPLATE_ALIASES, ErrorReporter.exploding());
// will be created when used
genJsCodeVisitor.assistantForMsgs = null;
for (SoyNode child : templateNode.getChildren()) {
genJsCodeVisitor.visitForTesting(child, parseResult.registry(), ErrorReporter.exploding());
}
String genCode = genJsCodeVisitor.jsCodeBuilder.getCode();
assertThat(genCode).isEqualTo(expectedJsCode);
}
use of com.google.template.soy.soytree.SoyNode in project closure-templates by google.
the class GenJsCodeVisitor method visitChildren.
@Override
protected void visitChildren(ParentSoyNode<?> node) {
// initialize the output var.
if (node.numChildren() == 0 || !canInitOutputVarVisitor.exec(node.getChild(0))) {
jsCodeBuilder.initOutputVarIfNecessary();
}
// For children that are computed by GenJsExprsVisitor, try to process as many of them as we can
// before adding to outputVar.
//
// output += 'a' + 'b';
// is preferable to
// output += 'a';
// output += 'b';
// This is because it is actually easier for the jscompiler to optimize.
List<CodeChunk.WithValue> consecChunks = new ArrayList<>();
for (SoyNode child : node.getChildren()) {
if (isComputableAsJsExprsVisitor.exec(child)) {
consecChunks.addAll(genJsExprsVisitor.exec(child));
} else {
if (!consecChunks.isEmpty()) {
jsCodeBuilder.addChunksToOutputVar(consecChunks);
consecChunks.clear();
}
visit(child);
}
}
if (!consecChunks.isEmpty()) {
jsCodeBuilder.addChunksToOutputVar(consecChunks);
consecChunks.clear();
}
}
use of com.google.template.soy.soytree.SoyNode 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.SoyNode 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);
}
Aggregations