Support nullable Kotlin value class arguments

This commit skips the value class parameter instantiation for nullable
types when a null argument is passed.

Closes gh-32353
This commit is contained in:
Sébastien Deleuze
2024-03-03 22:23:57 +01:00
parent 877e0b1483
commit 516a203703
6 changed files with 86 additions and 20 deletions

View File

@@ -115,18 +115,20 @@ public abstract class CoroutinesUtils {
switch (parameter.getKind()) {
case INSTANCE -> argMap.put(parameter, target);
case VALUE, EXTENSION_RECEIVER -> {
if (!parameter.isOptional() || args[index] != null) {
Object arg = args[index];
if (!(parameter.isOptional() && arg == null)) {
if (parameter.getType().getClassifier() instanceof KClass<?> kClass) {
Class<?> javaClass = JvmClassMappingKt.getJavaClass(kClass);
if (KotlinDetector.isInlineClass(javaClass)) {
argMap.put(parameter, KClasses.getPrimaryConstructor(kClass).call(args[index]));
if (KotlinDetector.isInlineClass(javaClass)
&& !(parameter.getType().isMarkedNullable() && arg == null)) {
argMap.put(parameter, KClasses.getPrimaryConstructor(kClass).call(arg));
}
else {
argMap.put(parameter, args[index]);
argMap.put(parameter, arg);
}
}
else {
argMap.put(parameter, args[index]);
argMap.put(parameter, arg);
}
}
index++;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -82,6 +82,15 @@ class CoroutinesUtilsTests {
.verify()
}
@Test
fun invokeSuspendingFunctionWithNullableParameter() {
val method = CoroutinesUtilsTests::class.java.getDeclaredMethod("suspendingFunctionWithNullable", String::class.java, Continuation::class.java)
val mono = CoroutinesUtils.invokeSuspendingFunction(method, this, null, null) as Mono
runBlocking {
Assertions.assertThat(mono.awaitSingleOrNull()).isNull()
}
}
@Test
fun invokeNonSuspendingFunction() {
val method = CoroutinesUtilsTests::class.java.getDeclaredMethod("nonSuspendingFunction", String::class.java)
@@ -165,6 +174,15 @@ class CoroutinesUtilsTests {
}
}
@Test
fun invokeSuspendingFunctionWithNullableValueClassParameter() {
val method = CoroutinesUtilsTests::class.java.declaredMethods.first { it.name.startsWith("suspendingFunctionWithNullableValueClass") }
val mono = CoroutinesUtils.invokeSuspendingFunction(method, this, null, null) as Mono
runBlocking {
Assertions.assertThat(mono.awaitSingleOrNull()).isNull()
}
}
@Test
fun invokeSuspendingFunctionWithExtension() {
val method = CoroutinesUtilsTests::class.java.getDeclaredMethod("suspendingFunctionWithExtension",
@@ -190,6 +208,11 @@ class CoroutinesUtilsTests {
return value
}
suspend fun suspendingFunctionWithNullable(value: String?): String? {
delay(1)
return value
}
suspend fun suspendingFunctionWithFlow(): Flow<String> {
delay(1)
return flowOf("foo", "bar")
@@ -222,6 +245,11 @@ class CoroutinesUtilsTests {
return value.value
}
suspend fun suspendingFunctionWithNullableValueClass(value: ValueClass?): String? {
delay(1)
return value?.value
}
suspend fun CustomException.suspendingFunctionWithExtension(): String {
delay(1)
return "${this.message}"