use of com.google.template.soy.exprtree.FunctionNode in project closure-templates by google.
the class VeLogInstrumentationVisitor method visitVeLogNode.
/**
* Adds data-soylog attribute to the top-level DOM node in this {velog} block.
*/
@Override
protected void visitVeLogNode(VeLogNode node) {
// VeLogValidationPass enforces that the first child is a open tag. We can safely cast it here.
HtmlOpenTagNode tag = (HtmlOpenTagNode) node.getChild(0);
SourceLocation insertionLocation = tag.getSourceLocation().getEndPoint().offset(0, tag.isSelfClosing() ? -2 : -1).asLocation(tag.getSourceLocation().getFilePath());
FunctionNode funcNode = new FunctionNode(VeLogFunction.INSTANCE, insertionLocation);
funcNode.addChild(new IntegerNode(node.getLoggingId(), insertionLocation));
funcNode.addChild(node.getConfigExpression() == null ? new NullNode(insertionLocation) : node.getConfigExpression().copy(new CopyState()));
if (node.getLogonlyExpression() != null) {
funcNode.addChild(node.getLogonlyExpression().copy(new CopyState()));
}
PrintNode attributeNode = new PrintNode(nodeIdGen.genId(), insertionLocation, /* isImplicit= */
true, /* expr= */
funcNode, /* attributes= */
ImmutableList.of(), ErrorReporter.exploding());
tag.addChild(attributeNode);
visitChildren(node);
}
use of com.google.template.soy.exprtree.FunctionNode in project closure-templates by google.
the class SoyNodeCompiler method visitPrintNode.
@Override
protected Statement visitPrintNode(PrintNode node) {
if (node.getExpr().getRoot() instanceof FunctionNode) {
FunctionNode fn = (FunctionNode) node.getExpr().getRoot();
if (fn.getSoyFunction() instanceof LoggingFunction) {
return visitLoggingFunction(node, fn, (LoggingFunction) fn.getSoyFunction());
}
}
// evaluates to a SoyValueProvider. This will allow us to render incrementally.
if (areAllPrintDirectivesStreamable(node)) {
Label reattachPoint = new Label();
ExprRootNode expr = node.getExpr();
Optional<Expression> asSoyValueProvider = expressionToSoyValueProviderCompiler.compileAvoidingBoxing(expr, reattachPoint);
if (asSoyValueProvider.isPresent()) {
return renderIncrementally(asSoyValueProvider.get(), node.getChildren(), reattachPoint);
}
}
// otherwise we need to apply some non-streaming print directives, or the expression would
// require boxing to be a print directive (which usually means it is quite trivial).
Label reattachPoint = new Label();
SoyExpression value = compilePrintNodeAsExpression(node, reattachPoint);
// TODO(lukes): call value.render?
AppendableExpression renderSoyValue = appendableExpression.appendString(value.coerceToString()).labelStart(reattachPoint);
Statement stmt;
if (shouldCheckBuffer(node)) {
stmt = detachState.detachLimited(renderSoyValue);
} else {
stmt = renderSoyValue.toStatement();
}
return stmt;
}
use of com.google.template.soy.exprtree.FunctionNode in project closure-templates by google.
the class SoyNodeCompiler method shouldCheckBuffer.
/**
* Returns true if the print expression should check the rendering buffer and generate a detach.
*
* <p>We do not generate detaches for css() and xid() builtin functions, since they are typically
* very short.
*/
private static boolean shouldCheckBuffer(PrintNode node) {
if (!(node.getExpr().getRoot() instanceof FunctionNode)) {
return true;
}
FunctionNode fn = (FunctionNode) node.getExpr().getRoot();
if (!(fn.getSoyFunction() instanceof BuiltinFunction)) {
return true;
}
BuiltinFunction bfn = (BuiltinFunction) fn.getSoyFunction();
if (bfn != BuiltinFunction.XID && bfn != BuiltinFunction.CSS) {
return true;
}
return false;
}
use of com.google.template.soy.exprtree.FunctionNode in project closure-templates by google.
the class MsgIdFunctionPass method handleMsgIdCall.
/**
* Rewrites calls to msgId($msgVar) to either a static constant message id or a conditional if
* there is a fallback.
*/
private void handleMsgIdCall(FunctionNode fn, MsgFallbackGroupNode msgNode) {
ExprNode replacement;
long primaryMsgId = MsgUtils.computeMsgIdForDualFormat(msgNode.getChild(0));
if (msgNode.numChildren() == 1) {
// easy peasy
replacement = createMsgIdNode(primaryMsgId, fn.getSourceLocation());
} else {
long fallbackMsgId = MsgUtils.computeMsgIdForDualFormat(msgNode.getChild(1));
ConditionalOpNode condOpNode = new ConditionalOpNode(fn.getSourceLocation());
FunctionNode isPrimaryMsgInUse = new FunctionNode(BuiltinFunction.IS_PRIMARY_MSG_IN_USE, fn.getSourceLocation());
// We add the varRef, and the 2 message ids to the funcitonnode as arguments so they are
// trivial to access in the backends. This is a little hacky however since we never generate
// code for these things.
// We could formalize the hack by providing a way to stash arbitrary data in the FunctionNode
// and then just pack this up in a non-AST datastructure.
isPrimaryMsgInUse.addChild(fn.getChild(0));
isPrimaryMsgInUse.addChild(new IntegerNode(primaryMsgId, fn.getSourceLocation()));
isPrimaryMsgInUse.addChild(new IntegerNode(fallbackMsgId, fn.getSourceLocation()));
condOpNode.addChild(isPrimaryMsgInUse);
condOpNode.addChild(createMsgIdNode(primaryMsgId, fn.getSourceLocation()));
condOpNode.addChild(createMsgIdNode(fallbackMsgId, fn.getSourceLocation()));
replacement = condOpNode;
}
fn.getParent().replaceChild(fn, replacement);
}
use of com.google.template.soy.exprtree.FunctionNode in project closure-templates by google.
the class XidPass method run.
@Override
public void run(SoyFileNode file, IdGenerator nodeIdGen) {
for (FunctionNode fn : SoyTreeUtils.getAllNodesOfType(file, FunctionNode.class)) {
if (fn.getSoyFunction() == BuiltinFunction.XID) {
if (fn.numChildren() != 1) {
// if it isn't == 1, then an error has already been reported, move along.
continue;
}
ExprNode child = fn.getChild(0);
switch(child.getKind()) {
case GLOBAL_NODE:
GlobalNode global = (GlobalNode) child;
if (global.isResolved()) {
// This doesn't have to be an error. but it is confusing if it is is since it is
// unclear if the user intended to xid the identifier or the value.
reporter.report(global.getSourceLocation(), GLOBAL_XID_ARG_IS_RESOLVED, global.getType().toString(), global.getValue().toSourceString());
}
fn.replaceChild(0, new StringNode(global.getName(), QuoteStyle.SINGLE, global.getSourceLocation()));
break;
case STRING_NODE:
break;
default:
reporter.report(child.getSourceLocation(), STRING_OR_GLOBAL_REQUIRED);
}
}
}
}
Aggregations