package io.vertx.test.codegen;
import io.vertx.codegen.type.ClassKind;
import io.vertx.codegen.ClassModel;
import io.vertx.codegen.Generator;
import io.vertx.codegen.MethodInfo;
import io.vertx.codegen.MethodKind;
import io.vertx.codegen.type.ParameterizedTypeInfo;
import io.vertx.codegen.type.TypeInfo;
import io.vertx.codegen.testmodel.TestDataObject;
import io.vertx.codegen.testmodel.TestEnum;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.test.codegen.testapi.VertxGenClass1;
import io.vertx.test.codegen.testapi.nullable.DiamondGenericBottomFluentNullableParam;
import io.vertx.test.codegen.testapi.nullable.InterfaceWithInvalidListNullableParamOverride;
import io.vertx.test.codegen.testapi.nullable.InterfaceWithInvalidNullableParamOverride;
import io.vertx.test.codegen.testapi.nullable.InterfaceWithInvalidNullableReturnOverride;
import io.vertx.test.codegen.testapi.nullable.InterfaceWithNullableReturnMethod;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableTypeArgumentHandler;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableTypeArgumentHandlerAsyncResult;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableTypeArgumentParam;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableTypeArgumentReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithListNullableParamOverride;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableNonAnnotatedObjectParam;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableNonAnnotatedTypeVariableHandlerAsyncResult;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableNonAnnotatedTypeVariableHandler;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableNonAnnotatedTypeVariableParam;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableNonAnnotatedTypeVariableReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableParamOverride;
import io.vertx.test.codegen.testapi.nullable.InterfaceWithNullableReturnOverride;
import io.vertx.test.codegen.testapi.nullable.MethodWithHandlerNullable;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidHandlerNullableVoid;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidHandlerAsyncResultNullableVoid;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidHandlerNullableAsyncResult;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableBooleanReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableByteReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableCharReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableDoubleReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableFloatReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableFluentReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableIntReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableLongReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidNullableShortReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithInvalidOverloadedNullableParam;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableHandler;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableHandlerAsyncResult;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableParam;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableTypeArgReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableTypeVariableHandlerAsyncResult;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableTypeVariableHandler;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableTypeVariableParam;
import io.vertx.test.codegen.testapi.nullable.MethodWithNullableTypeVariableReturn;
import io.vertx.test.codegen.testapi.nullable.MethodWithOverloadedNullableParam;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
*/
public class ClassNullableTest extends ClassTestBase {
// Invalid params
@Test
public void testMethodWithHandlerNullableVoid() throws Exception {
assertGenInvalid(MethodWithInvalidHandlerNullableVoid.class);
}
@Test
public void testMethodWithInvalidHandlerNullableAsyncResult() throws Exception {
assertGenInvalid(MethodWithInvalidHandlerNullableAsyncResult.class);
}
@Test
public void testMethodWithInvalidHandlerAsyncResultNullableVoid() throws Exception {
assertGenInvalid(MethodWithInvalidHandlerAsyncResultNullableVoid.class);
}
@Test
public void testInterfaceWithInvalidNullableParamOverride() throws Exception {
assertGenInvalid(InterfaceWithInvalidNullableParamOverride.class);
}
@Test
public void testInterfaceWithInvalidListNullableParamOverride() throws Exception {
assertGenInvalid(InterfaceWithInvalidListNullableParamOverride.class);
}
@Test
public void testMethodWithInvalidNullableTypeArgumentParam() throws Exception {
assertGenInvalid(MethodWithInvalidNullableTypeArgumentParam.class);
}
@Test
public void testMethodWithInvalidNullableTypeArgumentHandler() throws Exception {
assertGenInvalid(MethodWithInvalidNullableTypeArgumentHandler.class);
}
@Test
public void testMethodWithInvalidNullableTypeArgumentHandlerAsyncResult() throws Exception {
assertGenInvalid(MethodWithInvalidNullableTypeArgumentHandlerAsyncResult.class);
}
// Invalid returns
@Test
public void testMethodWithInvalidNullableBooleanReturn() throws Exception {
assertGenInvalid(MethodWithInvalidNullableBooleanReturn.class);
}
@Test
public void testMethodWithInvalidNullableByteReturn() throws Exception {
assertGenInvalid(MethodWithInvalidNullableByteReturn.class);
}
@Test
public void testMethodWithInvalidNullableShortReturn() throws Exception {
assertGenInvalid(MethodWithInvalidNullableShortReturn.class);
}
@Test
public void testMethodWithInvalidNullableIntReturn() throws Exception {
assertGenInvalid(MethodWithInvalidNullableIntReturn.class);
}
@Test
public void testMethodWithInvalidNullableLongReturn() throws Exception {
assertGenInvalid(MethodWithInvalidNullableLongReturn.class);
}
@Test
public void testMethodWithInvalidNullableFloatReturn() throws Exception {
assertGenInvalid(MethodWithInvalidNullableFloatReturn.class);
}
@Test
public void testMethodWithInvalidNullableDoubleReturn() throws Exception {
assertGenInvalid(MethodWithInvalidNullableDoubleReturn.class);
}
@Test
public void testMethodWithInvalidNullableCharReturn() throws Exception {
assertGenInvalid(MethodWithInvalidNullableCharReturn.class);
}
@Test
public void testMethodWithInvalidOverloadedNullableParam() throws Exception {
assertGenInvalid(MethodWithInvalidOverloadedNullableParam.class);
}
@Test
public void testInterfaceWithInvalidNullableReturnOverride() throws Exception {
assertGenInvalid(InterfaceWithInvalidNullableReturnOverride.class);
}
@Test
public void testMethodWithInvalidNullableFluentReturn() throws Exception {
assertGenInvalid(MethodWithInvalidNullableFluentReturn.class);
}
@Test
public void testMethodWithInvalidNullableTypeArgumentReturn() throws Exception {
assertGenInvalid(MethodWithInvalidNullableTypeArgumentReturn.class);
}
// Valid params
@Test
public void testMethodWithNullableParam() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 1, "void", MethodKind.OTHER);
assertTrue(mi1.getParams().get(0).isNullable());
}, MethodWithNullableParam.class);
}
@Test
public void testMethodWithNullableHandler() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 1, "void", MethodKind.HANDLER);
assertTrue(mi1.getParams().get(0).isNullable());
}, MethodWithNullableHandler.class);
}
@Test
public void testMethodWithNullableHandlerAsyncResult() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 1, "void", MethodKind.FUTURE);
assertTrue(mi1.getParams().get(0).isNullable());
}, MethodWithNullableHandlerAsyncResult.class);
}
@Test
public void testInterfaceWithNullableParamOverride() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
assertTrue(mi1.getParams().get(0).isNullable());
}, MethodWithNullableParamOverride.class, MethodWithNullableParam.class);
}
@Test
public void testInterfaceWithListNullableParamOverride() throws Exception {
ClassModel model = new Generator().generateClass(MethodWithListNullableParamOverride.class);
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi2 = methods.get(0);
assertTrue(((ParameterizedTypeInfo) mi2.getParams().get(0).getType()).getArg(0).isNullable());
}
@Test
public void testMethodWithHandlerNullable() throws Exception {
ClassModel model = new Generator().generateClass(MethodWithHandlerNullable.class);
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
assertTrue(((ParameterizedTypeInfo) mi1.getParams().get(0).getType()).getArg(0).isNullable());
}
@Test
public void testMethodWithNullableTypeVariableParam() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 1, "void", MethodKind.OTHER);
assertTrue(mi1.getParams().get(0).isNullable());
}, MethodWithNullableTypeVariableParam.class);
}
@Test
public void testMethodWithNullableNonAnnotatedTypeVariableParam() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 1, "void", MethodKind.OTHER);
assertTrue(mi1.getParams().get(0).isNullable());
}, MethodWithNullableNonAnnotatedTypeVariableParam.class);
}
@Test
public void testMethodWithNullableNonAnnotatedObjectParam() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 1, "void", MethodKind.OTHER);
assertTrue(mi1.getParams().get(0).isNullable());
}, MethodWithNullableNonAnnotatedObjectParam.class);
}
@Test
public void testMethodWithNullableTypeVariableHandler() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 1, "void", MethodKind.HANDLER);
assertTrue(mi1.getParams().get(0).isNullableCallback());
}, MethodWithNullableTypeVariableHandler.class);
}
@Test
public void testMethodWithNullableNonAnnotatedTypeVariableHandler() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 1, "void", MethodKind.HANDLER);
assertTrue(mi1.getParams().get(0).isNullableCallback());
}, MethodWithNullableNonAnnotatedTypeVariableHandler.class);
}
@Test
public void testMethodWithNullableTypeVariableHandlerAsyncResult() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 1, "void", MethodKind.FUTURE);
assertTrue(mi1.getParams().get(0).isNullableCallback());
}, MethodWithNullableTypeVariableHandlerAsyncResult.class);
}
@Test
public void testMethodWithNullableNonAnnotatedTypeVariableHandlerAsyncResult() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 1, "void", MethodKind.FUTURE);
assertTrue(mi1.getParams().get(0).isNullableCallback());
}, MethodWithNullableNonAnnotatedTypeVariableHandlerAsyncResult.class);
}
@Test
public void testMethodWithOverloadedNullableParam() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(2, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 2, "void", MethodKind.OTHER);
assertEquals(ClassKind.STRING, mi1.getParams().get(0).getType().getKind());
checkParam(mi1.getParams().get(0), "s", String.class);
assertTrue(mi1.getParams().get(0).isNullable());
checkParam(mi1.getParams().get(1), "i", Integer.class);
assertFalse(mi1.getParams().get(1).isNullable());
MethodInfo mi2 = methods.get(1);
checkMethod(mi2, "method", 2, "void", MethodKind.OTHER);
checkParam(mi2.getParams().get(0), "i", Integer.class);
assertFalse(mi2.getParams().get(0).isNullable());
checkParam(mi2.getParams().get(1), "s", String.class);
assertTrue(mi2.getParams().get(1).isNullable());
}, MethodWithOverloadedNullableParam.class);
}
// Valid returns
@Test
public <T> void testMethodWithNullableReturn() throws Exception {
AtomicBoolean checkModel = new AtomicBoolean();
TypeLiteral<T> typeLiteral = new TypeLiteral<T>() {};
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(50, methods.size());
checkMethod(methods.get(0), "nullableByteReturn", 0, new TypeLiteral<Byte>() {}, MethodKind.OTHER);
checkMethod(methods.get(1), "nullableShortReturn", 0, new TypeLiteral<Short>() {}, MethodKind.OTHER);
checkMethod(methods.get(2), "nullableIntegerReturn", 0, new TypeLiteral<Integer>() {}, MethodKind.OTHER);
checkMethod(methods.get(3), "nullableLongReturn", 0, new TypeLiteral<Long>() {}, MethodKind.OTHER);
checkMethod(methods.get(4), "nullableFloatReturn", 0, new TypeLiteral<Float>() {}, MethodKind.OTHER);
checkMethod(methods.get(5), "nullableDoubleReturn", 0, new TypeLiteral<Double>() {}, MethodKind.OTHER);
checkMethod(methods.get(6), "nullableCharacterReturn", 0, new TypeLiteral<Character>() {}, MethodKind.OTHER);
checkMethod(methods.get(7), "nullableStringReturn", 0, new TypeLiteral<String>() {}, MethodKind.OTHER);
checkMethod(methods.get(8), "nullableJsonObjectReturn", 0, new TypeLiteral<JsonObject>() {}, MethodKind.OTHER);
checkMethod(methods.get(9), "nullableJsonArrayReturn", 0, new TypeLiteral<JsonArray>() {}, MethodKind.OTHER);
checkMethod(methods.get(10), "nullableTypeVariableReturn", 0, typeLiteral, MethodKind.OTHER);
checkMethod(methods.get(11), "nullableEnumReturn", 0, new TypeLiteral<TestEnum>() {}, MethodKind.OTHER);
checkMethod(methods.get(12), "nullableDataObjectReturn", 0, new TypeLiteral<TestDataObject>() {}, MethodKind.OTHER);
checkMethod(methods.get(13), "nullableApiReturn", 0, new TypeLiteral<VertxGenClass1>() {}, MethodKind.OTHER);
checkMethod(methods.get(14), "nullableListByteReturn", 0, new TypeLiteral<List<Byte>>() {}, MethodKind.OTHER);
checkMethod(methods.get(15), "nullableListShortReturn", 0, new TypeLiteral<List<Short>>() {}, MethodKind.OTHER);
checkMethod(methods.get(16), "nullableListIntegerReturn", 0, new TypeLiteral<List<Integer>>() {}, MethodKind.OTHER);
checkMethod(methods.get(17), "nullableListLongReturn", 0, new TypeLiteral<List<Long>>() {}, MethodKind.OTHER);
checkMethod(methods.get(18), "nullableListFloatReturn", 0, new TypeLiteral<List<Float>>() {}, MethodKind.OTHER);
checkMethod(methods.get(19), "nullableListDoubleReturn", 0, new TypeLiteral<List<Double>>() {}, MethodKind.OTHER);
checkMethod(methods.get(20), "nullableListCharacterReturn", 0, new TypeLiteral<List<Character>>() {}, MethodKind.OTHER);
checkMethod(methods.get(21), "nullableListStringReturn", 0, new TypeLiteral<List<String>>() {}, MethodKind.OTHER);
checkMethod(methods.get(22), "nullableListJsonObjectReturn", 0, new TypeLiteral<List<JsonObject>>() {}, MethodKind.OTHER);
checkMethod(methods.get(23), "nullableListJsonArrayReturn", 0, new TypeLiteral<List<JsonArray>>() {}, MethodKind.OTHER);
checkMethod(methods.get(24), "nullableListEnumReturn", 0, new TypeLiteral<List<TestEnum>>() {}, MethodKind.OTHER);
checkMethod(methods.get(25), "nullableListDataObjectReturn", 0, new TypeLiteral<List<TestDataObject>>() {}, MethodKind.OTHER);
checkMethod(methods.get(26), "nullableListApiReturn", 0, new TypeLiteral<List<VertxGenClass1>>() {}, MethodKind.OTHER);
checkMethod(methods.get(27), "nullableSetByteReturn", 0, new TypeLiteral<Set<Byte>>() {}, MethodKind.OTHER);
checkMethod(methods.get(28), "nullableSetShortReturn", 0, new TypeLiteral<Set<Short>>() {}, MethodKind.OTHER);
checkMethod(methods.get(29), "nullableSetIntegerReturn", 0, new TypeLiteral<Set<Integer>>() {}, MethodKind.OTHER);
checkMethod(methods.get(30), "nullableSetLongReturn", 0, new TypeLiteral<Set<Long>>() {}, MethodKind.OTHER);
checkMethod(methods.get(31), "nullableSetFloatReturn", 0, new TypeLiteral<Set<Float>>() {}, MethodKind.OTHER);
checkMethod(methods.get(32), "nullableSetDoubleReturn", 0, new TypeLiteral<Set<Double>>() {}, MethodKind.OTHER);
checkMethod(methods.get(33), "nullableSetCharacterReturn", 0, new TypeLiteral<Set<Character>>() {}, MethodKind.OTHER);
checkMethod(methods.get(34), "nullableSetStringReturn", 0, new TypeLiteral<Set<String>>() {}, MethodKind.OTHER);
checkMethod(methods.get(35), "nullableSetJsonObjectReturn", 0, new TypeLiteral<Set<JsonObject>>() {}, MethodKind.OTHER);
checkMethod(methods.get(36), "nullableSetJsonArrayReturn", 0, new TypeLiteral<Set<JsonArray>>() {}, MethodKind.OTHER);
checkMethod(methods.get(37), "nullableSetEnumReturn", 0, new TypeLiteral<Set<TestEnum>>() {}, MethodKind.OTHER);
checkMethod(methods.get(38), "nullableSetDataObjectReturn", 0, new TypeLiteral<Set<TestDataObject>>() {}, MethodKind.OTHER);
checkMethod(methods.get(39), "nullableSetApiReturn", 0, new TypeLiteral<Set<VertxGenClass1>>() {}, MethodKind.OTHER);
checkMethod(methods.get(40), "nullableMapByteReturn", 0, new TypeLiteral<Map<String, Byte>>() {}, MethodKind.OTHER);
checkMethod(methods.get(41), "nullableMapShortReturn", 0, new TypeLiteral<Map<String, Short>>() {}, MethodKind.OTHER);
checkMethod(methods.get(42), "nullableMapIntegerReturn", 0, new TypeLiteral<Map<String, Integer>>() {}, MethodKind.OTHER);
checkMethod(methods.get(43), "nullableMapLongReturn", 0, new TypeLiteral<Map<String, Long>>() {}, MethodKind.OTHER);
checkMethod(methods.get(44), "nullableMapFloatReturn", 0, new TypeLiteral<Map<String, Float>>() {}, MethodKind.OTHER);
checkMethod(methods.get(45), "nullableMapDoubleReturn", 0, new TypeLiteral<Map<String, Double>>() {}, MethodKind.OTHER);
checkMethod(methods.get(46), "nullableMapCharacterReturn", 0, new TypeLiteral<Map<String, Character>>() {}, MethodKind.OTHER);
checkMethod(methods.get(47), "nullableMapStringReturn", 0, new TypeLiteral<Map<String, String>>() {}, MethodKind.OTHER);
checkMethod(methods.get(48), "nullableMapJsonObjectReturn", 0, new TypeLiteral<Map<String, JsonObject>>() {}, MethodKind.OTHER);
checkMethod(methods.get(49), "nullableMapJsonArrayReturn", 0, new TypeLiteral<Map<String, JsonArray>>() {}, MethodKind.OTHER);
if (!checkModel.compareAndSet(false, true)) {
// nullableTypeVariableReturn does not pass with model api
methods.remove(10);
}
methods.forEach(m -> {
assertTrue("Expects " + m.getName() + " to have nullable return type", m.isNullableReturn());
});
}, MethodWithNullableReturn.class);
}
@Test
public void testMethodWithNullableTypeArgReturn() throws Exception {
ClassModel model = new Generator().generateClass(MethodWithNullableTypeArgReturn.class);
List<MethodInfo> methods = model.getMethods();
assertEquals(36, methods.size());
checkMethod(methods.get(0), "listNullableByteReturn", 0, new TypeLiteral<List<Byte>>() {}, MethodKind.OTHER);
checkMethod(methods.get(1), "listNullableShortReturn", 0, new TypeLiteral<List<Short>>() {}, MethodKind.OTHER);
checkMethod(methods.get(2), "listNullableIntegerReturn", 0, new TypeLiteral<List<Integer>>() {}, MethodKind.OTHER);
checkMethod(methods.get(3), "listNullableLongReturn", 0, new TypeLiteral<List<Long>>() {}, MethodKind.OTHER);
checkMethod(methods.get(4), "listNullableFloatReturn", 0, new TypeLiteral<List<Float>>() {}, MethodKind.OTHER);
checkMethod(methods.get(5), "listNullableDoubleReturn", 0, new TypeLiteral<List<Double>>() {}, MethodKind.OTHER);
checkMethod(methods.get(6), "listNullableCharacterReturn", 0, new TypeLiteral<List<Character>>() {}, MethodKind.OTHER);
checkMethod(methods.get(7), "listNullableStringReturn", 0, new TypeLiteral<List<String>>() {}, MethodKind.OTHER);
checkMethod(methods.get(8), "listNullableJsonObjectReturn", 0, new TypeLiteral<List<JsonObject>>() {}, MethodKind.OTHER);
checkMethod(methods.get(9), "listNullableJsonArrayReturn", 0, new TypeLiteral<List<JsonArray>>() {}, MethodKind.OTHER);
checkMethod(methods.get(10), "listNullableEnumReturn", 0, new TypeLiteral<List<TestEnum>>() {}, MethodKind.OTHER);
checkMethod(methods.get(11), "listNullableDataObjectReturn", 0, new TypeLiteral<List<TestDataObject>>() {}, MethodKind.OTHER);
checkMethod(methods.get(12), "listNullableApiReturn", 0, new TypeLiteral<List<VertxGenClass1>>() {}, MethodKind.OTHER);
checkMethod(methods.get(13), "setNullableByteReturn", 0, new TypeLiteral<Set<Byte>>() {}, MethodKind.OTHER);
checkMethod(methods.get(14), "setNullableShortReturn", 0, new TypeLiteral<Set<Short>>() {}, MethodKind.OTHER);
checkMethod(methods.get(15), "setNullableIntegerReturn", 0, new TypeLiteral<Set<Integer>>() {}, MethodKind.OTHER);
checkMethod(methods.get(16), "setNullableLongReturn", 0, new TypeLiteral<Set<Long>>() {}, MethodKind.OTHER);
checkMethod(methods.get(17), "setNullableFloatReturn", 0, new TypeLiteral<Set<Float>>() {}, MethodKind.OTHER);
checkMethod(methods.get(18), "setNullableDoubleReturn", 0, new TypeLiteral<Set<Double>>() {}, MethodKind.OTHER);
checkMethod(methods.get(19), "setNullableCharacterReturn", 0, new TypeLiteral<Set<Character>>() {}, MethodKind.OTHER);
checkMethod(methods.get(20), "setNullableStringReturn", 0, new TypeLiteral<Set<String>>() {}, MethodKind.OTHER);
checkMethod(methods.get(21), "setNullableJsonObjectReturn", 0, new TypeLiteral<Set<JsonObject>>() {}, MethodKind.OTHER);
checkMethod(methods.get(22), "setNullableJsonArrayReturn", 0, new TypeLiteral<Set<JsonArray>>() {}, MethodKind.OTHER);
checkMethod(methods.get(23), "setNullableEnumReturn", 0, new TypeLiteral<Set<TestEnum>>() {}, MethodKind.OTHER);
checkMethod(methods.get(24), "setNullableDataObjectReturn", 0, new TypeLiteral<Set<TestDataObject>>() {}, MethodKind.OTHER);
checkMethod(methods.get(25), "setNullableApiReturn", 0, new TypeLiteral<Set<VertxGenClass1>>() {}, MethodKind.OTHER);
checkMethod(methods.get(26), "mapNullableByteReturn", 0, new TypeLiteral<Map<String, Byte>>() {}, MethodKind.OTHER);
checkMethod(methods.get(27), "mapNullableShortReturn", 0, new TypeLiteral<Map<String, Short>>() {}, MethodKind.OTHER);
checkMethod(methods.get(28), "mapNullableIntegerReturn", 0, new TypeLiteral<Map<String, Integer>>() {}, MethodKind.OTHER);
checkMethod(methods.get(29), "mapNullableLongReturn", 0, new TypeLiteral<Map<String, Long>>() {}, MethodKind.OTHER);
checkMethod(methods.get(30), "mapNullableFloatReturn", 0, new TypeLiteral<Map<String, Float>>() {}, MethodKind.OTHER);
checkMethod(methods.get(31), "mapNullableDoubleReturn", 0, new TypeLiteral<Map<String, Double>>() {}, MethodKind.OTHER);
checkMethod(methods.get(32), "mapNullableCharacterReturn", 0, new TypeLiteral<Map<String, Character>>() {}, MethodKind.OTHER);
checkMethod(methods.get(33), "mapNullableStringReturn", 0, new TypeLiteral<Map<String, String>>() {}, MethodKind.OTHER);
checkMethod(methods.get(34), "mapNullableJsonObjectReturn", 0, new TypeLiteral<Map<String, JsonObject>>() {}, MethodKind.OTHER);
checkMethod(methods.get(35), "mapNullableJsonArrayReturn", 0, new TypeLiteral<Map<String, JsonArray>>() {}, MethodKind.OTHER);
methods.forEach(m -> {
assertFalse("Expects " + m.getName() + " to have nullable return type", m.isNullableReturn());
List<TypeInfo> args = ((ParameterizedTypeInfo) m.getReturnType()).getArgs();
assertTrue("Expects " + m.getName() + " to have nullable return type", args.get(args.size() - 1).isNullable());
});
}
@Test
public void testInterfaceWithNullableReturnOverride() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi3 = methods.get(0);
assertTrue(mi3.getReturnType().isNullable());
}, InterfaceWithNullableReturnOverride.class, InterfaceWithNullableReturnMethod.class);
}
@Test
public void testDiamondFluentNullableReturn() throws Exception {
ClassModel model = new Generator().generateClass(DiamondGenericBottomFluentNullableParam.class);
}
@Test
public void testMethodWithNullableTypeVariableReturn() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 0, "T", MethodKind.OTHER);
assertTrue(mi1.isNullableReturn());
}, MethodWithNullableTypeVariableReturn.class);
}
@Test
public void testMethodWithNullableNonAnnotatedTypeVariableReturn() throws Exception {
generateClass(model -> {
List<MethodInfo> methods = model.getMethods();
assertEquals(1, methods.size());
MethodInfo mi1 = methods.get(0);
checkMethod(mi1, "method", 0, "T", MethodKind.OTHER);
assertTrue(mi1.isNullableReturn());
}, MethodWithNullableNonAnnotatedTypeVariableReturn.class);
}
private void generateClass(Consumer<ClassModel> test, Class<?> clazz, Class<?>... rest) throws Exception {
ClassModel model = new Generator().generateClass(clazz);
test.accept(model);
Thread thread = Thread.currentThread();
ClassLoader prev = thread.getContextClassLoader();
thread.setContextClassLoader(new ClassLoader(prev) {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (name.startsWith("io.vertx.test.codegen.testapi.nullable.")) {
throw new ClassNotFoundException();
}
return super.loadClass(name);
}
});
try {
model = new Generator().generateClass(clazz, rest);
} finally {
thread.setContextClassLoader(prev);
}
test.accept(model);
}
}