Skip to content

Commit 9c17965

Browse files
lukesandbergBrendan Linn
authored andcommitted
Soy jbcsrc: Add information about used injected parameters and callees to @TemplateMetadata
This is a prerequisite for adding precompilation support. The SoySauce object has a method getTransitiveIjParamsForTemplate which is currently implemented via a specific compiler pass. In order to support this method in a precompilation usecase we will need to store this information somewhere else. The current plan is to add metadata to each generated template and then lazily calculate this data by crawling through the callgraph. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=106638022
1 parent 6658b55 commit 9c17965

File tree

4 files changed

+75
-4
lines changed

4 files changed

+75
-4
lines changed

java/src/com/google/template/soy/jbcsrc/TemplateCompiler.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,24 @@
2828
import static com.google.template.soy.jbcsrc.StandardNames.IJ_FIELD;
2929
import static com.google.template.soy.jbcsrc.StandardNames.PARAMS_FIELD;
3030
import static com.google.template.soy.jbcsrc.StandardNames.STATE_FIELD;
31+
import static com.google.template.soy.soytree.SoytreeUtils.getAllNodesOfType;
3132

3233
import com.google.common.collect.ImmutableMap;
3334
import com.google.template.soy.data.SoyRecord;
3435
import com.google.template.soy.data.SoyValueProvider;
36+
import com.google.template.soy.exprtree.VarDefn;
37+
import com.google.template.soy.exprtree.VarDefn.Kind;
38+
import com.google.template.soy.exprtree.VarRefNode;
3539
import com.google.template.soy.jbcsrc.SoyNodeCompiler.CompiledMethodBody;
3640
import com.google.template.soy.jbcsrc.shared.CompiledTemplate;
3741
import com.google.template.soy.jbcsrc.shared.TemplateMetadata;
42+
import com.google.template.soy.soytree.CallBasicNode;
43+
import com.google.template.soy.soytree.CallDelegateNode;
3844
import com.google.template.soy.soytree.CallParamContentNode;
3945
import com.google.template.soy.soytree.CallParamValueNode;
4046
import com.google.template.soy.soytree.LetContentNode;
4147
import com.google.template.soy.soytree.LetValueNode;
48+
import com.google.template.soy.soytree.SoytreeUtils;
4249
import com.google.template.soy.soytree.TemplateNode;
4350
import com.google.template.soy.soytree.defn.LocalVar;
4451
import com.google.template.soy.soytree.defn.TemplateParam;
@@ -49,7 +56,9 @@
4956
import org.objectweb.asm.Type;
5057

5158
import java.util.ArrayList;
59+
import java.util.HashSet;
5260
import java.util.List;
61+
import java.util.Set;
5362

5463
/**
5564
* Compiles the top level {@link CompiledTemplate} class for a single template and all related
@@ -154,6 +163,28 @@ private void generateTemplateMetadata() {
154163
? ""
155164
: template.node().getContentKind().name();
156165
annotationWriter.visit("contentKind", kind);
166+
167+
AnnotationVisitor ijsVisitor = annotationWriter.visitArray("injectedParams");
168+
Set<String> uniqueIjs = new HashSet<>();
169+
for (VarRefNode var : getAllNodesOfType(template.node(), VarRefNode.class)) {
170+
if (var.isInjected() && uniqueIjs.add(var.getName())) {
171+
ijsVisitor.visit(null /* ignored for array values */, var.getName());
172+
}
173+
}
174+
ijsVisitor.visitEnd();
175+
176+
AnnotationVisitor calleesVisitor = annotationWriter.visitArray("callees");
177+
for (CallBasicNode call : getAllNodesOfType(template.node(), CallBasicNode.class)) {
178+
calleesVisitor.visit(null /* ignored for array values */, call.getCalleeName());
179+
}
180+
calleesVisitor.visitEnd();
181+
182+
AnnotationVisitor delCalleesVisitor = annotationWriter.visitArray("delCallees");
183+
for (CallDelegateNode call : getAllNodesOfType(template.node(), CallDelegateNode.class)) {
184+
delCalleesVisitor.visit(null /* ignored for array values */, call.getDelCalleeName());
185+
}
186+
delCalleesVisitor.visitEnd();
187+
157188
annotationWriter.visitEnd();
158189
}
159190

java/src/com/google/template/soy/jbcsrc/shared/TemplateMetadata.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,19 @@
4040
* or {@code ""} which means that this isn't a strict template.
4141
*/
4242
String contentKind();
43+
44+
/**
45+
* Returns the list of injected params, both {@code $ij.foo} variables and {@code @inject} params
46+
*/
47+
String[] injectedParams();
48+
49+
/**
50+
* Returns the fully qualified names of all the basic templates called by this template.
51+
*/
52+
String[] callees();
53+
54+
/**
55+
* Returns the fully qualified names of all the delegate templates called by this template.
56+
*/
57+
String[] delCallees();
4358
}

java/tests/com/google/template/soy/jbcsrc/BytecodeCompilerTest.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ public void testDelCall_delVariant() throws IOException {
202202
factory.create(TemplateTester.asRecord(ImmutableMap.of("variant", "unknown")), EMPTY_DICT)
203203
.render(builder, context));
204204
assertThat(builder.toString()).isEmpty();
205+
206+
TemplateMetadata templateMetadata = getTemplateMetadata(templates, "ns1.callerTemplate");
207+
assertThat(templateMetadata.callees()).isEmpty();
208+
assertThat(templateMetadata.delCallees()).asList().containsExactly("ns1.del");
205209
}
206210

207211
public void testCallBasicNode() throws IOException {
@@ -251,21 +255,30 @@ public void testCallBasicNode() throws IOException {
251255
params.setField("boo", StringData.forValue("boo"));
252256
assertThat(render(templates, params, "ns.callerDataAll")).isEqualTo("Foo: foo\nBoo: boo\n");
253257

258+
assertThat(getTemplateMetadata(templates, "ns.callerDataAll").callees()).asList().containsExactly("ns.callee");
259+
254260
params = new BasicParamStore(2);
255261
params.setField("rec", new BasicParamStore(2).setField("foo", StringData.forValue("foo")));
256262
assertThat(render(templates, params, "ns.callerDataExpr")).isEqualTo("Foo: foo\nBoo: null\n");
257263
((ParamStore) params.getField("rec")).setField("boo", StringData.forValue("boo"));
258264
assertThat(render(templates, params, "ns.callerDataExpr")).isEqualTo("Foo: foo\nBoo: boo\n");
265+
assertThat(getTemplateMetadata(templates, "ns.callerDataExpr").callees()).asList().containsExactly("ns.callee");
259266

260267
params = new BasicParamStore(2);
261268
params.setField("p1", StringData.forValue("foo"));
262269
assertThat(render(templates, params, "ns.callerParams")).isEqualTo("Foo: foo\nBoo: a1b\n");
270+
assertThat(getTemplateMetadata(templates, "ns.callerParams").callees()).asList().containsExactly("ns.callee");
263271

264272
params = new BasicParamStore(2);
265273
params.setField("p1", StringData.forValue("foo"));
266274
params.setField("boo", StringData.forValue("boo"));
267275
assertThat(render(templates, params, "ns.callerParamsAndData"))
268276
.isEqualTo("Foo: foo\nBoo: boo\n");
277+
assertThat(getTemplateMetadata(templates, "ns.callerParamsAndData").callees()).asList().containsExactly("ns.callee");
278+
}
279+
280+
private static TemplateMetadata getTemplateMetadata(CompiledTemplates templates, String name) {
281+
return templates.getTemplateFactory(name).getClass().getDeclaringClass().getAnnotation(TemplateMetadata.class);
269282
}
270283

271284
private String render(CompiledTemplates templates, SoyRecord params, String name)
@@ -655,6 +668,11 @@ public void testParamFields() throws Exception {
655668
assertEquals(StringData.forValue("foo"), getField("foo", template));
656669
assertEquals(StringData.forValue("bar"), getField("bar", template));
657670
assertEquals(StringData.forValue("baz"), getField("baz", template));
671+
672+
TemplateMetadata templateMetadata = template.getClass().getAnnotation(TemplateMetadata.class);
673+
assertThat(templateMetadata.injectedParams()).asList().containsExactly("bar");
674+
assertThat(templateMetadata.callees()).isEmpty();
675+
assertThat(templateMetadata.delCallees()).isEmpty();
658676
}
659677

660678
private Object getField(String name, CompiledTemplate template) throws Exception {
@@ -674,7 +692,12 @@ public void testBasicFunctionality() {
674692
factory.create(EMPTY_DICT, EMPTY_DICT).getClass();
675693
assertEquals("com.google.template.soy.jbcsrc.gen.ns.foo", templateClass.getName());
676694
assertEquals("foo", templateClass.getSimpleName());
677-
assertEquals("HTML", templateClass.getAnnotation(TemplateMetadata.class).contentKind());
695+
696+
TemplateMetadata templateMetadata = templateClass.getAnnotation(TemplateMetadata.class);
697+
assertEquals("HTML", templateMetadata.contentKind());
698+
assertThat(templateMetadata.injectedParams()).isEmpty();
699+
assertThat(templateMetadata.callees()).isEmpty();
700+
assertThat(templateMetadata.delCallees()).isEmpty();
678701

679702
// ensure that the factory is an inner class of the template.
680703
assertEquals(templateClass, factory.getClass().getEnclosingClass());

testdata/javascript/soy_usegoog_lib.js

Lines changed: 5 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)