diff --git a/backend/mirai-console/src/command/AbstractCommand.kt b/backend/mirai-console/src/command/AbstractCommand.kt index c9048e221..bb5163bc9 100644 --- a/backend/mirai-console/src/command/AbstractCommand.kt +++ b/backend/mirai-console/src/command/AbstractCommand.kt @@ -37,6 +37,8 @@ public abstract class AbstractCommand init { Command.checkCommandName(primaryName) + @Suppress("LeakingThis") + Command.checkCommandOwner(this) secondaryNames.forEach(Command.Companion::checkCommandName) } diff --git a/backend/mirai-console/src/command/Command.kt b/backend/mirai-console/src/command/Command.kt index 675481731..532e9b048 100644 --- a/backend/mirai-console/src/command/Command.kt +++ b/backend/mirai-console/src/command/Command.kt @@ -117,5 +117,19 @@ public interface Command { name.contains('.') -> throw IllegalArgumentException("'.' is forbidden in command name.") } } + + /** + * 检查指令 [owner] 的合法性, 在非法时抛出 [IllegalArgumentException] + */ + @JvmStatic + @Throws(IllegalArgumentException::class) + public fun checkCommandOwner(command: Command) { + val owner = command.owner + if (owner is ConsoleCommandOwner) { + if (command.javaClass.enclosingClass != BuiltInCommands::class.java) { + throw IllegalArgumentException("ConsoleCommandOwner is not allowed") + } + } + } } } diff --git a/backend/mirai-console/test/command/TestCommand.kt b/backend/mirai-console/test/command/TestCommand.kt index 7b93718b8..c2c060379 100644 --- a/backend/mirai-console/test/command/TestCommand.kt +++ b/backend/mirai-console/test/command/TestCommand.kt @@ -34,7 +34,7 @@ import org.junit.jupiter.api.Test import kotlin.test.* object TestCompositeCommand : CompositeCommand( - ConsoleCommandOwner, + owner, "testComposite", "tsC" ) { @SubCommand @@ -49,7 +49,7 @@ object TestCompositeCommand : CompositeCommand( } object TestRawCommand : RawCommand( - ConsoleCommandOwner, + owner, "testRaw" ) { override suspend fun CommandSender.onCommand(args: MessageChain) { @@ -65,7 +65,9 @@ object TestSimpleCommand : RawCommand(owner, "testSimple", "tsS") { } internal val sender by lazy { ConsoleCommandSender } -internal val owner by lazy { ConsoleCommandOwner } + +internal object TestUnitCommandOwner : CommandOwner by ConsoleCommandOwner +internal val owner by lazy { TestUnitCommandOwner } @OptIn(ExperimentalCommandDescriptors::class) @@ -88,12 +90,13 @@ internal class TestCommand { fun testRegister() { try { unregisterAllCommands(ConsoleCommandOwner) // builtins + unregisterAllCommands(owner) // testing unit unregisterCommand(TestSimpleCommand) assertTrue(TestCompositeCommand.register()) assertFalse(TestCompositeCommand.register()) - assertEquals(1, getRegisteredCommands(ConsoleCommandOwner).size) + assertEquals(1, getRegisteredCommands(owner).size) assertEquals(1, CommandManagerImpl._registeredCommands.size) assertEquals(2, @@ -198,7 +201,7 @@ internal class TestCommand { fun `composite sub command resolution conflict`() { runBlocking { val composite = object : CompositeCommand( - ConsoleCommandOwner, + owner, "tr" ) { @Suppress("UNUSED_PARAMETER") @@ -233,7 +236,7 @@ internal class TestCommand { ) val composite = object : CompositeCommand( - ConsoleCommandOwner, + owner, "test22", overrideContext = buildCommandArgumentContext { add(object : CommandValueArgumentParser { @@ -291,7 +294,7 @@ internal class TestCommand { fun `test optional argument command`() { runBlocking { val optionCommand = object : CompositeCommand( - ConsoleCommandOwner, + owner, "testOptional" ) { @SubCommand @@ -315,7 +318,7 @@ internal class TestCommand { fun `test vararg`() { runBlocking { val optionCommand = object : CompositeCommand( - ConsoleCommandOwner, + owner, "test" ) { @SubCommand