use of com.google.template.soy.soytree.SoyNode in project closure-templates by google.
the class SoyCodeForPySubject method compileBody.
private String compileBody() {
SoyNode node = SharedTestUtils.getNode(SoyFileSetParserBuilder.forTemplateContents(AutoEscapingType.STRICT, actual()).declaredSyntaxVersion(SyntaxVersion.V2_0).parse().fileSet(), 0);
// Setup the GenPyCodeVisitor's state before the node is visited.
try (GuiceSimpleScope.InScope inScope = enterScope()) {
GenPyCodeVisitor genPyCodeVisitor = PySrcMain.createVisitor(defaultOptions(), ImmutableMap.<String, String>of());
genPyCodeVisitor.pyCodeBuilder = new PyCodeBuilder();
genPyCodeVisitor.pyCodeBuilder.pushOutputVar("output");
genPyCodeVisitor.pyCodeBuilder.setOutputVarInited();
genPyCodeVisitor.localVarExprs = new LocalVariableStack();
genPyCodeVisitor.localVarExprs.pushFrame();
genPyCodeVisitor.genPyExprsVisitor = genPyCodeVisitor.genPyExprsVisitorFactory.create(genPyCodeVisitor.localVarExprs, ErrorReporter.exploding());
genPyCodeVisitor.visitForTesting(node, ErrorReporter.exploding());
return genPyCodeVisitor.pyCodeBuilder.getCode().replaceAll("([a-zA-Z]+)\\d+", "$1###");
}
}
use of com.google.template.soy.soytree.SoyNode in project closure-templates by google.
the class SoyExprForPySubject method compilesTo.
/**
* Asserts the subject compiles to the correct list of PyExprs.
*
* <p>The given Soy expr is wrapped in a full body of a template. The actual result is replaced
* with ids for ### so that tests don't break when ids change.
*
* @param expectedPyExprs the expected result of compilation
*/
public void compilesTo(List<PyExpr> expectedPyExprs) {
SoyFileSetNode soyTree = SoyFileSetParserBuilder.forTemplateContents(getSubject()).parse().fileSet();
SoyNode node = SharedTestUtils.getNode(soyTree, 0);
SharedTestUtils.simulateNewApiCall(injector, null, BidiGlobalDir.LTR);
final IsComputableAsPyExprVisitor isComputableAsPyExprs = new IsComputableAsPyExprVisitor();
// here we resolve it with a mutable field in a custom provider
class PyCallExprVisitorSupplier implements Supplier<GenPyCallExprVisitor> {
GenPyExprsVisitorFactory factory;
@Override
public GenPyCallExprVisitor get() {
return new GenPyCallExprVisitor(isComputableAsPyExprs, checkNotNull(factory));
}
}
PyCallExprVisitorSupplier provider = new PyCallExprVisitorSupplier();
GenPyExprsVisitorFactory genPyExprsFactory = new GenPyExprsVisitorFactory(isComputableAsPyExprs, provider);
provider.factory = genPyExprsFactory;
GenPyExprsVisitor genPyExprsVisitor = genPyExprsFactory.create(localVarExprs, ErrorReporter.exploding());
List<PyExpr> actualPyExprs = genPyExprsVisitor.exec(node);
assertThat(actualPyExprs).hasSize(expectedPyExprs.size());
for (int i = 0; i < expectedPyExprs.size(); i++) {
PyExpr expectedPyExpr = expectedPyExprs.get(i);
PyExpr actualPyExpr = actualPyExprs.get(i);
assertThat(actualPyExpr.getText().replaceAll("\\([0-9]+", "(###")).isEqualTo(expectedPyExpr.getText());
assertThat(actualPyExpr.getPrecedence()).isEqualTo(expectedPyExpr.getPrecedence());
}
}
use of com.google.template.soy.soytree.SoyNode in project closure-templates by google.
the class GenJsCodeVisitor method visitSwitchNode.
/**
* Example:
*
* <pre>
* {switch $boo}
* {case 0}
* ...
* {case 1, 2}
* ...
* {default}
* ...
* {/switch}
* </pre>
*
* might generate
*
* <pre>
* switch (opt_data.boo) {
* case 0:
* ...
* break;
* case 1:
* case 2:
* ...
* break;
* default:
* ...
* }
* </pre>
*/
@Override
protected void visitSwitchNode(SwitchNode node) {
CodeChunk.WithValue switchOn = coerceTypeForSwitchComparison(node.getExpr());
SwitchBuilder switchBuilder = switch_(switchOn);
for (SoyNode child : node.getChildren()) {
if (child instanceof SwitchCaseNode) {
SwitchCaseNode scn = (SwitchCaseNode) child;
ImmutableList.Builder<CodeChunk.WithValue> caseChunks = ImmutableList.builder();
for (ExprNode caseExpr : scn.getExprList()) {
CodeChunk.WithValue caseChunk = translateExpr(caseExpr);
caseChunks.add(caseChunk);
}
CodeChunk body = visitChildrenReturningCodeChunk(scn);
switchBuilder.case_(caseChunks.build(), body);
} else if (child instanceof SwitchDefaultNode) {
CodeChunk body = visitChildrenReturningCodeChunk((SwitchDefaultNode) child);
switchBuilder.default_(body);
} else {
throw new AssertionError();
}
}
jsCodeBuilder.append(switchBuilder.build());
}
use of com.google.template.soy.soytree.SoyNode 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)));
}
use of com.google.template.soy.soytree.SoyNode in project closure-templates by google.
the class CombineConsecutiveRawTextNodesPass method visit.
private void visit(ParentSoyNode<?> node) {
// The raw text node at the beginning of the current sequence
int start = -1;
int lastNonEmptyRawTextNode = -1;
int i = 0;
for (; i < node.numChildren(); i++) {
SoyNode child = node.getChild(i);
if (child instanceof RawTextNode) {
RawTextNode childAsRawText = (RawTextNode) child;
if (start == -1) {
// drop empty raw text nodes at the prefix
if (childAsRawText.getRawText().isEmpty()) {
node.removeChild(i);
i--;
} else {
// mark the beginning of a sequence of nonempty raw text
start = i;
lastNonEmptyRawTextNode = i;
}
} else {
if (!childAsRawText.getRawText().isEmpty()) {
lastNonEmptyRawTextNode = i;
}
}
} else {
i = mergeRange(node, start, lastNonEmptyRawTextNode, i);
// reset
start = -1;
if (child instanceof ParentSoyNode) {
// recurse
visit((ParentSoyNode<?>) child);
}
// else do nothing since it cannot contain raw text nodes
}
}
mergeRange(node, start, lastNonEmptyRawTextNode, i);
}
Aggregations