From bc009263b5f13ac3587a9f379d1fd0ef17dc4b8e Mon Sep 17 00:00:00 2001 From: Karlatemp Date: Wed, 17 Feb 2021 15:15:05 +0800 Subject: [PATCH] [Command] Support detect receiver parameter with first parameter; fix #295 --- .../src/internal/command/CommandReflector.kt | 21 +++++++++--- .../mirai-console/test/command/TestCommand.kt | 32 +++++++++++++++++++ 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/backend/mirai-console/src/internal/command/CommandReflector.kt b/backend/mirai-console/src/internal/command/CommandReflector.kt index 29015046f..37eaa1633 100644 --- a/backend/mirai-console/src/internal/command/CommandReflector.kt +++ b/backend/mirai-console/src/internal/command/CommandReflector.kt @@ -203,10 +203,12 @@ internal class CommandReflector( ) fun CommandParameter<*>.toErasedParameterInfo(index: Int): ErasedParameterInfo { - return ErasedParameterInfo(index, + return ErasedParameterInfo( + index, this.name, this.type.withNullability(false), - if (this is AbstractCommandValueParameter.StringConstant) this.expectingValue else null) + if (this is AbstractCommandValueParameter.StringConstant) this.expectingValue else null + ) } val candidates = signatures.map { variant -> @@ -244,11 +246,21 @@ internal class CommandReflector( name?.split(' ')?.mapIndexed { index, s -> createStringConstantParameterForName(index, s) } .orEmpty() + val valueParameters = function.valueParameters.toMutableList() + var receiverParameter = function.extensionReceiverParameter + if (receiverParameter == null && valueParameters.isNotEmpty()) { + val valueFirstParameter = valueParameters[0] + if (valueFirstParameter.type.classifierAsKClassOrNull()?.isSubclassOf(CommandSender::class) == true) { + receiverParameter = valueFirstParameter + valueParameters.removeAt(0) + } + } + val functionValueParameters = - function.valueParameters.associateBy { it.toUserDefinedCommandParameter() } + valueParameters.associateBy { it.toUserDefinedCommandParameter() } CommandSignatureFromKFunctionImpl( - receiverParameter = function.extensionReceiverParameter?.toCommandReceiverParameter(), + receiverParameter = receiverParameter?.toCommandReceiverParameter(), valueParameters = functionNameAsValueParameter + functionValueParameters.keys, originFunction = function ) { call -> @@ -272,7 +284,6 @@ internal class CommandReflector( args[instanceParameter] = command } - val receiverParameter = function.extensionReceiverParameter if (receiverParameter != null) { check(receiverParameter.type.classifierAsKClass().isInstance(call.caller)) { "Bad command call resolved. " + diff --git a/backend/mirai-console/test/command/TestCommand.kt b/backend/mirai-console/test/command/TestCommand.kt index f00898787..beee000aa 100644 --- a/backend/mirai-console/test/command/TestCommand.kt +++ b/backend/mirai-console/test/command/TestCommand.kt @@ -69,9 +69,11 @@ object TestEnumArgCommand : CompositeCommand(owner, "testenum") { enum class TestEnum { V1, V2, V3 } + enum class TestCase { A, a } + enum class TestCamelCase { A, B, A_B } @@ -295,6 +297,36 @@ internal class TestCommand { } } + @Test + fun `test first param command sender`() = runBlocking { + object : CompositeCommand(owner, "cmd") { + @SubCommand + fun handle(sender: CommandSender, arg: String) { + Testing.ok(arg) + } + }.withRegistration { + assertEquals("test", withTesting { assertSuccess(execute(sender, "handle test")) }) + } + + object : SimpleCommand(owner, "cmd") { + @Handler + fun handle(sender: CommandSender, arg: String) { + Testing.ok(arg) + } + }.withRegistration { + assertEquals("hello", withTesting { assertSuccess(execute(sender, "hello")) }) + } + + object : SimpleCommand(owner, "cmd") { + @Handler + fun handle(arg: String, sender: CommandSender) { + Testing.ok(arg) + } + }.withRegistration { + assertFailure(execute(sender, "hello")) + } + } + @Test fun `composite sub command resolution conflict`() { runBlocking {