From ea4f6db7a93c614665c61a4718d2886d7e3fe8c2 Mon Sep 17 00:00:00 2001 From: Andrea Cavalli Date: Wed, 4 Sep 2024 17:46:50 +0200 Subject: [PATCH] Use generic TypedNullable instead of the specific implementation in records --- .../datagen/plugin/ComputedType.java | 1 + .../plugin/ComputedTypeArrayFixed.java | 5 ++ .../plugin/ComputedTypeArrayNative.java | 6 ++ .../plugin/ComputedTypeArrayVersioned.java | 5 ++ .../datagen/plugin/ComputedTypeBase.java | 6 ++ .../datagen/plugin/ComputedTypeCustom.java | 5 ++ .../datagen/plugin/ComputedTypeNative.java | 5 ++ .../plugin/ComputedTypeNullableFixed.java | 14 ++- .../plugin/ComputedTypeNullableNative.java | 5 ++ .../plugin/ComputedTypeNullableVersioned.java | 14 ++- .../datagen/plugin/ComputedTypeSuper.java | 6 ++ .../datagen/plugin/SourcesGenerator.java | 2 +- .../datagen/plugin/classgen/GenDataBaseX.java | 2 +- .../plugin/classgen/GenDataSuperX.java | 4 +- .../datagen/plugin/classgen/GenNullableX.java | 3 +- .../classgen/GenSerializerNullableX.java | 4 +- .../plugin/classgen/GenUpgraderBaseX.java | 2 +- .../datagen/plugin/classgen/GenVersion.java | 2 +- .../it/cavallium/datagen/TypedNullable.java | 5 +- .../datagen/nativedata/TestTypedNullable.java | 87 +++++++++++++++++++ 20 files changed, 170 insertions(+), 13 deletions(-) create mode 100644 datagen/src/test/java/it/cavallium/datagen/nativedata/TestTypedNullable.java diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedType.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedType.java index 0065646..9823d32 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedType.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedType.java @@ -12,6 +12,7 @@ public sealed interface ComputedType permits VersionedComputedType, ComputedType String getName(); TypeName getJTypeName(String basePackageName); + TypeName getJTypeNameGeneric(String basePackageName); TypeName getJSerializerName(String basePackageName); diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayFixed.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayFixed.java index 8acbf9c..ab91dd5 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayFixed.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayFixed.java @@ -71,6 +71,11 @@ public final class ComputedTypeArrayFixed implements ComputedTypeArray { computedTypeSupplier.get(baseType).getJTypeName(basePackageName)); } + @Override + public TypeName getJTypeNameGeneric(String basePackageName) { + return getJTypeName(basePackageName); + } + @Override public ClassName getJSerializerName(String basePackageName) { return ClassName.get(currentVersion.getSerializersPackage(basePackageName), "Array" + baseType + "Serializer"); diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayNative.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayNative.java index 18829f1..b9d56f1 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayNative.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayNative.java @@ -3,6 +3,7 @@ package it.cavallium.datagen.plugin; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; +import it.cavallium.datagen.NativeNullable; import it.cavallium.datagen.nativedata.ArrayInt52Serializer; import it.cavallium.datagen.nativedata.ArrayStringSerializer; import it.cavallium.datagen.nativedata.ArraybooleanSerializer; @@ -96,6 +97,11 @@ public final class ComputedTypeArrayNative implements ComputedTypeArray { }; } + @Override + public TypeName getJTypeNameGeneric(String basePackageName) { + return getJTypeName(basePackageName); + } + @Override public ClassName getJSerializerName(String basePackageName) { return switch (baseType) { diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayVersioned.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayVersioned.java index 07aa1e4..10453d9 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayVersioned.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeArrayVersioned.java @@ -88,6 +88,11 @@ public final class ComputedTypeArrayVersioned implements VersionedComputedType, computedTypeSupplier.get(baseType).getJTypeName(basePackageName)); } + @Override + public TypeName getJTypeNameGeneric(String basePackageName) { + return getJTypeName(basePackageName); + } + @Override public ClassName getJSerializerName(String basePackageName) { return ClassName.get(baseType.version().getSerializersPackage(basePackageName), "Array" + baseType.type() + "Serializer"); diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeBase.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeBase.java index f42f03f..3d830b6 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeBase.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeBase.java @@ -2,6 +2,7 @@ package it.cavallium.datagen.plugin; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.TypeName; import it.cavallium.datagen.plugin.ComputedType.VersionedComputedType; import java.util.LinkedHashMap; import java.util.Objects; @@ -101,6 +102,11 @@ public final class ComputedTypeBase implements VersionedComputedType { return ClassName.get(getVersion().getDataPackage(basePackageName), type.type()); } + @Override + public TypeName getJTypeNameGeneric(String basePackageName) { + return getJTypeName(basePackageName); + } + @Override public ClassName getJSerializerName(String basePackageName) { return ClassName.get(type.version().getSerializersPackage(basePackageName), type.type() + "Serializer"); diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeCustom.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeCustom.java index 7f397ea..71d426f 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeCustom.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeCustom.java @@ -93,6 +93,11 @@ public final class ComputedTypeCustom implements ComputedType { return typeName; } + @Override + public TypeName getJTypeNameGeneric(String basePackageName) { + return getJTypeName(basePackageName); + } + @Override public TypeName getJSerializerName(String basePackageName) { return ClassName.bestGuess(serializer); diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNative.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNative.java index a14fe0b..7bdd661 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNative.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNative.java @@ -46,6 +46,11 @@ public final class ComputedTypeNative implements ComputedType { }; } + @Override + public TypeName getJTypeNameGeneric(String basePackageName) { + return getJTypeName(basePackageName); + } + @Override public TypeName getJSerializerName(String basePackageName) { return switch (type) { diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableFixed.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableFixed.java index 09d34ce..85b09fa 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableFixed.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableFixed.java @@ -2,7 +2,9 @@ package it.cavallium.datagen.plugin; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; +import it.cavallium.datagen.TypedNullable; import it.cavallium.datagen.nativedata.UpgradeUtil; import java.util.Objects; import java.util.stream.Stream; @@ -68,11 +70,21 @@ public final class ComputedTypeNullableFixed implements ComputedTypeNullable { return getJTypeNameOfVersion(currentVersion, basePackageName); } + @Override + public TypeName getJTypeNameGeneric(String basePackageName) { + return getJTypeNameGenericOfVersion(currentVersion, basePackageName); + } + private TypeName getJTypeNameOfVersion(ComputedVersion version, String basePackageName) { return ClassName.get(version.getDataNullablesPackage(basePackageName), "Nullable" + baseType); } + private TypeName getJTypeNameGenericOfVersion(ComputedVersion version, String basePackageName) { + return ParameterizedTypeName.get(ClassName.get(TypedNullable.class), + ClassName.get(version.getDataPackage(basePackageName), baseType)); + } + @Override public ClassName getJSerializerName(String basePackageName) { return ClassName.get(currentVersion.getSerializersPackage(basePackageName), @@ -102,7 +114,7 @@ public final class ComputedTypeNullableFixed implements ComputedTypeNullable { var upgraderInstance = getBase().getJUpgraderInstance(basePackageName); builder.add("new $T($T.upgradeNullable(", next.getJTypeName(basePackageName), UpgradeUtil.class); builder.add(content); - builder.add(".value(), $T.$N)", upgraderInstance.className(), upgraderInstance.fieldName()); + builder.add(".getNullable(), $T.$N)", upgraderInstance.className(), upgraderInstance.fieldName()); builder.add(")"); return builder.build(); } diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableNative.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableNative.java index 87a1cee..765c42b 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableNative.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableNative.java @@ -99,6 +99,11 @@ public final class ComputedTypeNullableNative implements ComputedTypeNullable { }; } + @Override + public TypeName getJTypeNameGeneric(String basePackageName) { + return getJTypeName(basePackageName); + } + @Override public ClassName getJSerializerName(String basePackageName) { return switch (baseType) { diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableVersioned.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableVersioned.java index f6b27ad..0d21dc9 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableVersioned.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeNullableVersioned.java @@ -2,7 +2,9 @@ package it.cavallium.datagen.plugin; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; +import it.cavallium.datagen.TypedNullable; import it.cavallium.datagen.nativedata.UpgradeUtil; import it.cavallium.datagen.plugin.ComputedType.VersionedComputedType; import java.util.LinkedHashMap; @@ -81,11 +83,21 @@ public final class ComputedTypeNullableVersioned implements ComputedTypeNullable return getJTypeNameOfVersion(baseType.version(), basePackageName); } + @Override + public TypeName getJTypeNameGeneric(String basePackageName) { + return getJTypeNameGenericOfVersion(baseType.version(), basePackageName); + } + private TypeName getJTypeNameOfVersion(ComputedVersion version, String basePackageName) { return ClassName.get(version.getDataNullablesPackage(basePackageName), "Nullable" + baseType.type()); } + private TypeName getJTypeNameGenericOfVersion(ComputedVersion version, String basePackageName) { + return ParameterizedTypeName.get(ClassName.get(TypedNullable.class), + ClassName.get(version.getDataPackage(basePackageName), baseType.type())); + } + @Override public ClassName getJSerializerName(String basePackageName) { return ClassName.get(baseType.version().getSerializersPackage(basePackageName), @@ -115,7 +127,7 @@ public final class ComputedTypeNullableVersioned implements ComputedTypeNullable var upgraderInstance = getBase().getJUpgraderInstance(basePackageName); builder.add("new $T($T.upgradeNullable(", next.getJTypeName(basePackageName), UpgradeUtil.class); builder.add(content); - builder.add(".value(), $T.$N)", upgraderInstance.className(), upgraderInstance.fieldName()); + builder.add(".getNullable(), $T.$N)", upgraderInstance.className(), upgraderInstance.fieldName()); builder.add(")"); return builder.build(); } diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeSuper.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeSuper.java index 03c67bb..e0325db 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeSuper.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/ComputedTypeSuper.java @@ -2,6 +2,7 @@ package it.cavallium.datagen.plugin; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.TypeName; import it.cavallium.datagen.plugin.ComputedType.VersionedComputedType; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -97,6 +98,11 @@ public final class ComputedTypeSuper implements VersionedComputedType { return ClassName.get(getVersion().getDataPackage(basePackageName), type.type()); } + @Override + public TypeName getJTypeNameGeneric(String basePackageName) { + return ClassName.get(getVersion().getDataPackage(basePackageName), type.type()); + } + @Override public ClassName getJSerializerName(String basePackageName) { return ClassName.get(type.version().getSerializersPackage(basePackageName), type.type() + "Serializer"); diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/SourcesGenerator.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/SourcesGenerator.java index c07c14c..a22269c 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/SourcesGenerator.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/SourcesGenerator.java @@ -69,7 +69,7 @@ public class SourcesGenerator { private static final Logger logger = LoggerFactory.getLogger(SourcesGenerator.class); private static final boolean OVERRIDE_ALL_NULLABLE_METHODS = false; - private static final String SERIAL_VERSION = "2"; + private static final String SERIAL_VERSION = "5"; private final DataModel dataModel; diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenDataBaseX.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenDataBaseX.java index 9a5db5c..993899c 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenDataBaseX.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenDataBaseX.java @@ -68,7 +68,7 @@ public class GenDataBaseX extends ClassGenerator { .addModifiers(Modifier.PUBLIC, Modifier.STATIC); base.getData().forEach((fieldName, fieldType) -> { - var fieldTypeName = fieldType.getJTypeName(basePackageName); + var fieldTypeName = fieldType.getJTypeNameGeneric(basePackageName); var param = ParameterSpec .builder(fieldTypeName, fieldName) diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenDataSuperX.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenDataSuperX.java index e27779f..e85c63a 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenDataSuperX.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenDataSuperX.java @@ -61,7 +61,7 @@ public class GenDataSuperX extends ClassGenerator { Stream .concat(dataModel.getCommonInterfaceData(typeSuper), dataModel.getCommonInterfaceGetters(typeSuper)) .forEach(superType -> { - var returnType = superType.getValue().getJTypeName(basePackageName); + var returnType = superType.getValue().getJTypeNameGeneric(basePackageName); var getter = MethodSpec .methodBuilder(superType.getKey()) .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) @@ -73,7 +73,7 @@ public class GenDataSuperX extends ClassGenerator { }); dataModel.getCommonInterfaceData(typeSuper).forEach(superType -> { - var returnType = superType.getValue().getJTypeName(basePackageName); + var returnType = superType.getValue().getJTypeNameGeneric(basePackageName); var setter = MethodSpec .methodBuilder("set" + StringUtils.capitalize(superType.getKey())) diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenNullableX.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenNullableX.java index 2713ed7..c69ce76 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenNullableX.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenNullableX.java @@ -88,8 +88,9 @@ public class GenNullableX extends ClassGenerator { classBuilder.addField(FieldSpec .builder(type, "NULL").addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL).initializer("new $T(null)", type).build()); + classBuilder.addSuperinterfaces(List.of(iNullableITypeClass, iNullableClass, typedNullable)); + if (version.isCurrent()) { - classBuilder.addSuperinterfaces(List.of(iNullableITypeClass, iNullableClass, typedNullable)); classBuilder.addMethod(MethodSpec .methodBuilder("of") diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenSerializerNullableX.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenSerializerNullableX.java index c4886c6..3c25bc3 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenSerializerNullableX.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenSerializerNullableX.java @@ -42,7 +42,7 @@ public class GenSerializerNullableX extends ClassGenerator { private GeneratedClass generateTypeVersioned(ComputedVersion version, ComputedTypeNullable typeNullable) { ClassName serializerClassName = typeNullable.getJSerializerName(basePackageName); - var typeNullableClassName = typeNullable.getJTypeName(basePackageName); + var typeNullableClassName = typeNullable.getJTypeNameGeneric(basePackageName); var classBuilder = TypeSpec.classBuilder(serializerClassName.simpleName()); @@ -68,7 +68,7 @@ public class GenSerializerNullableX extends ClassGenerator { method.addParameter(ParameterSpec.builder(SafeDataOutput.class, "out").build()); method.addParameter(ParameterSpec - .builder(typeNullable.getJTypeName(basePackageName), "data") + .builder(typeNullable.getJTypeNameGeneric(basePackageName), "data") .addAnnotation(NotNull.class) .build()); diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenUpgraderBaseX.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenUpgraderBaseX.java index 0e37736..2f367d5 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenUpgraderBaseX.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenUpgraderBaseX.java @@ -286,7 +286,7 @@ public class GenUpgraderBaseX extends ClassGenerator { boolean first = true; for (String contextParameter : contextParameters) { var fieldType = typeBase.getData().get(contextParameter); - contextTypeClassBuilder.addRecordComponent(ParameterSpec.builder(fieldType.getJTypeName(basePackageName), contextParameter).build()); + contextTypeClassBuilder.addRecordComponent(ParameterSpec.builder(fieldType.getJTypeNameGeneric(basePackageName), contextParameter).build()); if (first) { first = false; diff --git a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenVersion.java b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenVersion.java index e6cf23f..58db021 100644 --- a/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenVersion.java +++ b/datagen-plugin/src/main/java/it/cavallium/datagen/plugin/classgen/GenVersion.java @@ -165,7 +165,7 @@ public class GenVersion extends ClassGenerator { var serializerClassName = type.getJSerializerName(basePackageName); var fieldBuilder = FieldSpec.builder(ParameterizedTypeName.get(ClassName.get(DataSerializer.class), - type.getJTypeName(basePackageName) + type.getJTypeNameGeneric(basePackageName) ), serializerFieldLocation.fieldName(), Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL); fieldBuilder.initializer("new $T()", serializerClassName); classBuilder.addField(fieldBuilder.build()); diff --git a/datagen/src/main/java/it/cavallium/datagen/TypedNullable.java b/datagen/src/main/java/it/cavallium/datagen/TypedNullable.java index ee4a5d4..0000ce7 100644 --- a/datagen/src/main/java/it/cavallium/datagen/TypedNullable.java +++ b/datagen/src/main/java/it/cavallium/datagen/TypedNullable.java @@ -34,10 +34,11 @@ public interface TypedNullable extends NativeNullable { } @Override - default @NotNull NativeNullable or(@NotNull NativeNullable fallback) { + default @NotNull TypedNullable or(@NotNull NativeNullable fallback) { var value = getNullable(); if (value == null) { - return fallback; + //noinspection unchecked + return (TypedNullable) fallback; } else { return this; } diff --git a/datagen/src/test/java/it/cavallium/datagen/nativedata/TestTypedNullable.java b/datagen/src/test/java/it/cavallium/datagen/nativedata/TestTypedNullable.java new file mode 100644 index 0000000..7c4137f --- /dev/null +++ b/datagen/src/test/java/it/cavallium/datagen/nativedata/TestTypedNullable.java @@ -0,0 +1,87 @@ +package it.cavallium.datagen.nativedata; + +import it.cavallium.datagen.TypedNullable; +import org.jetbrains.annotations.Nullable; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class TestTypedNullable { + @Test + public void testNullableOr() { + class TypeA { + + } + + class TypeAB extends TypeA { + + } + + var a = new TypedNullable() { + + @Override + public @Nullable TypeA getNullable() { + return new TypeA(); + } + }; + + var aNull = new TypedNullable() { + + @Override + public @Nullable TypeA getNullable() { + return null; + } + }; + + var ab = new TypedNullable() { + + @Override + public @Nullable TypeAB getNullable() { + return new TypeAB(); + } + }; + + var abNull = new TypedNullable() { + + @Override + public @Nullable TypeAB getNullable() { + return null; + } + }; + + Assertions.assertDoesNotThrow(() -> { + a.or(ab).getNullable(); + }); + + Assertions.assertDoesNotThrow(() -> { + aNull.or(ab).getNullable(); + }); + + Assertions.assertDoesNotThrow(() -> { + a.or(abNull).getNullable(); + }); + + Assertions.assertDoesNotThrow(() -> { + aNull.or(abNull).getNullable(); + }); + + Assertions.assertDoesNotThrow(() -> { + aNull.or(abNull).orElse(new TypeA()); + }); + + Assertions.assertDoesNotThrow(() -> { + aNull.or(ab).orElse(new TypeA()); + }); + + Assertions.assertDoesNotThrow(() -> { + aNull.or(ab).orElse(new TypeAB()); + }); + + Assertions.assertDoesNotThrow(() -> { + aNull.or(abNull).orElse(new TypeAB()); + }); + + Assertions.assertDoesNotThrow(() -> { + abNull.or(abNull).orElse(new TypeAB()); + }); + } +}