Allow overriding CommandArgumentContext in JCompositeCommand and JSimpleCommand

This commit is contained in:
Him188 2022-06-17 12:26:36 +01:00
parent eeb361358a
commit 90bc48177a
5 changed files with 177 additions and 23 deletions

View File

@ -384,7 +384,7 @@ public abstract interface class net/mamoe/mirai/console/command/CommandSenderOnM
public abstract class net/mamoe/mirai/console/command/CompositeCommand : net/mamoe/mirai/console/command/AbstractCommand, net/mamoe/mirai/console/command/Command, net/mamoe/mirai/console/command/descriptor/CommandArgumentContextAware {
public fun <init> (Lnet/mamoe/mirai/console/command/CommandOwner;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Lnet/mamoe/mirai/console/permission/Permission;Lnet/mamoe/mirai/console/command/descriptor/CommandArgumentContext;)V
public synthetic fun <init> (Lnet/mamoe/mirai/console/command/CommandOwner;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Lnet/mamoe/mirai/console/permission/Permission;Lnet/mamoe/mirai/console/command/descriptor/CommandArgumentContext;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getContext ()Lnet/mamoe/mirai/console/command/descriptor/CommandArgumentContext;
public fun getContext ()Lnet/mamoe/mirai/console/command/descriptor/CommandArgumentContext;
public final fun getOverloads ()Ljava/util/List;
public fun getUsage ()Ljava/lang/String;
}
@ -1107,6 +1107,8 @@ public abstract class net/mamoe/mirai/console/command/java/JCompositeCommand : n
public fun <init> (Lnet/mamoe/mirai/console/command/CommandOwner;Ljava/lang/String;[Ljava/lang/String;)V
public fun <init> (Lnet/mamoe/mirai/console/command/CommandOwner;Ljava/lang/String;[Ljava/lang/String;Lnet/mamoe/mirai/console/permission/Permission;)V
public synthetic fun <init> (Lnet/mamoe/mirai/console/command/CommandOwner;Ljava/lang/String;[Ljava/lang/String;Lnet/mamoe/mirai/console/permission/Permission;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
protected final fun addArgumentContext (Lnet/mamoe/mirai/console/command/descriptor/CommandArgumentContext;)V
public final fun getContext ()Lnet/mamoe/mirai/console/command/descriptor/CommandArgumentContext;
public final fun getDescription ()Ljava/lang/String;
public final fun getPermission ()Lnet/mamoe/mirai/console/permission/Permission;
public final fun getPrefixOptional ()Z
@ -1139,6 +1141,7 @@ public abstract class net/mamoe/mirai/console/command/java/JSimpleCommand : net/
public fun <init> (Lnet/mamoe/mirai/console/command/CommandOwner;Ljava/lang/String;[Ljava/lang/String;)V
public fun <init> (Lnet/mamoe/mirai/console/command/CommandOwner;Ljava/lang/String;[Ljava/lang/String;Lnet/mamoe/mirai/console/permission/Permission;)V
public synthetic fun <init> (Lnet/mamoe/mirai/console/command/CommandOwner;Ljava/lang/String;[Ljava/lang/String;Lnet/mamoe/mirai/console/permission/Permission;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
protected final fun addArgumentContext (Lnet/mamoe/mirai/console/command/descriptor/CommandArgumentContext;)V
public fun getContext ()Lnet/mamoe/mirai/console/command/descriptor/CommandArgumentContext;
public fun getDescription ()Ljava/lang/String;
public fun getPermission ()Lnet/mamoe/mirai/console/permission/Permission;

View File

@ -21,6 +21,7 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalApi
import kotlin.annotation.AnnotationRetention.RUNTIME
import kotlin.annotation.AnnotationTarget.FUNCTION
/**
* 复合指令. 指令注册时候会通过反射构造指令解析器.
*
@ -68,8 +69,8 @@ import kotlin.annotation.AnnotationTarget.FUNCTION
*
* @SubCommand
* suspend fun CommandContext.repeat() {
* // 使用 CommandContext 作为参数,
* sendMessage("/manage list 被调用了")
* // 使用 CommandContext 作为参数,可以获得触发指令的原消息链 originalMessage其中包含 MessageMetadata。
* sender.sendMessage(originalMessage)
* }
*
* // 支持 Image 类型, 需在聊天中执行此指令.
@ -111,9 +112,9 @@ public abstract class CompositeCommand(
}
/**
* [CommandValueArgumentParser] 环境
*/
public final override val context: CommandArgumentContext = CommandArgumentContext.Builtins + overrideContext
* 智能参数解析环境
*/ // open since 2.12
public override val context: CommandArgumentContext = CommandArgumentContext.Builtins + overrideContext
/**
* 标记一个函数为子指令, [value] 为空时使用函数名.

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.console.command.java
@ -13,8 +13,10 @@ import net.mamoe.mirai.console.command.BuiltInCommands
import net.mamoe.mirai.console.command.CommandManager
import net.mamoe.mirai.console.command.CommandOwner
import net.mamoe.mirai.console.command.CompositeCommand
import net.mamoe.mirai.console.command.descriptor.CommandArgumentContext
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
import net.mamoe.mirai.console.command.descriptor.buildCommandArgumentContext
import net.mamoe.mirai.console.command.descriptor.plus
import net.mamoe.mirai.console.compiler.common.ResolveContext
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.COMMAND_NAME
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.RESTRICTED_CONSOLE_COMMAND_OWNER
@ -24,7 +26,7 @@ import net.mamoe.mirai.console.permission.Permission
* 复合指令. 指令注册时候会通过反射构造指令解析器.
*
* 示例:
* ```
* ```java
* public final class MyCompositeCommand extends CompositeCommand {
* public static final MyCompositeCommand INSTANCE = new MyCompositeCommand();
*
@ -52,12 +54,18 @@ import net.mamoe.mirai.console.permission.Permission
* result = ExceptionsKt.stackTraceToString(e);
* }
*
* sender.sendMessage("结果: " + result)
* sender.sendMessage("结果: " + result);
* }
*
* @SubCommand
* public void list(CommandSender sender) { // 执行 "/manage list" 时调用这个方法
* sender.sendMessage("/manage list 被调用了")
* sender.sendMessage("/manage list 被调用了");
* }
*
* @SubCommand
* public void repeat(CommandContext context) {
* // 使用 CommandContext 作为参数,可以获得触发指令的原消息链 originalMessage其中包含 MessageMetadata。
* context.getSender().sendMessage(context.getOriginalMessage());
* }
*
* // 支持 Image 类型, 需在聊天中执行此指令.
@ -91,4 +99,18 @@ public abstract class JCompositeCommand
public final override var prefixOptional: Boolean = false
protected set
/**
* 智能参数解析环境
* @since 2.12
*/
public final override var context: CommandArgumentContext = super.context
private set
/**
* 增加智能参数解析环境
* @since 2.12
*/
protected open fun addArgumentContext(context: CommandArgumentContext) {
this.context += context
}
}

View File

@ -1,19 +1,21 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.console.command.java
import net.mamoe.mirai.console.command.CommandContext
import net.mamoe.mirai.console.command.CommandManager
import net.mamoe.mirai.console.command.CommandOwner
import net.mamoe.mirai.console.command.SimpleCommand
import net.mamoe.mirai.console.command.descriptor.CommandArgumentContext
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
import net.mamoe.mirai.console.command.descriptor.plus
import net.mamoe.mirai.console.compiler.common.ResolveContext
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.COMMAND_NAME
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.RESTRICTED_CONSOLE_COMMAND_OWNER
@ -25,21 +27,23 @@ import net.mamoe.mirai.console.permission.Permission
* public final class MySimpleCommand extends JSimpleCommand {
* public static final MySimpleCommand INSTANCE = new MySimpleCommand();
* private MySimpleCommand() {
* super(MyPlugin.INSTANCE, "tell")
* super(MyPlugin.INSTANCE, "tell");
* // 可选设置如下属性
* setDescription("这是一个测试指令")
* setUsage("/tell <target> <message>") // 如不设置则自动根据带有 @Handler 的方法生成
* setPermission(CommandPermission.Operator.INSTANCE)
* setPrefixOptional(true)
* setDescription("这是一个测试指令");
* setUsage("/tell <target> <message>"); // 如不设置则自动根据带有 @Handler 的方法生成
* setPermission(CommandPermission.Operator.INSTANCE);
* setPrefixOptional(true);
* }
*
* @Handler
* public void onCommand(CommandSender sender, User target, String message) {
* target.sendMessage(message)
* target.sendMessage(message);
* }
* }
* ```
*
* 其中 `CommandSender` 也可以替换为 `CommandContext`可通过 [CommandContext.originalMessage] 获得触发指令的原消息链
*
* @see SimpleCommand
* @see [CommandManager.executeCommand]
*/
@ -57,6 +61,18 @@ public abstract class JSimpleCommand @JvmOverloads constructor(
@ExperimentalCommandDescriptors
public override var prefixOptional: Boolean = super.prefixOptional
protected set
/**
* 指令参数环境.
*/
public override var context: CommandArgumentContext = super.context
protected set
/**
* 增加智能参数解析环境
* @since 2.12
*/
protected fun addArgumentContext(context: CommandArgumentContext) {
this.context += context
}
}

View File

@ -0,0 +1,112 @@
/*
* Copyright 2019-2022 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:OptIn(ExperimentalCommandDescriptors::class)
package net.mamoe.mirai.console.command
import kotlinx.coroutines.runBlocking
import net.mamoe.mirai.console.Testing
import net.mamoe.mirai.console.command.descriptor.CommandArgumentParserException
import net.mamoe.mirai.console.command.descriptor.CommandValueArgumentParser
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
import net.mamoe.mirai.console.command.descriptor.buildCommandArgumentContext
import net.mamoe.mirai.console.command.java.JCompositeCommand
import net.mamoe.mirai.console.command.java.JSimpleCommand
import net.mamoe.mirai.console.internal.data.classifierAsKClass
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageContent
import net.mamoe.mirai.message.data.PlainText
import net.mamoe.mirai.message.data.messageChainOf
import org.junit.jupiter.api.DynamicTest
import org.junit.jupiter.api.TestFactory
import kotlin.test.assertEquals
internal class CommandValueArgumentContextTest : AbstractCommandTest() {
inner class CustomBooleanParser : CommandValueArgumentParser<Boolean> {
@Throws(CommandArgumentParserException::class)
override fun parse(raw: String, sender: CommandSender): Boolean {
return raw == "TRUE!"
}
@Throws(CommandArgumentParserException::class)
override fun parse(raw: MessageContent, sender: CommandSender): Boolean {
// 将一个图片认为是 'true'
return if (raw is Image && raw.imageId == "{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg") {
true
} else super.parse(raw, sender)
}
}
inner class JavaComposite : JCompositeCommand(mockPlugin, "main") {
init {
addArgumentContext(
buildCommandArgumentContext { java.lang.Boolean.TYPE with CustomBooleanParser() }
)
}
@SubCommand("name")
fun foo(context: CommandContext, arg: String, b: Boolean) {
Testing.ok(b)
}
}
inner class JavaSimple : JSimpleCommand(mockPlugin, "main") {
init {
addArgumentContext(
buildCommandArgumentContext { java.lang.Boolean.TYPE with CustomBooleanParser() }
)
}
@Handler
fun foo(context: CommandContext, arg: String, b: Boolean) {
Testing.ok(b)
}
}
@TestFactory
fun test(): List<DynamicTest> {
return listOf(
JavaComposite() to listOf(
messageChainOf(PlainText("/main"), PlainText("name"), PlainText("aaa"), PlainText("TRUE!")),
messageChainOf(
PlainText("/main"),
PlainText("name"),
PlainText("aaa"),
Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg")
)
), JavaSimple() to listOf(
messageChainOf(PlainText("/main"), PlainText("aaa"), PlainText("TRUE!")),
messageChainOf(
PlainText("/main"),
PlainText("aaa"),
Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg")
)
)
).flatMap { (instance, cmds) ->
cmds.map { message ->
DynamicTest.dynamicTest(instance::class.supertypes.first().classifierAsKClass().simpleName) {
runBlocking {
instance.withRegistration {
assertEquals(
true,
Testing.withTesting {
assertSuccess(
CommandManager.executeCommand(sender, message, checkPermission = false)
)
}
)
}
}
}
}
}
}
}