mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-11 02:50:15 +08:00
Fix command call
This commit is contained in:
parent
4c30e3d9d7
commit
084e2c5c55
@ -90,9 +90,9 @@ public sealed class CommandExecuteResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 没有匹配的指令 */
|
/** 没有匹配的指令 */
|
||||||
public class CommandNotFound(
|
public class UnresolvedCall(
|
||||||
/** 尝试执行的指令名 */
|
/** 尝试执行的指令名 */
|
||||||
public override val commandName: String
|
public override val commandName: String,
|
||||||
) : CommandExecuteResult() {
|
) : CommandExecuteResult() {
|
||||||
/** 指令执行时发生的错误, 总是 `null` */
|
/** 指令执行时发生的错误, 总是 `null` */
|
||||||
public override val exception: Nothing? get() = null
|
public override val exception: Nothing? get() = null
|
||||||
@ -196,19 +196,19 @@ public fun CommandExecuteResult.isPermissionDenied(): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当 [this] 为 [CommandExecuteResult.CommandNotFound] 时返回 `true`
|
* 当 [this] 为 [CommandExecuteResult.UnresolvedCall] 时返回 `true`
|
||||||
*/
|
*/
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
public fun CommandExecuteResult.isCommandNotFound(): Boolean {
|
public fun CommandExecuteResult.isCommandNotFound(): Boolean {
|
||||||
contract {
|
contract {
|
||||||
returns(true) implies (this@isCommandNotFound is CommandExecuteResult.CommandNotFound)
|
returns(true) implies (this@isCommandNotFound is CommandExecuteResult.UnresolvedCall)
|
||||||
returns(false) implies (this@isCommandNotFound !is CommandExecuteResult.CommandNotFound)
|
returns(false) implies (this@isCommandNotFound !is CommandExecuteResult.UnresolvedCall)
|
||||||
}
|
}
|
||||||
return this is CommandExecuteResult.CommandNotFound
|
return this is CommandExecuteResult.UnresolvedCall
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当 [this] 为 [CommandExecuteResult.ExecutionFailed], [CommandExecuteResult.IllegalArgument] 或 [CommandExecuteResult.CommandNotFound] 时返回 `true`
|
* 当 [this] 为 [CommandExecuteResult.ExecutionFailed], [CommandExecuteResult.IllegalArgument] 或 [CommandExecuteResult.UnresolvedCall] 时返回 `true`
|
||||||
*/
|
*/
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
public fun CommandExecuteResult.isFailure(): Boolean {
|
public fun CommandExecuteResult.isFailure(): Boolean {
|
||||||
|
@ -228,8 +228,8 @@ internal suspend fun executeCommandImpl(
|
|||||||
caller: CommandSender,
|
caller: CommandSender,
|
||||||
checkPermission: Boolean,
|
checkPermission: Boolean,
|
||||||
): CommandExecuteResult = with(receiver) {
|
): CommandExecuteResult = with(receiver) {
|
||||||
val call = message.asMessageChain().parseCommandCall(caller) ?: return CommandExecuteResult.CommandNotFound("")
|
val call = message.asMessageChain().parseCommandCall(caller) ?: return CommandExecuteResult.UnresolvedCall("")
|
||||||
val resolved = call.resolve() ?: return CommandExecuteResult.CommandNotFound(call.calleeName)
|
val resolved = call.resolve() ?: return CommandExecuteResult.UnresolvedCall(call.calleeName)
|
||||||
|
|
||||||
val command = resolved.callee
|
val command = resolved.callee
|
||||||
|
|
||||||
|
@ -62,12 +62,16 @@ public abstract class SimpleCommand(
|
|||||||
CommandArgumentContextAware {
|
CommandArgumentContextAware {
|
||||||
|
|
||||||
@ExperimentalCommandDescriptors
|
@ExperimentalCommandDescriptors
|
||||||
override val overloads: List<CommandSignatureVariant> = listOf(
|
override val overloads: List<CommandSignatureVariant> by lazy {
|
||||||
CommandSignatureVariantImpl(listOf(CommandValueParameter.UserDefinedType.createRequired<MessageChain>("args", true))) { call ->
|
CommandSignatureVariantImpl(
|
||||||
|
valueParameters = subCommands.single().params.map {
|
||||||
|
CommandValueParameter.UserDefinedType(it.name, null, isOptional = false, isVararg = false, type = it.type)
|
||||||
|
}
|
||||||
|
) { call ->
|
||||||
val sender = call.caller
|
val sender = call.caller
|
||||||
subCommands.single().onCommand(sender, call.resolvedValueArguments)
|
subCommands.single().onCommand(sender, call.resolvedValueArguments)
|
||||||
|
}.let { listOf(it) }
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自动根据带有 [Handler] 注解的函数签名生成 [usage]. 也可以被覆盖.
|
* 自动根据带有 [Handler] 注解的函数签名生成 [usage]. 也可以被覆盖.
|
||||||
|
@ -81,7 +81,7 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by MiraiCons
|
|||||||
sender.catchExecutionException(result.exception)
|
sender.catchExecutionException(result.exception)
|
||||||
intercept()
|
intercept()
|
||||||
}
|
}
|
||||||
is CommandExecuteResult.CommandNotFound -> {
|
is CommandExecuteResult.UnresolvedCall -> {
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,11 +140,11 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by MiraiCons
|
|||||||
override fun Command.unregister(): Boolean = modifyLock.withLock {
|
override fun Command.unregister(): Boolean = modifyLock.withLock {
|
||||||
if (this.prefixOptional) {
|
if (this.prefixOptional) {
|
||||||
this.allNames.forEach {
|
this.allNames.forEach {
|
||||||
optionalPrefixCommandMap.remove(it)
|
optionalPrefixCommandMap.remove(it.toLowerCase())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.allNames.forEach {
|
this.allNames.forEach {
|
||||||
requiredPrefixCommandMap.remove(it)
|
requiredPrefixCommandMap.remove(it.toLowerCase())
|
||||||
}
|
}
|
||||||
_registeredCommands.remove(this)
|
_registeredCommands.remove(this)
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ package net.mamoe.mirai.console.internal.command
|
|||||||
|
|
||||||
import net.mamoe.mirai.console.command.*
|
import net.mamoe.mirai.console.command.*
|
||||||
import net.mamoe.mirai.console.command.descriptor.*
|
import net.mamoe.mirai.console.command.descriptor.*
|
||||||
|
import net.mamoe.mirai.console.internal.command.hasAnnotation
|
||||||
import net.mamoe.mirai.console.permission.Permission
|
import net.mamoe.mirai.console.permission.Permission
|
||||||
import net.mamoe.mirai.message.data.MessageChain
|
import net.mamoe.mirai.message.data.MessageChain
|
||||||
import net.mamoe.mirai.message.data.PlainText
|
import net.mamoe.mirai.message.data.PlainText
|
||||||
@ -22,10 +23,7 @@ import kotlin.reflect.KAnnotatedElement
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KFunction
|
import kotlin.reflect.KFunction
|
||||||
import kotlin.reflect.KParameter
|
import kotlin.reflect.KParameter
|
||||||
import kotlin.reflect.full.callSuspendBy
|
import kotlin.reflect.full.*
|
||||||
import kotlin.reflect.full.declaredFunctions
|
|
||||||
import kotlin.reflect.full.findAnnotation
|
|
||||||
import kotlin.reflect.full.isSubclassOf
|
|
||||||
|
|
||||||
internal object CompositeCommandSubCommandAnnotationResolver :
|
internal object CompositeCommandSubCommandAnnotationResolver :
|
||||||
AbstractReflectionCommand.SubCommandAnnotationResolver {
|
AbstractReflectionCommand.SubCommandAnnotationResolver {
|
||||||
@ -322,7 +320,9 @@ internal fun AbstractReflectionCommand.createSubCommand(
|
|||||||
subDescription, // overridePermission?.value
|
subDescription, // overridePermission?.value
|
||||||
permission,//overridePermission?.value?.let { PermissionService.INSTANCE[PermissionId.parseFromString(it)] } ?: permission,
|
permission,//overridePermission?.value?.let { PermissionService.INSTANCE[PermissionId.parseFromString(it)] } ?: permission,
|
||||||
onCommand = { _: CommandSender, args ->
|
onCommand = { _: CommandSender, args ->
|
||||||
val result = function.callSuspendBy(parameters.zip(args).toMap())
|
val p = parameters.zip(args).toMap(LinkedHashMap())
|
||||||
|
if (notStatic) p[function.instanceParameter!!] = this@createSubCommand
|
||||||
|
val result = function.callSuspendBy(p)
|
||||||
|
|
||||||
checkNotNull(result) { "sub command return value is null (at ${this::class.qualifiedName}.${function.name})" }
|
checkNotNull(result) { "sub command return value is null (at ${this::class.qualifiedName}.${function.name})" }
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ internal class TestCommand {
|
|||||||
fun testRegister() {
|
fun testRegister() {
|
||||||
try {
|
try {
|
||||||
ConsoleCommandOwner.unregisterAllCommands() // builtins
|
ConsoleCommandOwner.unregisterAllCommands() // builtins
|
||||||
|
TestSimpleCommand.unregister()
|
||||||
|
|
||||||
assertTrue(TestCompositeCommand.register())
|
assertTrue(TestCompositeCommand.register())
|
||||||
assertFalse(TestCompositeCommand.register())
|
assertFalse(TestCompositeCommand.register())
|
||||||
@ -80,7 +81,9 @@ internal class TestCommand {
|
|||||||
assertEquals(1, ConsoleCommandOwner.registeredCommands.size)
|
assertEquals(1, ConsoleCommandOwner.registeredCommands.size)
|
||||||
|
|
||||||
assertEquals(1, CommandManagerImpl._registeredCommands.size)
|
assertEquals(1, CommandManagerImpl._registeredCommands.size)
|
||||||
assertEquals(2, CommandManagerImpl.requiredPrefixCommandMap.size)
|
assertEquals(2,
|
||||||
|
CommandManagerImpl.requiredPrefixCommandMap.size,
|
||||||
|
CommandManagerImpl.requiredPrefixCommandMap.entries.joinToString { it.toString() })
|
||||||
} finally {
|
} finally {
|
||||||
TestCompositeCommand.unregister()
|
TestCompositeCommand.unregister()
|
||||||
}
|
}
|
||||||
@ -107,15 +110,18 @@ internal class TestCommand {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSimpleArgsSplitting() = runBlocking {
|
fun testSimpleArgsSplitting() = runBlocking {
|
||||||
|
TestSimpleCommand.withRegistration {
|
||||||
assertEquals(arrayOf("test", "ttt", "tt").joinToString(), withTesting<MessageChain> {
|
assertEquals(arrayOf("test", "ttt", "tt").joinToString(), withTesting<MessageChain> {
|
||||||
assertSuccess(TestSimpleCommand.execute(sender, PlainText("test ttt tt")))
|
assertSuccess(TestSimpleCommand.execute(sender, PlainText("test ttt tt")))
|
||||||
}.joinToString())
|
}.joinToString())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val image = Image("/f8f1ab55-bf8e-4236-b55e-955848d7069f")
|
val image = Image("/f8f1ab55-bf8e-4236-b55e-955848d7069f")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `PlainText and Image args splitting`() = runBlocking {
|
fun `PlainText and Image args splitting`() = runBlocking {
|
||||||
|
TestSimpleCommand.withRegistration {
|
||||||
val result = withTesting<MessageChain> {
|
val result = withTesting<MessageChain> {
|
||||||
assertSuccess(TestSimpleCommand.execute(sender, buildMessageChain {
|
assertSuccess(TestSimpleCommand.execute(sender, buildMessageChain {
|
||||||
+"test"
|
+"test"
|
||||||
@ -126,6 +132,7 @@ internal class TestCommand {
|
|||||||
assertEquals<Any>(arrayOf("test", image, "tt").joinToString(), result.toTypedArray().joinToString())
|
assertEquals<Any>(arrayOf("test", image, "tt").joinToString(), result.toTypedArray().joinToString())
|
||||||
assertSame(image, result[1])
|
assertSame(image, result[1])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test throw Exception`() {
|
fun `test throw Exception`() {
|
||||||
@ -147,10 +154,12 @@ internal class TestCommand {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `composite command executing`() = runBlocking {
|
fun `composite command executing`() = runBlocking {
|
||||||
|
TestCompositeCommand.withRegistration {
|
||||||
assertEquals(1, withTesting {
|
assertEquals(1, withTesting {
|
||||||
assertSuccess(TestCompositeCommand.execute(sender, "mute 1"))
|
assertSuccess(TestCompositeCommand.execute(sender, "mute 1"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `composite sub command resolution conflict`() {
|
fun `composite sub command resolution conflict`() {
|
||||||
@ -187,7 +196,7 @@ internal class TestCommand {
|
|||||||
fun `composite sub command parsing`() {
|
fun `composite sub command parsing`() {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
class MyClass(
|
class MyClass(
|
||||||
val value: Int
|
val value: Int,
|
||||||
)
|
)
|
||||||
|
|
||||||
val composite = object : CompositeCommand(
|
val composite = object : CompositeCommand(
|
||||||
@ -215,10 +224,12 @@ internal class TestCommand {
|
|||||||
composite.withRegistration {
|
composite.withRegistration {
|
||||||
assertEquals(333, withTesting<MyClass> { execute(sender, "mute 333") }.value)
|
assertEquals(333, withTesting<MyClass> { execute(sender, "mute 333") }.value)
|
||||||
assertEquals(2, withTesting<MyClass> {
|
assertEquals(2, withTesting<MyClass> {
|
||||||
|
assertSuccess(
|
||||||
execute(sender, buildMessageChain {
|
execute(sender, buildMessageChain {
|
||||||
+"mute"
|
+"mute"
|
||||||
+image
|
+image
|
||||||
})
|
})
|
||||||
|
)
|
||||||
}.value)
|
}.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user