Skip to content

Commit e98c324

Browse files
java-team-github-botGoogle Java Core Libraries
authored andcommitted
Improve handling of nullable properties in AutoBuilder:
- Support setters accepting `Optional` types for nullable properties. - Support getters providing `Optional` types for nullable properties. RELNOTES=AutoBuilder now allows `Optional` getters and setters to be used with nullable properties. PiperOrigin-RevId: 887170824
1 parent 74bb96d commit e98c324

9 files changed

Lines changed: 375 additions & 27 deletions

File tree

value/src/it/functional/src/test/java/com/google/auto/value/AutoBuilderTest.java

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
import java.util.NoSuchElementException;
4242
import java.util.Objects;
4343
import java.util.Optional;
44+
import java.util.OptionalDouble;
45+
import java.util.OptionalInt;
46+
import java.util.OptionalLong;
4447
import java.util.Set;
4548
import javax.lang.model.SourceVersion;
4649
import org.junit.Test;
@@ -779,4 +782,135 @@ public void builderTypeVariableWithNullableBound() {
779782
NullPointerException.class,
780783
() -> FrobCaller.<@Nullable String, String>caller().arg(null).notNull(null).call());
781784
}
785+
786+
static class NullablesExposedAsOptionals {
787+
private final @Nullable String aString1;
788+
private final @Nullable String aString2;
789+
private final @Nullable Double aDouble;
790+
private final @Nullable Integer anInt;
791+
private final @Nullable Long aLong;
792+
793+
NullablesExposedAsOptionals(
794+
@Nullable String aString1,
795+
@Nullable String aString2,
796+
@Nullable Double aDouble,
797+
@Nullable Integer anInt,
798+
@Nullable Long aLong) {
799+
this.aString1 = aString1;
800+
this.aString2 = aString2;
801+
this.aDouble = aDouble;
802+
this.anInt = anInt;
803+
this.aLong = aLong;
804+
}
805+
806+
Optional<String> aString1() {
807+
return Optional.ofNullable(aString1);
808+
}
809+
810+
com.google.common.base.Optional<String> aString2() {
811+
return com.google.common.base.Optional.fromNullable(aString2);
812+
}
813+
814+
OptionalDouble aDouble() {
815+
return aDouble == null ? OptionalDouble.empty() : OptionalDouble.of(aDouble);
816+
}
817+
818+
OptionalInt anInt() {
819+
return anInt == null ? OptionalInt.empty() : OptionalInt.of(anInt);
820+
}
821+
822+
OptionalLong aLong() {
823+
return aLong == null ? OptionalLong.empty() : OptionalLong.of(aLong);
824+
}
825+
826+
Builder toBuilder() {
827+
return new AutoBuilder_AutoBuilderTest_NullablesExposedAsOptionals_Builder(this);
828+
}
829+
830+
static Builder builder() {
831+
return new AutoBuilder_AutoBuilderTest_NullablesExposedAsOptionals_Builder();
832+
}
833+
834+
@AutoBuilder
835+
abstract static class Builder {
836+
abstract Builder setAString1(Optional<String> aString1);
837+
838+
abstract Builder setAString2(com.google.common.base.Optional<String> aString2);
839+
840+
abstract Builder setADouble(OptionalDouble aDouble);
841+
842+
abstract Builder setAnInt(OptionalInt anInt);
843+
844+
abstract Builder setALong(OptionalLong aLong);
845+
846+
abstract NullablesExposedAsOptionals build();
847+
}
848+
}
849+
850+
@Test
851+
public void builderExposingNullableAsOptionalString() {
852+
NullablesExposedAsOptionals built =
853+
NullablesExposedAsOptionals.builder().setAString1(Optional.of("foo")).build();
854+
assertThat(built.aString1()).hasValue("foo");
855+
assertThat(built.toBuilder().build().aString1()).hasValue("foo");
856+
857+
NullablesExposedAsOptionals builtEmpty =
858+
built.toBuilder().setAString1(Optional.empty()).build();
859+
assertThat(builtEmpty.aString1()).isEmpty();
860+
assertThat(builtEmpty.toBuilder().build().aString1()).isEmpty();
861+
}
862+
863+
@Test
864+
public void builderExposingNullableAsBaseOptionalString() {
865+
NullablesExposedAsOptionals built =
866+
NullablesExposedAsOptionals.builder()
867+
.setAString2(com.google.common.base.Optional.of("foo"))
868+
.build();
869+
assertThat(built.aString2()).hasValue("foo");
870+
assertThat(built.toBuilder().build().aString2()).hasValue("foo");
871+
872+
NullablesExposedAsOptionals builtAbsent =
873+
built.toBuilder().setAString2(com.google.common.base.Optional.absent()).build();
874+
assertThat(builtAbsent.aString2()).isAbsent();
875+
assertThat(builtAbsent.toBuilder().build().aString2()).isAbsent();
876+
}
877+
878+
@Test
879+
public void builderExposingNullableAsOptionalDouble() {
880+
NullablesExposedAsOptionals built =
881+
NullablesExposedAsOptionals.builder().setADouble(OptionalDouble.of(3.14)).build();
882+
assertThat(built.aDouble()).hasValue(3.14);
883+
assertThat(built.toBuilder().build().aDouble()).hasValue(3.14);
884+
885+
NullablesExposedAsOptionals builtEmpty =
886+
built.toBuilder().setADouble(OptionalDouble.empty()).build();
887+
assertThat(builtEmpty.aDouble()).isEmpty();
888+
assertThat(builtEmpty.toBuilder().build().aDouble()).isEmpty();
889+
}
890+
891+
@Test
892+
public void builderExposingNullableAsOptionalInt() {
893+
NullablesExposedAsOptionals built =
894+
NullablesExposedAsOptionals.builder().setAnInt(OptionalInt.of(3)).build();
895+
assertThat(built.anInt()).hasValue(3);
896+
assertThat(built.toBuilder().build().anInt()).hasValue(3);
897+
898+
NullablesExposedAsOptionals builtEmpty =
899+
built.toBuilder().setAnInt(OptionalInt.empty()).build();
900+
assertThat(builtEmpty.anInt()).isEmpty();
901+
assertThat(builtEmpty.toBuilder().build().anInt()).isEmpty();
902+
}
903+
904+
@Test
905+
public void builderExposingNullableAsOptionalLong() {
906+
NullablesExposedAsOptionals built =
907+
NullablesExposedAsOptionals.builder().setALong(OptionalLong.of(3)).build();
908+
assertThat(built.aLong()).hasValue(3);
909+
assertThat(built.toBuilder().build().aLong()).hasValue(3);
910+
911+
NullablesExposedAsOptionals builtEmpty =
912+
built.toBuilder().setALong(OptionalLong.empty()).build();
913+
assertThat(builtEmpty.aLong()).isEmpty();
914+
assertThat(builtEmpty.toBuilder().build().aLong()).isEmpty();
915+
}
782916
}

value/src/it/functional/src/test/java/com/google/auto/value/AutoValueJava8Test.java

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
import java.util.List;
5151
import java.util.Optional;
5252
import java.util.OptionalDouble;
53+
import java.util.OptionalInt;
54+
import java.util.OptionalLong;
5355
import java.util.Set;
5456
import java.util.function.Predicate;
5557
import java.util.stream.Stream;
@@ -1210,4 +1212,111 @@ public void typeParameterBuilderFieldsAreNullable() throws ReflectiveOperationEx
12101212
.asList()
12111213
.contains(nullable());
12121214
}
1215+
1216+
@AutoValue
1217+
abstract static class NullablesExposedAsOptionals {
1218+
abstract @Nullable String maybeString();
1219+
1220+
abstract @Nullable Double maybeDouble();
1221+
1222+
abstract @Nullable Integer maybeInt();
1223+
1224+
abstract @Nullable Long maybeLong();
1225+
1226+
static Builder builder() {
1227+
return new AutoValue_AutoValueJava8Test_NullablesExposedAsOptionals.Builder();
1228+
}
1229+
1230+
@AutoValue.Builder
1231+
abstract static class Builder {
1232+
abstract Builder setMaybeString(Optional<String> maybeString);
1233+
1234+
abstract Builder setMaybeString(com.google.common.base.Optional<String> maybeString);
1235+
1236+
abstract Builder setMaybeDouble(OptionalDouble maybeDouble);
1237+
1238+
abstract Builder setMaybeInt(OptionalInt maybeInt);
1239+
1240+
abstract Builder setMaybeLong(OptionalLong maybeLong);
1241+
1242+
abstract NullablesExposedAsOptionals build();
1243+
}
1244+
}
1245+
1246+
@Test
1247+
public void testNullablesExposedAsOptionals_optionalString() {
1248+
assertThat(
1249+
NullablesExposedAsOptionals.builder()
1250+
.setMaybeString(Optional.of("foo"))
1251+
.build()
1252+
.maybeString())
1253+
.isEqualTo("foo");
1254+
assertThat(
1255+
NullablesExposedAsOptionals.builder()
1256+
.setMaybeString(Optional.empty())
1257+
.build()
1258+
.maybeString())
1259+
.isNull();
1260+
}
1261+
1262+
@Test
1263+
public void testNullablesExposedAsOptionals_baseOptionalString() {
1264+
assertThat(
1265+
NullablesExposedAsOptionals.builder()
1266+
.setMaybeString(com.google.common.base.Optional.of("foo"))
1267+
.build()
1268+
.maybeString())
1269+
.isEqualTo("foo");
1270+
assertThat(
1271+
NullablesExposedAsOptionals.builder()
1272+
.setMaybeString(com.google.common.base.Optional.absent())
1273+
.build()
1274+
.maybeString())
1275+
.isNull();
1276+
}
1277+
1278+
@Test
1279+
public void testNullablesExposedAsOptionals_optionalDouble() {
1280+
assertThat(
1281+
NullablesExposedAsOptionals.builder()
1282+
.setMaybeDouble(OptionalDouble.of(3.14))
1283+
.build()
1284+
.maybeDouble())
1285+
.isEqualTo(3.14);
1286+
assertThat(
1287+
NullablesExposedAsOptionals.builder()
1288+
.setMaybeDouble(OptionalDouble.empty())
1289+
.build()
1290+
.maybeDouble())
1291+
.isNull();
1292+
}
1293+
1294+
@Test
1295+
public void testNullablesExposedAsOptionals_optionalInt() {
1296+
assertThat(
1297+
NullablesExposedAsOptionals.builder().setMaybeInt(OptionalInt.of(3)).build().maybeInt())
1298+
.isEqualTo(3);
1299+
assertThat(
1300+
NullablesExposedAsOptionals.builder()
1301+
.setMaybeInt(OptionalInt.empty())
1302+
.build()
1303+
.maybeInt())
1304+
.isNull();
1305+
}
1306+
1307+
@Test
1308+
public void testNullablesExposedAsOptionals_optionalLong() {
1309+
assertThat(
1310+
NullablesExposedAsOptionals.builder()
1311+
.setMaybeLong(OptionalLong.of(3))
1312+
.build()
1313+
.maybeLong())
1314+
.isEqualTo(3);
1315+
assertThat(
1316+
NullablesExposedAsOptionals.builder()
1317+
.setMaybeLong(OptionalLong.empty())
1318+
.build()
1319+
.maybeLong())
1320+
.isNull();
1321+
}
12131322
}

0 commit comments

Comments
 (0)