use of com.google.template.soy.soytree.SoyNode in project closure-templates by google.
the class ExtractMsgsVisitor method execOnMultipleNodes.
/**
* Returns a SoyMsgBundle containing all messages extracted from the given nodes (locale string is
* null).
*/
public SoyMsgBundle execOnMultipleNodes(Iterable<? extends SoyNode> nodes) {
msgs = Lists.newArrayList();
for (SoyNode node : nodes) {
visit(node);
}
Collections.sort(msgs, SOURCE_LOCATION_ORDERING);
return new SoyMsgBundleImpl(null, msgs);
}
use of com.google.template.soy.soytree.SoyNode in project closure-templates by google.
the class SoyNodeCompiler method visitSwitchNode.
@Override
protected Statement visitSwitchNode(SwitchNode node) {
// A few special cases:
// 1. only a {default} block. In this case we can skip all the switch logic and temporaries
// 2. no children. Just return the empty statement
// Note that in both of these cases we do not evalutate (or generate code) for the switch
// expression.
List<BlockNode> children = node.getChildren();
if (children.isEmpty()) {
return Statement.NULL_STATEMENT;
}
if (children.size() == 1 && children.get(0) instanceof SwitchDefaultNode) {
return visitChildrenInNewScope(children.get(0));
}
// otherwise we need to evaluate the switch variable and generate dispatching logic.
SoyExpression switchVar = exprCompiler.compile(node.getExpr());
Scope scope = variables.enterScope();
Variable variable = scope.createSynthetic(SyntheticVarName.forSwitch(node), switchVar, STORE);
Statement initializer = variable.initializer();
switchVar = switchVar.withSource(variable.local());
List<IfBlock> cases = new ArrayList<>();
Optional<Statement> defaultBlock = Optional.absent();
for (SoyNode child : children) {
if (child instanceof SwitchCaseNode) {
SwitchCaseNode caseNode = (SwitchCaseNode) child;
Label reattachPoint = new Label();
List<Expression> comparisons = new ArrayList<>();
for (ExprRootNode caseExpr : caseNode.getExprList()) {
comparisons.add(compareSoyEquals(switchVar, exprCompiler.compile(caseExpr, reattachPoint)));
}
Expression condition = BytecodeUtils.logicalOr(comparisons).labelStart(reattachPoint);
Statement block = visitChildrenInNewScope(caseNode);
cases.add(IfBlock.create(condition, block));
} else {
SwitchDefaultNode defaultNode = (SwitchDefaultNode) child;
defaultBlock = Optional.of(visitChildrenInNewScope(defaultNode));
}
}
Statement exitScope = scope.exitScope();
// generation that we could maybe use
return Statement.concat(initializer, ControlFlow.ifElseChain(cases, defaultBlock), exitScope);
}
use of com.google.template.soy.soytree.SoyNode 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.SoyNode 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.SoyNode in project closure-templates by google.
the class RewriteGlobalsPassTest method testResolveAlias.
@Test
public void testResolveAlias() {
String template = "" + "{namespace ns}\n" + "\n" + "{alias foo.bar.baz as global}\n" + "{alias global.with.sugar}\n" + "\n" + "{template .t}\n" + " {global}\n" + " {global.with.field}\n" + " {sugar}\n" + " {sugar.with.field}\n" + " {unregistered}\n" + "{/template}";
SoyFileSetNode soytree = SoyFileSetParserBuilder.forFileContents(template).allowUnboundGlobals(true).parse().fileSet();
ImmutableList.Builder<String> actual = ImmutableList.builder();
for (SoyNode child : soytree.getChild(0).getChild(0).getChildren()) {
actual.add(child.toSourceString());
}
assertThat(actual.build()).containsExactly("{foo.bar.baz}", "{foo.bar.baz.with.field}", "{global.with.sugar}", "{global.with.sugar.with.field}", "{unregistered}").inOrder();
}
Aggregations