Skip to content

Commit

Permalink
Fix handling of value class with private constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
T45K authored and sdeleuze committed Mar 28, 2024
1 parent 88b9c05 commit b28153e
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ public static Publisher<?> invokeSuspendingFunction(
KType type = parameter.getType();
if (!(type.isMarkedNullable() && arg == null) && type.getClassifier() instanceof KClass<?> kClass
&& KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
arg = KClasses.getPrimaryConstructor(kClass).call(arg);
KFunction<?> valueClassConstructor = KClasses.getPrimaryConstructor(kClass);
KCallablesJvm.setAccessible(valueClassConstructor, true);
arg = valueClassConstructor.call(arg);
}
argMap.put(parameter, arg);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import reactor.core.publisher.Mono
import reactor.test.StepVerifier
import kotlin.coroutines.Continuation
import kotlin.coroutines.coroutineContext
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.isAccessible

/**
* Kotlin tests for [CoroutinesUtils].
Expand Down Expand Up @@ -206,6 +208,15 @@ class CoroutinesUtilsTests {
}
}

@Test
fun invokeSuspendingFunctionWithValueClassWithPrivateConstructorParameter() {
val method = CoroutinesUtilsTests::class.java.declaredMethods.first { it.name.startsWith("suspendingFunctionWithValueClassWithPrivateConstructor") }
val mono = CoroutinesUtils.invokeSuspendingFunction(method, this, "foo", null) as Mono
runBlocking {
Assertions.assertThat(mono.awaitSingleOrNull()).isEqualTo("foo")
}
}

@Test
fun invokeSuspendingFunctionWithExtension() {
val method = CoroutinesUtilsTests::class.java.getDeclaredMethod("suspendingFunctionWithExtension",
Expand Down Expand Up @@ -293,6 +304,11 @@ class CoroutinesUtilsTests {
return value?.value
}

suspend fun suspendingFunctionWithValueClassWithPrivateConstructor(value: ValueClassWithPrivateConstructor): String? {
delay(1)
return value.value
}

suspend fun CustomException.suspendingFunctionWithExtension(): String {
delay(1)
return "${this.message}"
Expand Down Expand Up @@ -331,6 +347,13 @@ class CoroutinesUtilsTests {
}
}

@JvmInline
value class ValueClassWithPrivateConstructor private constructor(val value: String) {
companion object {
fun from(value: String) = ValueClassWithPrivateConstructor(value)
}
}

class CustomException(message: String) : Throwable(message)

}
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,9 @@ public static Object invokeFunction(Method method, Object target, Object[] args)
KType type = parameter.getType();
if (!(type.isMarkedNullable() && arg == null) && type.getClassifier() instanceof KClass<?> kClass
&& KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
arg = KClasses.getPrimaryConstructor(kClass).call(arg);
KFunction<?> valueClassConstructor = KClasses.getPrimaryConstructor(kClass);
KCallablesJvm.setAccessible(valueClassConstructor, true);
arg = valueClassConstructor.call(arg);
}
argMap.put(parameter, arg);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ class InvocableHandlerMethodKotlinTests {
Assertions.assertThat(value).isNull()
}

@Test
fun valueClassWithPrivateConstructor() {
composite.addResolver(StubArgumentResolver(Char::class.java, 'a'))
val value = getInvocable(ValueClassHandler::class.java, Char::class.java).invokeForRequest(request, null)
Assertions.assertThat(value).isEqualTo('a')
}

@Test
fun propertyAccessor() {
val value = getInvocable(PropertyAccessorHandler::class.java).invokeForRequest(request, null)
Expand Down Expand Up @@ -191,6 +198,8 @@ class InvocableHandlerMethodKotlinTests {
fun valueClassWithNullable(limit: LongValueClass?) =
limit?.value

fun valueClassWithPrivateConstructor(limit: ValueClassWithPrivateConstructor) =
limit.value
}

private class PropertyAccessorHandler {
Expand Down Expand Up @@ -238,6 +247,13 @@ class InvocableHandlerMethodKotlinTests {
}
}

@JvmInline
value class ValueClassWithPrivateConstructor private constructor(val value: Char) {
companion object {
fun from(value: Char) = ValueClassWithPrivateConstructor(value)
}
}

class CustomException(message: String) : Throwable(message)

}
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,9 @@ public static Object invokeFunction(Method method, Object target, Object[] args,
KType type = parameter.getType();
if (!(type.isMarkedNullable() && arg == null) && type.getClassifier() instanceof KClass<?> kClass
&& KotlinDetector.isInlineClass(JvmClassMappingKt.getJavaClass(kClass))) {
arg = KClasses.getPrimaryConstructor(kClass).call(arg);
KFunction<?> valueClassConstructor = KClasses.getPrimaryConstructor(kClass);
KCallablesJvm.setAccessible(valueClassConstructor, true);
arg = valueClassConstructor.call(arg);
}
argMap.put(parameter, arg);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,14 @@ class InvocableHandlerMethodKotlinTests {
assertHandlerResultValue(result, "null")
}

@Test
fun valueClassWithPrivateConstructor() {
this.resolvers.add(stubResolver(1L, Long::class.java))
val method = ValueClassController::valueClassWithPrivateConstructor.javaMethod!!
val result = invoke(ValueClassController(), method, 1L)
assertHandlerResultValue(result, "1")
}

@Test
fun propertyAccessor() {
this.resolvers.add(stubResolver(null, String::class.java))
Expand Down Expand Up @@ -368,6 +376,8 @@ class InvocableHandlerMethodKotlinTests {
fun valueClassWithNullable(limit: LongValueClass?) =
"${limit?.value}"

fun valueClassWithPrivateConstructor(limit: ValueClassWithPrivateConstructor) =
"${limit.value}"
}

class PropertyAccessorController {
Expand Down Expand Up @@ -416,5 +426,12 @@ class InvocableHandlerMethodKotlinTests {
}
}

@JvmInline
value class ValueClassWithPrivateConstructor private constructor(val value: Long) {
companion object {
fun from(value: Long) = ValueClassWithPrivateConstructor(value)
}
}

class CustomException(message: String) : Throwable(message)
}

0 comments on commit b28153e

Please sign in to comment.