CommandValueArgumentParser

This commit is contained in:
Him188 2020-10-09 12:35:16 +08:00
parent 1e9b498ba9
commit 86c3b18bca
12 changed files with 122 additions and 110 deletions

View File

@ -150,8 +150,8 @@ public object BuiltInCommands {
ConsoleCommandOwner, "permission", "权限", "perm",
description = "管理权限",
overrideContext = buildCommandArgumentContext {
PermitteeId::class with PermitteeIdArgumentParser
Permission::class with PermissionIdArgumentParser.map { id ->
PermitteeId::class with PermitteeIdValueArgumentParser
Permission::class with PermissionIdValueArgumentParser.map { id ->
kotlin.runCatching {
id.findCorrespondingPermissionOrFail()
}.getOrElse { illegalArgument("指令不存在: $id", it) }

View File

@ -99,7 +99,7 @@ public abstract class CompositeCommand(
public override val usage: String get() = super.usage
/**
* [CommandArgumentParser] 的环境
* [CommandValueArgumentParser] 的环境
*/
public final override val context: CommandArgumentContext = CommandArgumentContext.Builtins + overrideContext

View File

@ -31,7 +31,7 @@ import net.mamoe.mirai.message.data.MessageChain
* 简单的, 支持参数自动解析的指令.
*
* 要查看指令解析流程, 参考 [CommandManager.executeCommand]
* 要查看参数解析方式, 参考 [CommandArgumentParser]
* 要查看参数解析方式, 参考 [CommandValueArgumentParser]
*
* Kotlin 实现:
* ```

View File

@ -29,7 +29,7 @@ import kotlin.reflect.full.isSubclassOf
/**
* 指令参数环境, [CommandArgumentParser] 的集合, 用于 [CompositeCommand] [SimpleCommand].
* 指令参数环境, [CommandValueArgumentParser] 的集合, 用于 [CompositeCommand] [SimpleCommand].
*
* 在指令解析时, 总是从 [CommandArgumentContextAware.context] 搜索相关解析器
*
@ -38,20 +38,20 @@ import kotlin.reflect.full.isSubclassOf
* @see SimpleCommandArgumentContext 简单实现
* @see EmptyCommandArgumentContext 空实现, 类似 [emptyList]
*
* @see CommandArgumentContext.Builtins 内建 [CommandArgumentParser]
* @see CommandArgumentContext.Builtins 内建 [CommandValueArgumentParser]
*
* @see buildCommandArgumentContext DSL 构造
*/
public interface CommandArgumentContext {
/**
* [KClass] [CommandArgumentParser] 的匹配
* [KClass] [CommandValueArgumentParser] 的匹配
*/
public data class ParserPair<T : Any>(
val klass: KClass<T>,
val parser: CommandArgumentParser<T>,
val parser: CommandValueArgumentParser<T>,
)
public operator fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>?
public operator fun <T : Any> get(klass: KClass<out T>): CommandValueArgumentParser<T>?
public fun toList(): List<ParserPair<*>>
@ -66,32 +66,32 @@ public interface CommandArgumentContext {
}
/**
* 内建的默认 [CommandArgumentParser]
* 内建的默认 [CommandValueArgumentParser]
*/
public object Builtins : CommandArgumentContext by (buildCommandArgumentContext {
Int::class with IntArgumentParser
Byte::class with ByteArgumentParser
Short::class with ShortArgumentParser
Boolean::class with BooleanArgumentParser
String::class with StringArgumentParser
Long::class with LongArgumentParser
Double::class with DoubleArgumentParser
Float::class with FloatArgumentParser
Int::class with IntValueArgumentParser
Byte::class with ByteValueArgumentParser
Short::class with ShortValueArgumentParser
Boolean::class with BooleanValueArgumentParser
String::class with StringValueArgumentParser
Long::class with LongValueArgumentParser
Double::class with DoubleValueArgumentParser
Float::class with FloatValueArgumentParser
Image::class with ImageArgumentParser
PlainText::class with PlainTextArgumentParser
Image::class with ImageValueArgumentParser
PlainText::class with PlainTextValueArgumentParser
Contact::class with ExistingContactArgumentParser
User::class with ExistingUserArgumentParser
Member::class with ExistingMemberArgumentParser
Group::class with ExistingGroupArgumentParser
Friend::class with ExistingFriendArgumentParser
Bot::class with ExistingBotArgumentParser
Contact::class with ExistingContactValueArgumentParser
User::class with ExistingUserValueArgumentParser
Member::class with ExistingMemberValueArgumentParser
Group::class with ExistingGroupValueArgumentParser
Friend::class with ExistingFriendValueArgumentParser
Bot::class with ExistingBotValueArgumentParser
PermissionId::class with PermissionIdArgumentParser
PermitteeId::class with PermitteeIdArgumentParser
PermissionId::class with PermissionIdValueArgumentParser
PermitteeId::class with PermitteeIdValueArgumentParser
MessageContent::class with RawContentArgumentParser
MessageContent::class with RawContentValueArgumentParser
})
}
@ -103,7 +103,7 @@ public interface CommandArgumentContext {
*/
public interface CommandArgumentContextAware {
/**
* [CommandArgumentParser] 的集合
* [CommandValueArgumentParser] 的集合
*/
public val context: CommandArgumentContext
}
@ -117,7 +117,7 @@ public operator fun CommandArgumentContext.plus(replacer: CommandArgumentContext
if (replacer == EmptyCommandArgumentContext) return this
if (this == EmptyCommandArgumentContext) return replacer
return object : CommandArgumentContext {
override fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>? =
override fun <T : Any> get(klass: KClass<out T>): CommandValueArgumentParser<T>? =
replacer[klass] ?: this@plus[klass]
override fun toList(): List<ParserPair<*>> = replacer.toList() + this@plus.toList()
@ -132,8 +132,8 @@ public operator fun CommandArgumentContext.plus(replacer: List<ParserPair<*>>):
if (this == EmptyCommandArgumentContext) return SimpleCommandArgumentContext(replacer)
return object : CommandArgumentContext {
@Suppress("UNCHECKED_CAST")
override fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>? =
replacer.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandArgumentParser<T>?
override fun <T : Any> get(klass: KClass<out T>): CommandValueArgumentParser<T>? =
replacer.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandValueArgumentParser<T>?
?: this@plus[klass]
override fun toList(): List<ParserPair<*>> = replacer.toList() + this@plus.toList()
@ -149,9 +149,9 @@ public operator fun CommandArgumentContext.plus(replacer: List<ParserPair<*>>):
public class SimpleCommandArgumentContext(
public val list: List<ParserPair<*>>,
) : CommandArgumentContext {
override fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>? =
override fun <T : Any> get(klass: KClass<out T>): CommandValueArgumentParser<T>? =
(this.list.firstOrNull { klass == it.klass }?.parser
?: this.list.firstOrNull { klass.isSubclassOf(it.klass) }?.parser) as CommandArgumentParser<T>?
?: this.list.firstOrNull { klass.isSubclassOf(it.klass) }?.parser) as CommandValueArgumentParser<T>?
override fun toList(): List<ParserPair<*>> = list
}
@ -203,14 +203,14 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
* 添加一个指令解析器.
*/
@JvmName("add")
public infix fun <T : Any> Class<T>.with(parser: CommandArgumentParser<T>): CommandArgumentContextBuilder =
public infix fun <T : Any> Class<T>.with(parser: CommandValueArgumentParser<T>): CommandArgumentContextBuilder =
this.kotlin with parser
/**
* 添加一个指令解析器
*/
@JvmName("add")
public inline infix fun <T : Any> KClass<T>.with(parser: CommandArgumentParser<T>): CommandArgumentContextBuilder {
public inline infix fun <T : Any> KClass<T>.with(parser: CommandValueArgumentParser<T>): CommandArgumentContextBuilder {
add(ParserPair(this, parser))
return this@CommandArgumentContextBuilder
}
@ -221,9 +221,9 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
@JvmSynthetic
@LowPriorityInOverloadResolution
public inline infix fun <T : Any> KClass<T>.with(
crossinline parser: CommandArgumentParser<T>.(s: String, sender: CommandSender) -> T,
crossinline parser: CommandValueArgumentParser<T>.(s: String, sender: CommandSender) -> T,
): CommandArgumentContextBuilder {
add(ParserPair(this, object : CommandArgumentParser<T> {
add(ParserPair(this, object : CommandValueArgumentParser<T> {
override fun parse(raw: String, sender: CommandSender): T = parser(raw, sender)
}))
return this@CommandArgumentContextBuilder
@ -234,16 +234,16 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
*/
@JvmSynthetic
public inline infix fun <T : Any> KClass<T>.with(
crossinline parser: CommandArgumentParser<T>.(s: String) -> T,
crossinline parser: CommandValueArgumentParser<T>.(s: String) -> T,
): CommandArgumentContextBuilder {
add(ParserPair(this, object : CommandArgumentParser<T> {
add(ParserPair(this, object : CommandValueArgumentParser<T> {
override fun parse(raw: String, sender: CommandSender): T = parser(raw)
}))
return this@CommandArgumentContextBuilder
}
@JvmSynthetic
public inline fun <reified T : Any> add(parser: CommandArgumentParser<T>): CommandArgumentContextBuilder {
public inline fun <reified T : Any> add(parser: CommandValueArgumentParser<T>): CommandArgumentContextBuilder {
add(ParserPair(T::class, parser))
return this@CommandArgumentContextBuilder
}
@ -254,8 +254,8 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
@ConsoleExperimentalApi
@JvmSynthetic
public inline infix fun <reified T : Any> add(
crossinline parser: CommandArgumentParser<*>.(s: String) -> T,
): CommandArgumentContextBuilder = T::class with object : CommandArgumentParser<T> {
crossinline parser: CommandValueArgumentParser<*>.(s: String) -> T,
): CommandArgumentContextBuilder = T::class with object : CommandValueArgumentParser<T> {
override fun parse(raw: String, sender: CommandSender): T = parser(raw)
}
@ -266,8 +266,8 @@ public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutab
@JvmSynthetic
@LowPriorityInOverloadResolution
public inline infix fun <reified T : Any> add(
crossinline parser: CommandArgumentParser<*>.(s: String, sender: CommandSender) -> T,
): CommandArgumentContextBuilder = T::class with object : CommandArgumentParser<T> {
crossinline parser: CommandValueArgumentParser<*>.(s: String, sender: CommandSender) -> T,
): CommandArgumentContextBuilder = T::class with object : CommandValueArgumentParser<T> {
override fun parse(raw: String, sender: CommandSender): T = parser(raw, sender)
}

View File

@ -25,7 +25,7 @@ import net.mamoe.mirai.message.data.*
/**
* 使用 [String.toInt] 解析
*/
public object IntArgumentParser : InternalCommandArgumentParserExtensions<Int> {
public object IntValueArgumentParser : InternalCommandValueArgumentParserExtensions<Int> {
public override fun parse(raw: String, sender: CommandSender): Int =
raw.toIntOrNull() ?: illegalArgument("无法解析 $raw 为整数")
}
@ -33,7 +33,7 @@ public object IntArgumentParser : InternalCommandArgumentParserExtensions<Int> {
/**
* 使用 [String.toLong] 解析
*/
public object LongArgumentParser : InternalCommandArgumentParserExtensions<Long> {
public object LongValueArgumentParser : InternalCommandValueArgumentParserExtensions<Long> {
public override fun parse(raw: String, sender: CommandSender): Long =
raw.toLongOrNull() ?: illegalArgument("无法解析 $raw 为长整数")
}
@ -41,7 +41,7 @@ public object LongArgumentParser : InternalCommandArgumentParserExtensions<Long>
/**
* 使用 [String.toShort] 解析
*/
public object ShortArgumentParser : InternalCommandArgumentParserExtensions<Short> {
public object ShortValueArgumentParser : InternalCommandValueArgumentParserExtensions<Short> {
public override fun parse(raw: String, sender: CommandSender): Short =
raw.toShortOrNull() ?: illegalArgument("无法解析 $raw 为短整数")
}
@ -49,7 +49,7 @@ public object ShortArgumentParser : InternalCommandArgumentParserExtensions<Shor
/**
* 使用 [String.toByte] 解析
*/
public object ByteArgumentParser : InternalCommandArgumentParserExtensions<Byte> {
public object ByteValueArgumentParser : InternalCommandValueArgumentParserExtensions<Byte> {
public override fun parse(raw: String, sender: CommandSender): Byte =
raw.toByteOrNull() ?: illegalArgument("无法解析 $raw 为字节")
}
@ -57,7 +57,7 @@ public object ByteArgumentParser : InternalCommandArgumentParserExtensions<Byte>
/**
* 使用 [String.toDouble] 解析
*/
public object DoubleArgumentParser : InternalCommandArgumentParserExtensions<Double> {
public object DoubleValueArgumentParser : InternalCommandValueArgumentParserExtensions<Double> {
public override fun parse(raw: String, sender: CommandSender): Double =
raw.toDoubleOrNull() ?: illegalArgument("无法解析 $raw 为小数")
}
@ -65,7 +65,7 @@ public object DoubleArgumentParser : InternalCommandArgumentParserExtensions<Dou
/**
* 使用 [String.toFloat] 解析
*/
public object FloatArgumentParser : InternalCommandArgumentParserExtensions<Float> {
public object FloatValueArgumentParser : InternalCommandValueArgumentParserExtensions<Float> {
public override fun parse(raw: String, sender: CommandSender): Float =
raw.toFloatOrNull() ?: illegalArgument("无法解析 $raw 为小数")
}
@ -73,14 +73,14 @@ public object FloatArgumentParser : InternalCommandArgumentParserExtensions<Floa
/**
* 直接返回 [String], 或取用 [SingleMessage.contentToString]
*/
public object StringArgumentParser : InternalCommandArgumentParserExtensions<String> {
public object StringValueArgumentParser : InternalCommandValueArgumentParserExtensions<String> {
public override fun parse(raw: String, sender: CommandSender): String = raw
}
/**
* 解析 [String] 通过 [Image].
*/
public object ImageArgumentParser : InternalCommandArgumentParserExtensions<Image> {
public object ImageValueArgumentParser : InternalCommandValueArgumentParserExtensions<Image> {
public override fun parse(raw: String, sender: CommandSender): Image {
return kotlin.runCatching {
Image(raw)
@ -95,7 +95,7 @@ public object ImageArgumentParser : InternalCommandArgumentParserExtensions<Imag
}
}
public object PlainTextArgumentParser : InternalCommandArgumentParserExtensions<PlainText> {
public object PlainTextValueArgumentParser : InternalCommandValueArgumentParserExtensions<PlainText> {
public override fun parse(raw: String, sender: CommandSender): PlainText {
return PlainText(raw)
}
@ -109,7 +109,7 @@ public object PlainTextArgumentParser : InternalCommandArgumentParserExtensions<
/**
* 当字符串内容为(不区分大小写) "true", "yes", "enabled"
*/
public object BooleanArgumentParser : InternalCommandArgumentParserExtensions<Boolean> {
public object BooleanValueArgumentParser : InternalCommandValueArgumentParserExtensions<Boolean> {
public override fun parse(raw: String, sender: CommandSender): Boolean = raw.trim().let { str ->
str.equals("true", ignoreCase = true)
|| str.equals("yes", ignoreCase = true)
@ -121,7 +121,7 @@ public object BooleanArgumentParser : InternalCommandArgumentParserExtensions<Bo
/**
* 根据 [Bot.id] 解析一个登录后的 [Bot]
*/
public object ExistingBotArgumentParser : InternalCommandArgumentParserExtensions<Bot> {
public object ExistingBotValueArgumentParser : InternalCommandValueArgumentParserExtensions<Bot> {
public override fun parse(raw: String, sender: CommandSender): Bot =
if (raw == "~") sender.inferBotOrFail()
else raw.findBotOrFail()
@ -136,7 +136,7 @@ public object ExistingBotArgumentParser : InternalCommandArgumentParserExtension
/**
* 解析任意一个存在的好友.
*/
public object ExistingFriendArgumentParser : InternalCommandArgumentParserExtensions<Friend> {
public object ExistingFriendValueArgumentParser : InternalCommandValueArgumentParserExtensions<Friend> {
private val syntax = """
- `botId.friendId`
- `botId.friendNick` (模糊搜索, 寻找最优匹配)
@ -175,7 +175,7 @@ public object ExistingFriendArgumentParser : InternalCommandArgumentParserExtens
/**
* 解析任意一个存在的群.
*/
public object ExistingGroupArgumentParser : InternalCommandArgumentParserExtensions<Group> {
public object ExistingGroupValueArgumentParser : InternalCommandValueArgumentParserExtensions<Group> {
private val syntax = """
- `botId.groupId`
- `~` (指代指令调用人自己所在群. 仅群聊天环境下)
@ -202,7 +202,7 @@ public object ExistingGroupArgumentParser : InternalCommandArgumentParserExtensi
}
}
public object ExistingUserArgumentParser : InternalCommandArgumentParserExtensions<User> {
public object ExistingUserValueArgumentParser : InternalCommandValueArgumentParserExtensions<User> {
private val syntax: String = """
- `botId.groupId.memberId`
- `botId.groupId.memberCard` (模糊搜索, 寻找最优匹配)
@ -215,11 +215,11 @@ public object ExistingUserArgumentParser : InternalCommandArgumentParserExtensio
""".trimIndent()
override fun parse(raw: String, sender: CommandSender): User {
return parseImpl(sender, raw, ExistingMemberArgumentParser::parse, ExistingFriendArgumentParser::parse)
return parseImpl(sender, raw, ExistingMemberValueArgumentParser::parse, ExistingFriendValueArgumentParser::parse)
}
override fun parse(raw: MessageContent, sender: CommandSender): User {
return parseImpl(sender, raw, ExistingMemberArgumentParser::parse, ExistingFriendArgumentParser::parse)
return parseImpl(sender, raw, ExistingMemberValueArgumentParser::parse, ExistingFriendValueArgumentParser::parse)
}
private fun <T> parseImpl(
@ -246,7 +246,7 @@ public object ExistingUserArgumentParser : InternalCommandArgumentParserExtensio
}
public object ExistingContactArgumentParser : InternalCommandArgumentParserExtensions<Contact> {
public object ExistingContactValueArgumentParser : InternalCommandValueArgumentParserExtensions<Contact> {
private val syntax: String = """
- `botId.groupId.memberId`
- `botId.groupId.memberCard` (模糊搜索, 寻找最优匹配)
@ -259,11 +259,11 @@ public object ExistingContactArgumentParser : InternalCommandArgumentParserExten
""".trimIndent()
override fun parse(raw: String, sender: CommandSender): Contact {
return parseImpl(sender, raw, ExistingUserArgumentParser::parse, ExistingGroupArgumentParser::parse)
return parseImpl(sender, raw, ExistingUserValueArgumentParser::parse, ExistingGroupValueArgumentParser::parse)
}
override fun parse(raw: MessageContent, sender: CommandSender): Contact {
return parseImpl(sender, raw, ExistingUserArgumentParser::parse, ExistingGroupArgumentParser::parse)
return parseImpl(sender, raw, ExistingUserValueArgumentParser::parse, ExistingGroupValueArgumentParser::parse)
}
private fun <T> parseImpl(
@ -286,7 +286,7 @@ public object ExistingContactArgumentParser : InternalCommandArgumentParserExten
/**
* 解析任意一个群成员.
*/
public object ExistingMemberArgumentParser : InternalCommandArgumentParserExtensions<Member> {
public object ExistingMemberValueArgumentParser : InternalCommandValueArgumentParserExtensions<Member> {
private val syntax: String = """
- `botId.groupId.memberId`
- `botId.groupId.memberCard` (模糊搜索, 寻找最优匹配)
@ -333,7 +333,7 @@ public object ExistingMemberArgumentParser : InternalCommandArgumentParserExtens
}
}
public object PermissionIdArgumentParser : CommandArgumentParser<PermissionId> {
public object PermissionIdValueArgumentParser : CommandValueArgumentParser<PermissionId> {
override fun parse(raw: String, sender: CommandSender): PermissionId {
return kotlin.runCatching { PermissionId.parseFromString(raw) }.getOrElse {
illegalArgument("无法解析 $raw 为 PermissionId")
@ -341,7 +341,7 @@ public object PermissionIdArgumentParser : CommandArgumentParser<PermissionId> {
}
}
public object PermitteeIdArgumentParser : CommandArgumentParser<PermitteeId> {
public object PermitteeIdValueArgumentParser : CommandValueArgumentParser<PermitteeId> {
override fun parse(raw: String, sender: CommandSender): PermitteeId {
return if (raw == "~") sender.permitteeId
else kotlin.runCatching { AbstractPermitteeId.parseFromString(raw) }.getOrElse {
@ -351,19 +351,19 @@ public object PermitteeIdArgumentParser : CommandArgumentParser<PermitteeId> {
override fun parse(raw: MessageContent, sender: CommandSender): PermitteeId {
if (raw is At) {
return ExistingUserArgumentParser.parse(raw, sender).asCommandSender(false).permitteeId
return ExistingUserValueArgumentParser.parse(raw, sender).asCommandSender(false).permitteeId
}
return super.parse(raw, sender)
}
}
/** 直接返回原始参数 [MessageContent] */
public object RawContentArgumentParser : CommandArgumentParser<MessageContent> {
public object RawContentValueArgumentParser : CommandValueArgumentParser<MessageContent> {
override fun parse(raw: String, sender: CommandSender): MessageContent = PlainText(raw)
override fun parse(raw: MessageContent, sender: CommandSender): MessageContent = raw
}
internal interface InternalCommandArgumentParserExtensions<T : Any> : CommandArgumentParser<T> {
internal interface InternalCommandValueArgumentParserExtensions<T : Any> : CommandValueArgumentParser<T> {
fun String.parseToLongOrFail(): Long = toLongOrNull() ?: illegalArgument("无法解析 $this 为整数")
fun Long.findBotOrFail(): Bot = Bot.getInstanceOrNull(this) ?: illegalArgument("无法找到 Bot: $this")

View File

@ -16,8 +16,8 @@ package net.mamoe.mirai.console.command.descriptor
*
* [message] 将会发送给指令调用方.
*
* @see CommandArgumentParser
* @see CommandArgumentParser.illegalArgument
* @see CommandValueArgumentParser
* @see CommandValueArgumentParser.illegalArgument
*/
public class CommandArgumentParserException : RuntimeException {
public constructor() : super()

View File

@ -65,7 +65,7 @@ public sealed class CommandValueParameter<T> : ICommandParameter<T> {
}
/**
* Extended by [CommandArgumentParser]
* Extended by [CommandValueArgumentParser]
*/
public abstract class Extended<T> : CommandValueParameter<T>()
}

View File

@ -32,27 +32,27 @@ import kotlin.contracts.contract
* ```
* suspend fun CommandSender.mute(target: Member, duration: Int)
* ```
* [CommandManager] 总是从 [SimpleCommand.context] 搜索一个 [T] [Member] [CommandArgumentParser], 并调用其 [CommandArgumentParser.parse]
* [CommandManager] 总是从 [SimpleCommand.context] 搜索一个 [T] [Member] [CommandValueArgumentParser], 并调用其 [CommandValueArgumentParser.parse]
*
* ### 内建指令解析器
* - 基础类型: [ByteArgumentParser], [ShortArgumentParser], [IntArgumentParser], [LongArgumentParser]
* [FloatArgumentParser], [DoubleArgumentParser],
* [BooleanArgumentParser], [StringArgumentParser]
* - 基础类型: [ByteValueArgumentParser], [ShortValueArgumentParser], [IntValueArgumentParser], [LongValueArgumentParser]
* [FloatValueArgumentParser], [DoubleValueArgumentParser],
* [BooleanValueArgumentParser], [StringValueArgumentParser]
*
* - [Bot]: [ExistingBotArgumentParser]
* - [Friend]: [ExistingFriendArgumentParser]
* - [Group]: [ExistingGroupArgumentParser]
* - [Member]: [ExistingMemberArgumentParser]
* - [User]: [ExistingUserArgumentParser]
* - [Contact]: [ExistingContactArgumentParser]
* - [Bot]: [ExistingBotValueArgumentParser]
* - [Friend]: [ExistingFriendValueArgumentParser]
* - [Group]: [ExistingGroupValueArgumentParser]
* - [Member]: [ExistingMemberValueArgumentParser]
* - [User]: [ExistingUserValueArgumentParser]
* - [Contact]: [ExistingContactValueArgumentParser]
*
*
* @see SimpleCommand 简单指令
* @see CompositeCommand 复合指令
*
* @see buildCommandArgumentContext 指令参数环境, [CommandArgumentParser] 的集合
* @see buildCommandArgumentContext 指令参数环境, [CommandValueArgumentParser] 的集合
*/
public interface CommandArgumentParser<out T : Any> {
public interface CommandValueArgumentParser<out T : Any> {
/**
* 解析一个字符串为 [T] 类型参数
*
@ -84,14 +84,14 @@ public interface CommandArgumentParser<out T : Any> {
/**
* 使用原 [this] 解析, 成功后使用 [mapper] 映射为另一个类型.
*/
public fun <T : Any, R : Any> CommandArgumentParser<T>.map(
mapper: CommandArgumentParser<R>.(T) -> R
): CommandArgumentParser<R> = MappingCommandArgumentParser(this, mapper)
public fun <T : Any, R : Any> CommandValueArgumentParser<T>.map(
mapper: CommandValueArgumentParser<R>.(T) -> R,
): CommandValueArgumentParser<R> = MappingCommandValueArgumentParser(this, mapper)
private class MappingCommandArgumentParser<T : Any, R : Any>(
private val original: CommandArgumentParser<T>,
private val mapper: CommandArgumentParser<R>.(T) -> R
) : CommandArgumentParser<R> {
private class MappingCommandValueArgumentParser<T : Any, R : Any>(
private val original: CommandValueArgumentParser<T>,
private val mapper: CommandValueArgumentParser<R>.(T) -> R,
) : CommandValueArgumentParser<R> {
override fun parse(raw: String, sender: CommandSender): R = mapper(original.parse(raw, sender))
override fun parse(raw: MessageContent, sender: CommandSender): R = mapper(original.parse(raw, sender))
}
@ -103,7 +103,7 @@ private class MappingCommandArgumentParser<T : Any, R : Any>(
*/
@JvmSynthetic
@Throws(IllegalArgumentException::class)
public fun <T : Any> CommandArgumentParser<T>.parse(raw: Any, sender: CommandSender): T {
public fun <T : Any> CommandValueArgumentParser<T>.parse(raw: Any, sender: CommandSender): T {
contract {
returns() implies (raw is String || raw is SingleMessage)
}
@ -123,7 +123,7 @@ public fun <T : Any> CommandArgumentParser<T>.parse(raw: Any, sender: CommandSen
@Suppress("unused")
@JvmSynthetic
@Throws(CommandArgumentParserException::class)
public inline fun CommandArgumentParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing {
public inline fun CommandValueArgumentParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing {
throw CommandArgumentParserException(message, cause)
}
@ -134,9 +134,9 @@ public inline fun CommandArgumentParser<*>.illegalArgument(message: String, caus
*/
@Throws(CommandArgumentParserException::class)
@JvmSynthetic
public inline fun CommandArgumentParser<*>.checkArgument(
public inline fun CommandValueArgumentParser<*>.checkArgument(
condition: Boolean,
crossinline message: () -> String = { "Check failed." }
crossinline message: () -> String = { "Check failed." },
) {
contract {
returns() implies condition

View File

@ -16,6 +16,9 @@ import kotlin.reflect.typeOf
@ExperimentalCommandDescriptors
public interface TypeVariant<out OutType> {
/**
* The reified type of [OutType]
*/
public val outType: KType
public fun mapValue(valueParameter: MessageContent): OutType
@ -33,8 +36,8 @@ public interface TypeVariant<out OutType> {
}
@ExperimentalCommandDescriptors
public object StringTypeVariant : TypeVariant<RawCommandArgument> {
public object MessageContentTypeVariant : TypeVariant<MessageContent> {
@OptIn(ExperimentalStdlibApi::class)
override val outType: KType = typeOf<String>()
override fun mapValue(valueParameter: RawCommandArgument): RawCommandArgument = valueParameter
override fun mapValue(valueParameter: MessageContent): MessageContent = valueParameter
}

View File

@ -10,8 +10,8 @@
package net.mamoe.mirai.console.command.parse
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
import net.mamoe.mirai.console.command.descriptor.MessageContentTypeVariant
import net.mamoe.mirai.console.command.descriptor.NoValueArgumentMappingException
import net.mamoe.mirai.console.command.descriptor.StringTypeVariant
import net.mamoe.mirai.console.command.descriptor.TypeVariant
import net.mamoe.mirai.message.data.MessageContent
import kotlin.reflect.full.isSubtypeOf
@ -23,20 +23,29 @@ import kotlin.reflect.typeOf
*/
public typealias RawCommandArgument = MessageContent
/**
* @see CommandValueArgument
*/
@ExperimentalCommandDescriptors
public interface CommandArgument
/**
* @see InvariantCommandValueArgument
*/
@ExperimentalCommandDescriptors
public interface CommandValueArgument : CommandArgument {
public val value: RawCommandArgument
public val typeVariants: List<TypeVariant<*>>
}
/**
* The [CommandValueArgument] that doesn't vary in type (remaining [MessageContent]).
*/
@ExperimentalCommandDescriptors
public data class InvariantCommandValueArgument(
public override val value: RawCommandArgument,
) : CommandValueArgument {
override val typeVariants: List<TypeVariant<*>> = listOf(StringTypeVariant)
override val typeVariants: List<TypeVariant<*>> = listOf(MessageContentTypeVariant)
}
@ExperimentalCommandDescriptors

View File

@ -12,7 +12,7 @@
package net.mamoe.mirai.console.internal.command
import net.mamoe.mirai.console.command.CompositeCommand
import net.mamoe.mirai.console.command.descriptor.CommandArgumentParser
import net.mamoe.mirai.console.command.descriptor.CommandValueArgumentParser
import kotlin.reflect.KClass
import kotlin.reflect.KParameter
@ -37,12 +37,12 @@ internal data class CommandParameter<T : Any>(
*/
val name: String,
/**
* 参数类型. 将从 [CompositeCommand.context] 中寻找 [CommandArgumentParser] 解析.
* 参数类型. 将从 [CompositeCommand.context] 中寻找 [CommandValueArgumentParser] 解析.
*/
val type: KClass<T>, // exact type
val parameter: KParameter, // source parameter
) {
constructor(name: String, type: KClass<T>, parameter: KParameter, parser: CommandArgumentParser<T>) : this(
constructor(name: String, type: KClass<T>, parameter: KParameter, parser: CommandValueArgumentParser<T>) : this(
name, type, parameter
) {
this._overrideParser = parser
@ -50,14 +50,14 @@ internal data class CommandParameter<T : Any>(
@Suppress("PropertyName")
@JvmField
internal var _overrideParser: CommandArgumentParser<T>? = null
internal var _overrideParser: CommandValueArgumentParser<T>? = null
/**
* 覆盖的 [CommandArgumentParser].
* 覆盖的 [CommandValueArgumentParser].
*
* 如果非 `null`, 将不会从 [CommandArgumentContext] 寻找 [CommandArgumentParser]
* 如果非 `null`, 将不会从 [CommandArgumentContext] 寻找 [CommandValueArgumentParser]
*/
val overrideParser: CommandArgumentParser<T>? get() = _overrideParser
val overrideParser: CommandValueArgumentParser<T>? get() = _overrideParser
}

View File

@ -22,7 +22,7 @@ import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.registeredCommands
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregister
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregisterAllCommands
import net.mamoe.mirai.console.command.descriptor.CommandArgumentParser
import net.mamoe.mirai.console.command.descriptor.CommandValueArgumentParser
import net.mamoe.mirai.console.command.descriptor.buildCommandArgumentContext
import net.mamoe.mirai.console.initTestEnvironment
import net.mamoe.mirai.console.internal.command.CommandManagerImpl
@ -191,7 +191,7 @@ internal class TestCommand {
ConsoleCommandOwner,
"test22",
overrideContext = buildCommandArgumentContext {
add(object : CommandArgumentParser<MyClass> {
add(object : CommandValueArgumentParser<MyClass> {
override fun parse(raw: String, sender: CommandSender): MyClass {
return MyClass(raw.toInt())
}