diff --git a/cloud-kotlin/cloud-kotlin-coroutines-annotations/src/main/kotlin/org/incendo/cloud/kotlin/coroutines/annotations/KotlinAnnotatedMethods.kt b/cloud-kotlin/cloud-kotlin-coroutines-annotations/src/main/kotlin/org/incendo/cloud/kotlin/coroutines/annotations/KotlinAnnotatedMethods.kt index 17f02f243..700675207 100644 --- a/cloud-kotlin/cloud-kotlin-coroutines-annotations/src/main/kotlin/org/incendo/cloud/kotlin/coroutines/annotations/KotlinAnnotatedMethods.kt +++ b/cloud-kotlin/cloud-kotlin-coroutines-annotations/src/main/kotlin/org/incendo/cloud/kotlin/coroutines/annotations/KotlinAnnotatedMethods.kt @@ -252,11 +252,15 @@ private class KotlinMethodArgumentParser( @Suppress("UNCHECKED_CAST") private fun CompletableFuture<*>.mapResult(): CompletableFuture> = - thenApply { - when (it) { - null -> ArgumentParseResult.failure(IllegalArgumentException("Result not found")) - is ArgumentParseResult<*> -> it as ArgumentParseResult - else -> ArgumentParseResult.success((it as T)!!) + handle { result, exception -> + if (exception != null) { + ArgumentParseResult.failure(exception) + } else { + when (result) { + null -> ArgumentParseResult.failure(IllegalArgumentException("Result not found")) + is ArgumentParseResult<*> -> result as ArgumentParseResult + else -> ArgumentParseResult.success((result as T)!!) + } } } } diff --git a/cloud-kotlin/cloud-kotlin-coroutines-annotations/src/test/kotlin/org/incendo/cloud/kotlin/coroutines/annotations/KotlinAnnotatedMethodsTest.kt b/cloud-kotlin/cloud-kotlin-coroutines-annotations/src/test/kotlin/org/incendo/cloud/kotlin/coroutines/annotations/KotlinAnnotatedMethodsTest.kt index bde2ccadd..b352774ea 100644 --- a/cloud-kotlin/cloud-kotlin-coroutines-annotations/src/test/kotlin/org/incendo/cloud/kotlin/coroutines/annotations/KotlinAnnotatedMethodsTest.kt +++ b/cloud-kotlin/cloud-kotlin-coroutines-annotations/src/test/kotlin/org/incendo/cloud/kotlin/coroutines/annotations/KotlinAnnotatedMethodsTest.kt @@ -190,6 +190,33 @@ class KotlinAnnotatedMethodsTest { } } + @Test + fun `test suspending parser method with exception`(): Unit = runBlocking { + AnnotationParser(commandManager, TestCommandSender::class.java) + .installCoroutineSupport() + .parse(ParserMethods()) + + val commandContext = StandardCommandContextFactory(commandManager).create( + true, + TestCommandSender() + ) + + val parser = commandManager.parserRegistry().createParser( + TypeToken.get(ParserResult3::class.java), + ParserParameters.empty() + ) + + assert(parser.isPresent) { + "Suspending parser cannot be found!" + } + + val result: ArgumentParseResult<*> = parser.get().parseFuture(commandContext, CommandInput.of("5")).await() + + assert(result.failure().orElse(null) is IllegalStateException) { + "Suspending parser should fail with IllegalStateException!" + } + } + public class TestCommandSender private class TestCommandManager : CommandManager( @@ -236,6 +263,8 @@ class KotlinAnnotatedMethodsTest { data class ParserResult2(val test: Int) + data class ParserResult3(val test: Int) + class ParserMethods { @Parser @@ -249,5 +278,11 @@ class KotlinAnnotatedMethodsTest { withContext(Dispatchers.Default) { ArgumentParseResult.success(ParserResult2(input.lastRemainingToken().toInt())) } + + @Parser + suspend fun exceptionParser(input: CommandInput): ParserResult3 = + withContext(Dispatchers.Default) { + throw IllegalStateException() + } } }