Skip to content

Commit f00c32a

Browse files
eamonnmcmanusGoogle Java Core Libraries
authored andcommitted
Generate missing-property checks in a way that is easier for null-analysis to understand.
The new code is more verbose than the old, since it has two null checks for every property (when there is more than one required property). The second check will only be executed when at least one property is missing and we are about to throw an exception. The extra checks also don't happen when compiling without identifiers, as is typically the case in code-size-sensitive environments like Android. RELNOTES=Generated builder code is now slightly friendly to null-analysis. PiperOrigin-RevId: 374652915
1 parent cd55f63 commit f00c32a

3 files changed

Lines changed: 44 additions & 31 deletions

File tree

value/src/main/java/com/google/auto/value/processor/builder.vm

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -239,31 +239,41 @@ class ${builderName}${builderFormalTypes} ##
239239
#end
240240

241241
#if (!$builderRequiredProperties.empty)
242+
if (#foreach ($p in $builderRequiredProperties)##
243+
this.$p == null##
244+
#if ($foreach.hasNext)
245+
246+
|| #end
247+
#end) {
248+
242249
#if ($identifiers) ## build a friendly message showing all missing properties
250+
#if ($builderRequiredProperties.size() == 1)
243251

244-
`java.lang.String` missing = "";
252+
`java.lang.String` missing = " $builderRequiredProperties.iterator().next()";
245253

246-
#foreach ($p in $builderRequiredProperties)
254+
#else
255+
256+
`java.lang.StringBuilder` missing = new `java.lang.StringBuilder`();
257+
258+
#foreach ($p in $builderRequiredProperties)
247259

248260
if (this.$p == null) {
249-
missing += " $p.name";
261+
missing.append(" $p.name");
250262
}
251263

264+
#end
252265
#end
253266

254-
if (!missing.isEmpty()) {
255-
throw new IllegalStateException("Missing required properties:" + missing);
256-
}
267+
throw new IllegalStateException("Missing required properties:" + missing);
257268

258269
#else ## just throw an exception if anything is missing
259270

260-
if (#foreach ($p in $builderRequiredProperties)##
261-
this.$p == null##
262-
#if ($foreach.hasNext) || #end
263-
#end) {
264-
throw new IllegalStateException();
265-
}
271+
throw new IllegalStateException();
272+
266273
#end
274+
275+
}
276+
267277
#end
268278

269279
#if ($builtType != "void") return #end ${build}(

value/src/test/java/com/google/auto/value/processor/AutoBuilderCompilationTest.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,15 @@ public final class AutoBuilderCompilationTest {
5858
"",
5959
" @Override",
6060
" public Baz build() {",
61-
" String missing = \"\";",
62-
" if (this.anInt == null) {",
63-
" missing += \" anInt\";",
64-
" }",
65-
" if (this.aString == null) {",
66-
" missing += \" aString\";",
67-
" }",
68-
" if (!missing.isEmpty()) {",
61+
" if (this.anInt == null",
62+
" || this.aString == null) {",
63+
" StringBuilder missing = new StringBuilder();",
64+
" if (this.anInt == null) {",
65+
" missing.append(\" anInt\");",
66+
" }",
67+
" if (this.aString == null) {",
68+
" missing.append(\" aString\");",
69+
" }",
6970
" throw new IllegalStateException(\"Missing required properties:\" + missing);",
7071
" }",
7172
" return new Baz(",

value/src/test/java/com/google/auto/value/processor/AutoValueCompilationTest.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,17 +1311,19 @@ public void correctBuilder() {
13111311
+ "NestedAutoValue.builder();",
13121312
" this.aNestedAutoValue = aNestedAutoValue$builder.build();",
13131313
" }",
1314-
" String missing = \"\";",
1315-
" if (this.anInt == null) {",
1316-
" missing += \" anInt\";",
1317-
" }",
1318-
" if (this.aByteArray == null) {",
1319-
" missing += \" aByteArray\";",
1320-
" }",
1321-
" if (this.aList == null) {",
1322-
" missing += \" aList\";",
1323-
" }",
1324-
" if (!missing.isEmpty()) {",
1314+
" if (this.anInt == null",
1315+
" || this.aByteArray == null",
1316+
" || this.aList == null) {",
1317+
" StringBuilder missing = new StringBuilder();",
1318+
" if (this.anInt == null) {",
1319+
" missing.append(\" anInt\");",
1320+
" }",
1321+
" if (this.aByteArray == null) {",
1322+
" missing.append(\" aByteArray\");",
1323+
" }",
1324+
" if (this.aList == null) {",
1325+
" missing.append(\" aList\");",
1326+
" }",
13251327
" throw new IllegalStateException(\"Missing required properties:\" + missing);",
13261328
" }",
13271329
" return new AutoValue_Baz<T>(",

0 commit comments

Comments
 (0)