Skip to content

Commit 66a0143

Browse files
authored
fix(kotlin): propagate exceptions properly on failed parsing (#783)
1 parent 5407bf9 commit 66a0143

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

cloud-kotlin/cloud-kotlin-coroutines-annotations/src/main/kotlin/org/incendo/cloud/kotlin/coroutines/annotations/KotlinAnnotatedMethods.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,15 @@ private class KotlinMethodArgumentParser<C, T>(
252252

253253
@Suppress("UNCHECKED_CAST")
254254
private fun <T> CompletableFuture<*>.mapResult(): CompletableFuture<ArgumentParseResult<T>> =
255-
thenApply {
256-
when (it) {
257-
null -> ArgumentParseResult.failure(IllegalArgumentException("Result not found"))
258-
is ArgumentParseResult<*> -> it as ArgumentParseResult<T>
259-
else -> ArgumentParseResult.success((it as T)!!)
255+
handle { result, exception ->
256+
if (exception != null) {
257+
ArgumentParseResult.failure(exception)
258+
} else {
259+
when (result) {
260+
null -> ArgumentParseResult.failure(IllegalArgumentException("Result not found"))
261+
is ArgumentParseResult<*> -> result as ArgumentParseResult<T>
262+
else -> ArgumentParseResult.success((result as T)!!)
263+
}
260264
}
261265
}
262266
}

cloud-kotlin/cloud-kotlin-coroutines-annotations/src/test/kotlin/org/incendo/cloud/kotlin/coroutines/annotations/KotlinAnnotatedMethodsTest.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,33 @@ class KotlinAnnotatedMethodsTest {
190190
}
191191
}
192192

193+
@Test
194+
fun `test suspending parser method with exception`(): Unit = runBlocking {
195+
AnnotationParser(commandManager, TestCommandSender::class.java)
196+
.installCoroutineSupport()
197+
.parse(ParserMethods())
198+
199+
val commandContext = StandardCommandContextFactory(commandManager).create(
200+
true,
201+
TestCommandSender()
202+
)
203+
204+
val parser = commandManager.parserRegistry().createParser(
205+
TypeToken.get(ParserResult3::class.java),
206+
ParserParameters.empty()
207+
)
208+
209+
assert(parser.isPresent) {
210+
"Suspending parser cannot be found!"
211+
}
212+
213+
val result: ArgumentParseResult<*> = parser.get().parseFuture(commandContext, CommandInput.of("5")).await()
214+
215+
assert(result.failure().orElse(null) is IllegalStateException) {
216+
"Suspending parser should fail with IllegalStateException!"
217+
}
218+
}
219+
193220
public class TestCommandSender
194221

195222
private class TestCommandManager : CommandManager<TestCommandSender>(
@@ -236,6 +263,8 @@ class KotlinAnnotatedMethodsTest {
236263

237264
data class ParserResult2(val test: Int)
238265

266+
data class ParserResult3(val test: Int)
267+
239268
class ParserMethods {
240269

241270
@Parser
@@ -249,5 +278,11 @@ class KotlinAnnotatedMethodsTest {
249278
withContext(Dispatchers.Default) {
250279
ArgumentParseResult.success(ParserResult2(input.lastRemainingToken().toInt()))
251280
}
281+
282+
@Parser
283+
suspend fun exceptionParser(input: CommandInput): ParserResult3 =
284+
withContext(Dispatchers.Default) {
285+
throw IllegalStateException()
286+
}
252287
}
253288
}

0 commit comments

Comments
 (0)