use of com.google.template.soy.exprtree.IntegerNode 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.IntegerNode 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.IntegerNode in project closure-templates by google.
the class RewriteGlobalsPass method resolveGlobal.
private void resolveGlobal(GlobalNode global) {
// First check to see if this global matches a proto enum. We do this because the enums from
// the type registry have better type information and for applications with legacy globals
// configs there is often overlap, so the order in which we check is actually important.
// proto enums are dotted identifiers
String name = global.getName();
int lastDot = name.lastIndexOf('.');
if (lastDot > 0) {
String enumTypeName = name.substring(0, lastDot);
SoyType type = typeRegistry.getType(enumTypeName);
if (type != null && type.getKind() == SoyType.Kind.PROTO_ENUM) {
SoyProtoEnumType enumType = (SoyProtoEnumType) type;
String enumMemberName = name.substring(lastDot + 1);
Integer enumValue = enumType.getValue(enumMemberName);
if (enumValue != null) {
// TODO(lukes): consider introducing a new PrimitiveNode for enums
global.resolve(enumType, new IntegerNode(enumValue, global.getSourceLocation()));
} else {
// If we found the type definition but not the value, then that's an error
// regardless of whether we're allowing unbound globals or not.
errorReporter.report(global.getSourceLocation(), ENUM_MEMBERSHIP_ERROR, enumMemberName, enumTypeName);
}
// TODO(lukes): issue a warning if a registered global also matches
return;
}
}
// if that doesn't work, see if it was registered in the globals file.
PrimitiveData value = compileTimeGlobals.get(global.getName());
if (value != null) {
PrimitiveNode expr = InternalValueUtils.convertPrimitiveDataToExpr(value, global.getSourceLocation());
global.resolve(expr.getType(), expr);
}
}
use of com.google.template.soy.exprtree.IntegerNode in project closure-templates by google.
the class TemplateDelegateNode method resolveVariantExpression.
/**
* Calculate a DeltemplateKey for the variant.
*
* <p>This is done lazily so that global references can be resolved. This is not ideal since
* nothing guarantees that resolution happens before access.
*
* <p>Note we don't do validation of the variant values since that is handled by the
* TemplateDelegateNodeBuilder during construction
*/
private DelTemplateKey resolveVariantExpression() {
if (delTemplateVariantExpr == null) {
delTemplateKey = DelTemplateKey.create(delTemplateName, "");
return delTemplateKey;
}
ExprNode exprNode = delTemplateVariantExpr.getRoot();
if (exprNode instanceof GlobalNode) {
GlobalNode globalNode = (GlobalNode) exprNode;
if (globalNode.isResolved()) {
exprNode = globalNode.getValue();
} else {
// For this reason we also don't store the key, instead we just return it.
return DelTemplateKey.create(delTemplateName, globalNode.getName());
}
}
if (exprNode instanceof IntegerNode) {
// Globals were already substituted: We may now create the definitive variant and key fields
// on this node.
long variantValue = ((IntegerNode) exprNode).getValue();
delTemplateKey = DelTemplateKey.create(delTemplateName, String.valueOf(variantValue));
} else if (exprNode instanceof StringNode) {
// Globals were already substituted: We may now create the definitive variant and key fields
// on this node.
delTemplateKey = DelTemplateKey.create(delTemplateName, ((StringNode) exprNode).getValue());
} else {
// We must have already reported an error, just create an arbitrary variant expr.
delTemplateKey = DelTemplateKey.create(delTemplateName, exprNode.toSourceString());
}
return delTemplateKey;
}
use of com.google.template.soy.exprtree.IntegerNode in project closure-templates by google.
the class MsgSubstUnitBaseVarNameUtils method genCandidateBaseNamesForExpr.
/**
* Private helper for {@code genShortestBaseNameForExpr()} and {@code
* genNoncollidingBaseNamesForExprs()}.
*
* <p>Given an expression that's a data ref or a global, generates the list of all possible base
* names, from short to long. Shortest contains only the last key. Longest contains up to the
* first key (unless there are accesses using expressions to compute non-static keys, in which
* case we cannot generate any more base names). If no base names can be generated for the given
* expression (i.e. if the expression is not a data ref or global, or the last key is non-static),
* then returns empty list.
*
* <p>For example, given $aaa[0].bbb.cccDdd, generates the list ["CCC_DDD", "BBB_CCC_DDD",
* "AAA_0_BBB_CCC_DDD"]. One the other hand, given $aaa['xxx'], generates the empty list (because
* ['xxx'] parses to a DataRefAccessExprNode).
*
* @param exprNode The expr root of the expression to generate all candidate base names for.
* @return The list of all candidate base names, from shortest to longest.
*/
@VisibleForTesting
static List<String> genCandidateBaseNamesForExpr(ExprNode exprNode) {
if (exprNode instanceof VarRefNode || exprNode instanceof DataAccessNode) {
List<String> baseNames = Lists.newArrayList();
String baseName = null;
while (exprNode != null) {
String nameSegment = null;
if (exprNode instanceof VarRefNode) {
nameSegment = ((VarRefNode) exprNode).getName();
exprNode = null;
} else if (exprNode instanceof FieldAccessNode) {
FieldAccessNode fieldAccess = (FieldAccessNode) exprNode;
nameSegment = fieldAccess.getFieldName();
exprNode = fieldAccess.getBaseExprChild();
} else if (exprNode instanceof ItemAccessNode) {
ItemAccessNode itemAccess = (ItemAccessNode) exprNode;
exprNode = itemAccess.getBaseExprChild();
if (itemAccess.getKeyExprChild() instanceof IntegerNode) {
// Prefix with index, but don't add to baseNames list since it's not a valid ident.
IntegerNode keyValue = (IntegerNode) itemAccess.getKeyExprChild();
if (keyValue.getValue() < 0) {
// Stop if we encounter an invalid key.
break;
}
nameSegment = Long.toString(keyValue.getValue());
baseName = BaseUtils.convertToUpperUnderscore(nameSegment) + ((baseName != null) ? "_" + baseName : "");
continue;
} else {
// Stop if we encounter a non-static key
break;
}
} else {
// Stop if we encounter an expression that is not representable as a name.
break;
}
baseName = BaseUtils.convertToUpperUnderscore(nameSegment) + ((baseName != null) ? "_" + baseName : "");
// new candidate base name whenever we encounter a key
baseNames.add(baseName);
}
return baseNames;
} else if (exprNode instanceof GlobalNode) {
String[] globalNameParts = ((GlobalNode) exprNode).getName().split("\\.");
List<String> baseNames = Lists.newArrayList();
String baseName = null;
for (int i = globalNameParts.length - 1; i >= 0; i--) {
baseName = BaseUtils.convertToUpperUnderscore(globalNameParts[i]) + ((baseName != null) ? "_" + baseName : "");
baseNames.add(baseName);
}
return baseNames;
} else {
// We don't handle expressions other than data refs and globals.
return ImmutableList.of();
}
}
Aggregations