use of com.google.template.soy.exprtree.VarRefNode in project closure-templates by google.
the class ExpressionCompilerTest method createTemplateBody.
private String createTemplateBody(String soyExpr) {
// collect all varrefs and apply them as template parameters. This way all varrefs have a valid
// vardef
// TODO(lukes): this logic would be useful in a lot of tests and potentially unblock efforts to
// eliminate UNDECLARED vars
ExprNode expr = SoyFileParser.parseExpression(soyExpr, PluginResolver.nullResolver(Mode.ALLOW_UNDEFINED, ErrorReporter.exploding()), ErrorReporter.exploding());
final StringBuilder templateBody = new StringBuilder();
new AbstractExprNodeVisitor<Void>() {
final Set<String> names = new HashSet<>();
@Override
protected void visitVarRefNode(VarRefNode node) {
if (names.add(node.getName())) {
SoyType type = variables.get(node.getName()).soyType();
templateBody.append("{@param ").append(node.getName()).append(": ").append(type).append("}\n");
}
}
@Override
protected void visitExprNode(ExprNode node) {
if (node instanceof ParentExprNode) {
visitChildren((ParentExprNode) node);
}
}
}.exec(expr);
templateBody.append("{" + soyExpr + "}\n");
return templateBody.toString();
}
use of com.google.template.soy.exprtree.VarRefNode in project closure-templates by google.
the class CheckTemplateParamsVisitor method visitTemplateNode.
// -----------------------------------------------------------------------------------------------
// Implementations for specific nodes.
@Override
protected void visitTemplateNode(TemplateNode node) {
if (!node.couldHaveSyntaxVersionAtLeast(SyntaxVersion.V2_0)) {
return;
}
ListMultimap<String, SourceLocation> dataKeys = ArrayListMultimap.create();
for (VarRefNode varRefNode : SoyTreeUtils.getAllNodesOfType(node, VarRefNode.class)) {
if (varRefNode.isPossibleParam()) {
dataKeys.put(varRefNode.getName(), varRefNode.getSourceLocation());
}
}
IndirectParamsInfo ipi = new FindIndirectParamsVisitor(templateRegistry).exec(node);
Set<String> allParamNames = new HashSet<>();
List<TemplateParam> unusedParams = new ArrayList<>();
for (TemplateParam param : node.getAllParams()) {
allParamNames.add(param.name());
if (dataKeys.containsKey(param.name())) {
// Good: Declared and referenced in template. We remove these from dataKeys so
// that at the end of the for-loop, dataKeys will only contain the keys that are referenced
// but not declared in SoyDoc.
dataKeys.removeAll(param.name());
} else if (ipi.paramKeyToCalleesMultimap.containsKey(param.name()) || ipi.mayHaveIndirectParamsInExternalCalls || ipi.mayHaveIndirectParamsInExternalDelCalls) {
// Good: Declared in SoyDoc and either (a) used in a call that passes all data or (b) used
// in an external call or delcall that passes all data, which may need the param (we can't
// verify).
} else {
// Bad: Declared in SoyDoc but not referenced in template.
unusedParams.add(param);
}
}
// At this point, the only keys left in dataKeys are undeclared.
for (Entry<String, SourceLocation> undeclared : dataKeys.entries()) {
String extraErrorMessage = SoyErrors.getDidYouMeanMessage(allParamNames, undeclared.getKey());
errorReporter.report(undeclared.getValue(), UNDECLARED_DATA_KEY, undeclared.getKey(), extraErrorMessage);
}
// of the same delegate may need to use those params.
if (node instanceof TemplateBasicNode) {
for (TemplateParam unusedParam : unusedParams) {
errorReporter.report(unusedParam.nameLocation(), UNUSED_PARAM, unusedParam.name());
}
}
}
use of com.google.template.soy.exprtree.VarRefNode in project closure-templates by google.
the class GenIncrementalDomCodeVisitor method tryGenerateFunctionCall.
/**
* Emits a call to a value of type ATTRIBUTES or HTML, which is actually a JS function. Currently,
* the only supported expressions for this operation are direct variable references and {X ?: ''}.
*
* @param expectedKind The kind of content that the expression must match.
*/
private GenerateFunctionCallResult tryGenerateFunctionCall(SoyType.Kind expectedKind, ExprNode expr) {
IncrementalDomCodeBuilder jsCodeBuilder = getJsCodeBuilder();
if (expr instanceof VarRefNode && expr.getType().getKind() == expectedKind) {
VarRefNode varRefNode = (VarRefNode) expr;
CodeChunk.WithValue call = templateTranslationContext.soyToJsVariableMappings().get(varRefNode.getName()).call();
jsCodeBuilder.append(call);
return GenerateFunctionCallResult.EMITTED;
}
if (!(expr instanceof NullCoalescingOpNode)) {
return GenerateFunctionCallResult.INDIRECT_NODE;
}
// ResolveExpressionTypesVisitor will resolve {$attributes ?: ''} to String because '' is not of
// type ATTRIBUTES. Therefore, we must check the type of the first operand, not the whole node.
NullCoalescingOpNode opNode = (NullCoalescingOpNode) expr;
if (!(opNode.getLeftChild() instanceof VarRefNode) || !(opNode.getRightChild() instanceof StringNode) || opNode.getLeftChild().getType().getKind() != expectedKind) {
return GenerateFunctionCallResult.INDIRECT_NODE;
}
if (!((StringNode) opNode.getRightChild()).getValue().isEmpty()) {
errorReporter.report(expr.getSourceLocation(), NULL_COALESCING_NON_EMPTY);
return GenerateFunctionCallResult.ILLEGAL_NODE;
}
VarRefNode varRefNode = (VarRefNode) opNode.getLeftChild();
CodeChunk.WithValue varName = templateTranslationContext.soyToJsVariableMappings().get(varRefNode.getName());
CodeChunk conditionalCall = CodeChunk.ifStatement(varName, varName.call()).build();
jsCodeBuilder.append(conditionalCall);
return GenerateFunctionCallResult.EMITTED;
}
use of com.google.template.soy.exprtree.VarRefNode in project closure-templates by google.
the class TemplateCompiler method generateTemplateMetadata.
/**
* Writes a {@link TemplateMetadata} to the generated class.
*/
private void generateTemplateMetadata() {
SanitizedContentKind contentKind = template.node().getContentKind();
String kind = contentKind == null ? "" : contentKind.name();
// using linked hash sets below for determinism
Set<String> uniqueIjs = new LinkedHashSet<>();
for (VarRefNode var : getAllNodesOfType(template.node(), VarRefNode.class)) {
if (var.isInjected()) {
uniqueIjs.add(var.getName());
}
}
Set<String> callees = new LinkedHashSet<>();
for (CallBasicNode call : getAllNodesOfType(template.node(), CallBasicNode.class)) {
callees.add(call.getCalleeName());
}
Set<String> delCallees = new LinkedHashSet<>();
for (CallDelegateNode call : getAllNodesOfType(template.node(), CallDelegateNode.class)) {
delCallees.add(call.getDelCalleeName());
}
TemplateMetadata.DelTemplateMetadata deltemplateMetadata;
if (template.node().getKind() == SoyNode.Kind.TEMPLATE_DELEGATE_NODE) {
TemplateDelegateNode delegateNode = (TemplateDelegateNode) template.node();
deltemplateMetadata = createDelTemplateMetadata(delegateNode.getDelPackageName() == null ? "" : delegateNode.getDelPackageName(), delegateNode.getDelTemplateName(), delegateNode.getDelTemplateVariant());
} else {
deltemplateMetadata = createDefaultDelTemplateMetadata();
}
TemplateMetadata metadata = createTemplateMetadata(kind, uniqueIjs, callees, delCallees, deltemplateMetadata);
TEMPLATE_METADATA_REF.write(metadata, writer);
}
use of com.google.template.soy.exprtree.VarRefNode in project closure-templates by google.
the class EvalVisitor method visitIndexFunction.
private SoyValue visitIndexFunction(FunctionNode node) {
int localVarIndex;
try {
VarRefNode dataRef = (VarRefNode) node.getChild(0);
localVarIndex = env.getIndex((LoopVar) dataRef.getDefnDecl());
} catch (Exception e) {
throw RenderException.create("Failed to evaluate function call " + node.toSourceString() + ".", e);
}
return convertResult(localVarIndex);
}
Aggregations