mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-10 18:40:15 +08:00
Review CommandArgumentContext and command
This commit is contained in:
parent
5c16e685b3
commit
d1ebe44f3e
@ -15,7 +15,11 @@ import kotlinx.coroutines.sync.withLock
|
||||
import net.mamoe.mirai.alsoLogin
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
|
||||
import net.mamoe.mirai.console.command.descriptor.*
|
||||
import net.mamoe.mirai.console.command.descriptor.CommandArgumentParserException
|
||||
import net.mamoe.mirai.console.command.descriptor.CommandValueArgumentParser.Companion.map
|
||||
import net.mamoe.mirai.console.command.descriptor.PermissionIdValueArgumentParser
|
||||
import net.mamoe.mirai.console.command.descriptor.PermitteeIdValueArgumentParser
|
||||
import net.mamoe.mirai.console.command.descriptor.buildCommandArgumentContext
|
||||
import net.mamoe.mirai.console.internal.command.CommandManagerImpl
|
||||
import net.mamoe.mirai.console.internal.command.CommandManagerImpl.allRegisteredCommands
|
||||
import net.mamoe.mirai.console.internal.util.runIgnoreException
|
||||
@ -154,7 +158,7 @@ public object BuiltInCommands {
|
||||
Permission::class with PermissionIdValueArgumentParser.map { id ->
|
||||
kotlin.runCatching {
|
||||
id.findCorrespondingPermissionOrFail()
|
||||
}.getOrElse { illegalArgument("指令不存在: $id", it) }
|
||||
}.getOrElse { throw CommandArgumentParserException("指令不存在: $id", it) }
|
||||
}
|
||||
},
|
||||
), BuiltInCommandInternal {
|
||||
|
@ -14,7 +14,6 @@ package net.mamoe.mirai.console.command
|
||||
import net.mamoe.mirai.console.command.descriptor.CommandArgumentContextAware
|
||||
import net.mamoe.mirai.console.command.descriptor.CommandSignatureVariant
|
||||
import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
||||
import net.mamoe.mirai.console.command.java.JCommand
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.COMMAND_NAME
|
||||
import net.mamoe.mirai.console.permission.Permission
|
||||
@ -31,8 +30,6 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
* @see SimpleCommand 简单的, 支持参数自动解析的指令
|
||||
*
|
||||
* @see CommandArgumentContextAware
|
||||
*
|
||||
* @see JCommand 为 Java 用户添加协程帮助的 [Command]
|
||||
*/
|
||||
public interface Command {
|
||||
/**
|
||||
|
@ -23,6 +23,8 @@ import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.message.data.MessageContent
|
||||
import net.mamoe.mirai.message.data.PlainText
|
||||
import kotlin.contracts.InvocationKind.EXACTLY_ONCE
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.internal.LowPriorityInOverloadResolution
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
@ -49,9 +51,17 @@ public interface CommandArgumentContext {
|
||||
public data class ParserPair<T : Any>(
|
||||
val klass: KClass<T>,
|
||||
val parser: CommandValueArgumentParser<T>,
|
||||
)
|
||||
) {
|
||||
public companion object {
|
||||
@JvmStatic
|
||||
public fun <T : Any> ParserPair<T>.toPair(): Pair<KClass<T>, CommandValueArgumentParser<T>> = klass to parser
|
||||
}
|
||||
}
|
||||
|
||||
public operator fun <T : Any> get(klass: KClass<out T>): CommandValueArgumentParser<T>?
|
||||
/**
|
||||
* 获取一个 [kClass] 类型的解析器.
|
||||
*/
|
||||
public operator fun <T : Any> get(kClass: KClass<T>): CommandValueArgumentParser<T>?
|
||||
|
||||
public fun toList(): List<ParserPair<*>>
|
||||
|
||||
@ -59,7 +69,7 @@ public interface CommandArgumentContext {
|
||||
/**
|
||||
* For Java callers.
|
||||
*
|
||||
* @see [EmptyCommandArgumentContext]
|
||||
* @see EmptyCommandArgumentContext
|
||||
*/
|
||||
@JvmStatic
|
||||
public val EMPTY: CommandArgumentContext = EmptyCommandArgumentContext
|
||||
@ -108,6 +118,9 @@ public interface CommandArgumentContextAware {
|
||||
public val context: CommandArgumentContext
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CommandArgumentContext.EMPTY
|
||||
*/
|
||||
public object EmptyCommandArgumentContext : CommandArgumentContext by SimpleCommandArgumentContext(listOf())
|
||||
|
||||
/**
|
||||
@ -117,8 +130,8 @@ 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>): CommandValueArgumentParser<T>? =
|
||||
replacer[klass] ?: this@plus[klass]
|
||||
override fun <T : Any> get(kClass: KClass<T>): CommandValueArgumentParser<T>? =
|
||||
replacer[kClass] ?: this@plus[kClass]
|
||||
|
||||
override fun toList(): List<ParserPair<*>> = replacer.toList() + this@plus.toList()
|
||||
}
|
||||
@ -132,9 +145,9 @@ 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>): CommandValueArgumentParser<T>? =
|
||||
replacer.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandValueArgumentParser<T>?
|
||||
?: this@plus[klass]
|
||||
override fun <T : Any> get(kClass: KClass<T>): CommandValueArgumentParser<T>? =
|
||||
replacer.firstOrNull { kClass.isSubclassOf(it.klass) }?.parser as CommandValueArgumentParser<T>?
|
||||
?: this@plus[kClass]
|
||||
|
||||
override fun toList(): List<ParserPair<*>> = replacer.toList() + this@plus.toList()
|
||||
}
|
||||
@ -149,9 +162,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>): CommandValueArgumentParser<T>? =
|
||||
(this.list.firstOrNull { klass == it.klass }?.parser
|
||||
?: this.list.firstOrNull { klass.isSubclassOf(it.klass) }?.parser) as CommandValueArgumentParser<T>?
|
||||
override fun <T : Any> get(kClass: KClass<T>): CommandValueArgumentParser<T>? =
|
||||
(this.list.firstOrNull { kClass == it.klass }?.parser
|
||||
?: this.list.firstOrNull { kClass.isSubclassOf(it.klass) }?.parser) as CommandValueArgumentParser<T>?
|
||||
|
||||
override fun toList(): List<ParserPair<*>> = list
|
||||
}
|
||||
@ -192,6 +205,9 @@ public class SimpleCommandArgumentContext(
|
||||
*/
|
||||
@JvmSynthetic
|
||||
public fun buildCommandArgumentContext(block: CommandArgumentContextBuilder.() -> Unit): CommandArgumentContext {
|
||||
contract {
|
||||
callsInPlace(block, EXACTLY_ONCE)
|
||||
}
|
||||
return CommandArgumentContextBuilder().apply(block).build()
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("EXPOSED_SUPER_CLASS")
|
||||
|
||||
package net.mamoe.mirai.console.command.descriptor
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
@ -25,7 +27,7 @@ import net.mamoe.mirai.message.data.*
|
||||
/**
|
||||
* 使用 [String.toInt] 解析
|
||||
*/
|
||||
public object IntValueArgumentParser : InternalCommandValueArgumentParserExtensions<Int> {
|
||||
public object IntValueArgumentParser : InternalCommandValueArgumentParserExtensions<Int>() {
|
||||
public override fun parse(raw: String, sender: CommandSender): Int =
|
||||
raw.toIntOrNull() ?: illegalArgument("无法解析 $raw 为整数")
|
||||
}
|
||||
@ -33,7 +35,7 @@ public object IntValueArgumentParser : InternalCommandValueArgumentParserExtensi
|
||||
/**
|
||||
* 使用 [String.toLong] 解析
|
||||
*/
|
||||
public object LongValueArgumentParser : InternalCommandValueArgumentParserExtensions<Long> {
|
||||
public object LongValueArgumentParser : InternalCommandValueArgumentParserExtensions<Long>() {
|
||||
public override fun parse(raw: String, sender: CommandSender): Long =
|
||||
raw.toLongOrNull() ?: illegalArgument("无法解析 $raw 为长整数")
|
||||
}
|
||||
@ -41,7 +43,7 @@ public object LongValueArgumentParser : InternalCommandValueArgumentParserExtens
|
||||
/**
|
||||
* 使用 [String.toShort] 解析
|
||||
*/
|
||||
public object ShortValueArgumentParser : InternalCommandValueArgumentParserExtensions<Short> {
|
||||
public object ShortValueArgumentParser : InternalCommandValueArgumentParserExtensions<Short>() {
|
||||
public override fun parse(raw: String, sender: CommandSender): Short =
|
||||
raw.toShortOrNull() ?: illegalArgument("无法解析 $raw 为短整数")
|
||||
}
|
||||
@ -49,7 +51,7 @@ public object ShortValueArgumentParser : InternalCommandValueArgumentParserExten
|
||||
/**
|
||||
* 使用 [String.toByte] 解析
|
||||
*/
|
||||
public object ByteValueArgumentParser : InternalCommandValueArgumentParserExtensions<Byte> {
|
||||
public object ByteValueArgumentParser : InternalCommandValueArgumentParserExtensions<Byte>() {
|
||||
public override fun parse(raw: String, sender: CommandSender): Byte =
|
||||
raw.toByteOrNull() ?: illegalArgument("无法解析 $raw 为字节")
|
||||
}
|
||||
@ -57,7 +59,7 @@ public object ByteValueArgumentParser : InternalCommandValueArgumentParserExtens
|
||||
/**
|
||||
* 使用 [String.toDouble] 解析
|
||||
*/
|
||||
public object DoubleValueArgumentParser : InternalCommandValueArgumentParserExtensions<Double> {
|
||||
public object DoubleValueArgumentParser : InternalCommandValueArgumentParserExtensions<Double>() {
|
||||
public override fun parse(raw: String, sender: CommandSender): Double =
|
||||
raw.toDoubleOrNull() ?: illegalArgument("无法解析 $raw 为小数")
|
||||
}
|
||||
@ -65,7 +67,7 @@ public object DoubleValueArgumentParser : InternalCommandValueArgumentParserExte
|
||||
/**
|
||||
* 使用 [String.toFloat] 解析
|
||||
*/
|
||||
public object FloatValueArgumentParser : InternalCommandValueArgumentParserExtensions<Float> {
|
||||
public object FloatValueArgumentParser : InternalCommandValueArgumentParserExtensions<Float>() {
|
||||
public override fun parse(raw: String, sender: CommandSender): Float =
|
||||
raw.toFloatOrNull() ?: illegalArgument("无法解析 $raw 为小数")
|
||||
}
|
||||
@ -73,14 +75,14 @@ public object FloatValueArgumentParser : InternalCommandValueArgumentParserExten
|
||||
/**
|
||||
* 直接返回 [String], 或取用 [SingleMessage.contentToString]
|
||||
*/
|
||||
public object StringValueArgumentParser : InternalCommandValueArgumentParserExtensions<String> {
|
||||
public object StringValueArgumentParser : InternalCommandValueArgumentParserExtensions<String>() {
|
||||
public override fun parse(raw: String, sender: CommandSender): String = raw
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 [String] 通过 [Image].
|
||||
*/
|
||||
public object ImageValueArgumentParser : InternalCommandValueArgumentParserExtensions<Image> {
|
||||
public object ImageValueArgumentParser : InternalCommandValueArgumentParserExtensions<Image>() {
|
||||
public override fun parse(raw: String, sender: CommandSender): Image {
|
||||
return kotlin.runCatching {
|
||||
Image(raw)
|
||||
@ -95,7 +97,7 @@ public object ImageValueArgumentParser : InternalCommandValueArgumentParserExten
|
||||
}
|
||||
}
|
||||
|
||||
public object PlainTextValueArgumentParser : InternalCommandValueArgumentParserExtensions<PlainText> {
|
||||
public object PlainTextValueArgumentParser : InternalCommandValueArgumentParserExtensions<PlainText>() {
|
||||
public override fun parse(raw: String, sender: CommandSender): PlainText {
|
||||
return PlainText(raw)
|
||||
}
|
||||
@ -109,7 +111,7 @@ public object PlainTextValueArgumentParser : InternalCommandValueArgumentParserE
|
||||
/**
|
||||
* 当字符串内容为(不区分大小写) "true", "yes", "enabled"
|
||||
*/
|
||||
public object BooleanValueArgumentParser : InternalCommandValueArgumentParserExtensions<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 +123,7 @@ public object BooleanValueArgumentParser : InternalCommandValueArgumentParserExt
|
||||
/**
|
||||
* 根据 [Bot.id] 解析一个登录后的 [Bot]
|
||||
*/
|
||||
public object ExistingBotValueArgumentParser : InternalCommandValueArgumentParserExtensions<Bot> {
|
||||
public object ExistingBotValueArgumentParser : InternalCommandValueArgumentParserExtensions<Bot>() {
|
||||
public override fun parse(raw: String, sender: CommandSender): Bot =
|
||||
if (raw == "~") sender.inferBotOrFail()
|
||||
else raw.findBotOrFail()
|
||||
@ -136,7 +138,7 @@ public object ExistingBotValueArgumentParser : InternalCommandValueArgumentParse
|
||||
/**
|
||||
* 解析任意一个存在的好友.
|
||||
*/
|
||||
public object ExistingFriendValueArgumentParser : InternalCommandValueArgumentParserExtensions<Friend> {
|
||||
public object ExistingFriendValueArgumentParser : InternalCommandValueArgumentParserExtensions<Friend>() {
|
||||
private val syntax = """
|
||||
- `botId.friendId`
|
||||
- `botId.friendNick` (模糊搜索, 寻找最优匹配)
|
||||
@ -175,7 +177,7 @@ public object ExistingFriendValueArgumentParser : InternalCommandValueArgumentPa
|
||||
/**
|
||||
* 解析任意一个存在的群.
|
||||
*/
|
||||
public object ExistingGroupValueArgumentParser : InternalCommandValueArgumentParserExtensions<Group> {
|
||||
public object ExistingGroupValueArgumentParser : InternalCommandValueArgumentParserExtensions<Group>() {
|
||||
private val syntax = """
|
||||
- `botId.groupId`
|
||||
- `~` (指代指令调用人自己所在群. 仅群聊天环境下)
|
||||
@ -202,7 +204,7 @@ public object ExistingGroupValueArgumentParser : InternalCommandValueArgumentPar
|
||||
}
|
||||
}
|
||||
|
||||
public object ExistingUserValueArgumentParser : InternalCommandValueArgumentParserExtensions<User> {
|
||||
public object ExistingUserValueArgumentParser : InternalCommandValueArgumentParserExtensions<User>() {
|
||||
private val syntax: String = """
|
||||
- `botId.groupId.memberId`
|
||||
- `botId.groupId.memberCard` (模糊搜索, 寻找最优匹配)
|
||||
@ -246,7 +248,7 @@ public object ExistingUserValueArgumentParser : InternalCommandValueArgumentPars
|
||||
}
|
||||
|
||||
|
||||
public object ExistingContactValueArgumentParser : InternalCommandValueArgumentParserExtensions<Contact> {
|
||||
public object ExistingContactValueArgumentParser : InternalCommandValueArgumentParserExtensions<Contact>() {
|
||||
private val syntax: String = """
|
||||
- `botId.groupId.memberId`
|
||||
- `botId.groupId.memberCard` (模糊搜索, 寻找最优匹配)
|
||||
@ -286,7 +288,7 @@ public object ExistingContactValueArgumentParser : InternalCommandValueArgumentP
|
||||
/**
|
||||
* 解析任意一个群成员.
|
||||
*/
|
||||
public object ExistingMemberValueArgumentParser : InternalCommandValueArgumentParserExtensions<Member> {
|
||||
public object ExistingMemberValueArgumentParser : InternalCommandValueArgumentParserExtensions<Member>() {
|
||||
private val syntax: String = """
|
||||
- `botId.groupId.memberId`
|
||||
- `botId.groupId.memberCard` (模糊搜索, 寻找最优匹配)
|
||||
@ -333,7 +335,7 @@ public object ExistingMemberValueArgumentParser : InternalCommandValueArgumentPa
|
||||
}
|
||||
}
|
||||
|
||||
public object PermissionIdValueArgumentParser : CommandValueArgumentParser<PermissionId> {
|
||||
public object PermissionIdValueArgumentParser : InternalCommandValueArgumentParserExtensions<PermissionId>() {
|
||||
override fun parse(raw: String, sender: CommandSender): PermissionId {
|
||||
return kotlin.runCatching { PermissionId.parseFromString(raw) }.getOrElse {
|
||||
illegalArgument("无法解析 $raw 为 PermissionId")
|
||||
@ -341,7 +343,7 @@ public object PermissionIdValueArgumentParser : CommandValueArgumentParser<Permi
|
||||
}
|
||||
}
|
||||
|
||||
public object PermitteeIdValueArgumentParser : CommandValueArgumentParser<PermitteeId> {
|
||||
public object PermitteeIdValueArgumentParser : InternalCommandValueArgumentParserExtensions<PermitteeId>() {
|
||||
override fun parse(raw: String, sender: CommandSender): PermitteeId {
|
||||
return if (raw == "~") sender.permitteeId
|
||||
else kotlin.runCatching { AbstractPermitteeId.parseFromString(raw) }.getOrElse {
|
||||
@ -363,26 +365,26 @@ public object RawContentValueArgumentParser : CommandValueArgumentParser<Message
|
||||
override fun parse(raw: MessageContent, sender: CommandSender): MessageContent = raw
|
||||
}
|
||||
|
||||
internal interface InternalCommandValueArgumentParserExtensions<T : Any> : CommandValueArgumentParser<T> {
|
||||
fun String.parseToLongOrFail(): Long = toLongOrNull() ?: illegalArgument("无法解析 $this 为整数")
|
||||
internal abstract class InternalCommandValueArgumentParserExtensions<T : Any> : AbstractCommandValueArgumentParser<T>() {
|
||||
private fun String.parseToLongOrFail(): Long = toLongOrNull() ?: illegalArgument("无法解析 $this 为整数")
|
||||
|
||||
fun Long.findBotOrFail(): Bot = Bot.getInstanceOrNull(this) ?: illegalArgument("无法找到 Bot: $this")
|
||||
protected fun Long.findBotOrFail(): Bot = Bot.getInstanceOrNull(this) ?: illegalArgument("无法找到 Bot: $this")
|
||||
|
||||
fun String.findBotOrFail(): Bot =
|
||||
protected fun String.findBotOrFail(): Bot =
|
||||
Bot.getInstanceOrNull(this.parseToLongOrFail()) ?: illegalArgument("无法找到 Bot: $this")
|
||||
|
||||
fun Bot.findGroupOrFail(id: Long): Group = getGroupOrNull(id) ?: illegalArgument("无法找到群: $this")
|
||||
protected fun Bot.findGroupOrFail(id: Long): Group = getGroupOrNull(id) ?: illegalArgument("无法找到群: $this")
|
||||
|
||||
fun Bot.findGroupOrFail(id: String): Group =
|
||||
protected fun Bot.findGroupOrFail(id: String): Group =
|
||||
getGroupOrNull(id.parseToLongOrFail()) ?: illegalArgument("无法找到群: $this")
|
||||
|
||||
fun Bot.findFriendOrFail(id: String): Friend =
|
||||
protected fun Bot.findFriendOrFail(id: String): Friend =
|
||||
getFriendOrNull(id.parseToLongOrFail()) ?: illegalArgument("无法找到好友: $this")
|
||||
|
||||
fun Bot.findMemberOrFail(id: String): Friend =
|
||||
protected fun Bot.findMemberOrFail(id: String): Friend =
|
||||
getFriendOrNull(id.parseToLongOrFail()) ?: illegalArgument("无法找到群员: $this")
|
||||
|
||||
fun Group.findMemberOrFail(idOrCard: String): Member {
|
||||
protected fun Group.findMemberOrFail(idOrCard: String): Member {
|
||||
if (idOrCard == "\$") return members.randomOrNull() ?: illegalArgument("当前语境下无法推断随机群员")
|
||||
idOrCard.toLongOrNull()?.let { getOrNull(it) }?.let { return it }
|
||||
this.members.singleOrNull { it.nameCardOrNick.contains(idOrCard) }?.let { return it }
|
||||
@ -405,23 +407,21 @@ internal interface InternalCommandValueArgumentParserExtensions<T : Any> : Comma
|
||||
}
|
||||
}
|
||||
|
||||
fun CommandSender.inferBotOrFail(): Bot =
|
||||
protected fun CommandSender.inferBotOrFail(): Bot =
|
||||
(this as? UserCommandSender)?.bot
|
||||
?: Bot.botInstancesSequence.singleOrNull()
|
||||
?: illegalArgument("当前语境下无法推断目标 Bot, 因为目前有多个 Bot 在线.")
|
||||
|
||||
fun CommandSender.inferGroupOrFail(): Group =
|
||||
protected fun CommandSender.inferGroupOrFail(): Group =
|
||||
inferGroup() ?: illegalArgument("当前语境下无法推断目标群")
|
||||
|
||||
fun CommandSender.inferGroup(): Group? = (this as? GroupAwareCommandSender)?.group
|
||||
protected fun CommandSender.inferGroup(): Group? = (this as? GroupAwareCommandSender)?.group
|
||||
|
||||
fun CommandSender.inferFriendOrFail(): Friend =
|
||||
protected fun CommandSender.inferFriendOrFail(): Friend =
|
||||
(this as? FriendCommandSender)?.user ?: illegalArgument("当前语境下无法推断目标好友")
|
||||
}
|
||||
|
||||
internal fun Double.toDecimalPlace(n: Int): String {
|
||||
return "%.${n}f".format(this)
|
||||
}
|
||||
internal fun Double.toDecimalPlace(n: Int): String = "%.${n}f".format(this)
|
||||
|
||||
internal fun String.truncate(lengthLimit: Int, replacement: String = "..."): String = buildString {
|
||||
var lengthSum = 0
|
||||
|
@ -12,6 +12,7 @@
|
||||
package net.mamoe.mirai.console.command.descriptor
|
||||
|
||||
import net.mamoe.mirai.console.command.IllegalCommandArgumentException
|
||||
import net.mamoe.mirai.console.command.descriptor.AbstractCommandValueArgumentParser.Companion.illegalArgument
|
||||
|
||||
/**
|
||||
* 在解析参数时遇到的 _正常_ 错误. 如参数不符合规范等.
|
||||
@ -20,7 +21,7 @@ import net.mamoe.mirai.console.command.IllegalCommandArgumentException
|
||||
*
|
||||
* @see IllegalCommandArgumentException
|
||||
* @see CommandValueArgumentParser
|
||||
* @see CommandValueArgumentParser.illegalArgument
|
||||
* @see AbstractCommandValueArgumentParser.illegalArgument
|
||||
*/
|
||||
public class CommandArgumentParserException : IllegalCommandArgumentException {
|
||||
public constructor() : super()
|
||||
|
@ -16,10 +16,9 @@ import net.mamoe.mirai.console.command.CommandManager
|
||||
import net.mamoe.mirai.console.command.CommandSender
|
||||
import net.mamoe.mirai.console.command.CompositeCommand
|
||||
import net.mamoe.mirai.console.command.SimpleCommand
|
||||
import net.mamoe.mirai.console.command.descriptor.CommandValueArgumentParser.Companion.parse
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.message.data.MessageContent
|
||||
import net.mamoe.mirai.message.data.SingleMessage
|
||||
import net.mamoe.mirai.message.data.content
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
||||
@ -78,68 +77,76 @@ public interface CommandValueArgumentParser<out T : Any> {
|
||||
*/
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
public fun parse(raw: MessageContent, sender: CommandSender): T = parse(raw.content, sender)
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用原 [this] 解析, 成功后使用 [mapper] 映射为另一个类型.
|
||||
*/
|
||||
public fun <T : Any, R : Any> CommandValueArgumentParser<T>.map(
|
||||
mapper: CommandValueArgumentParser<R>.(T) -> R,
|
||||
): CommandValueArgumentParser<R> = MappingCommandValueArgumentParser(this, mapper)
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
/**
|
||||
public companion object {
|
||||
/**
|
||||
* 解析一个字符串或 [SingleMessage] 为 [T] 类型参数
|
||||
*
|
||||
* @throws IllegalArgumentException 当 [raw] 既不是 [SingleMessage], 也不是 [String] 时抛出.
|
||||
*
|
||||
* @see CommandValueArgumentParser.parse
|
||||
*/
|
||||
@JvmSynthetic
|
||||
@Throws(IllegalArgumentException::class)
|
||||
public fun <T : Any> CommandValueArgumentParser<T>.parse(raw: Any, sender: CommandSender): T {
|
||||
contract {
|
||||
returns() implies (raw is String || raw is SingleMessage)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Throws(IllegalArgumentException::class)
|
||||
public fun <T : Any> CommandValueArgumentParser<T>.parse(raw: Message, sender: CommandSender): T {
|
||||
return when (raw) {
|
||||
is String -> parse(raw, sender)
|
||||
is PlainText -> parse(raw.content, sender)
|
||||
is MessageContent -> parse(raw, sender)
|
||||
else -> throw IllegalArgumentException("Illegal raw argument type: ${raw::class.qualifiedName}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用原 [this] 解析, 成功后使用 [mapper] 映射为另一个类型.
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun <Original : Any, Result : Any> CommandValueArgumentParser<Original>.map(
|
||||
mapper: MappingCommandValueArgumentParser<Original, Result>.(Original) -> Result,
|
||||
): CommandValueArgumentParser<Result> = MappingCommandValueArgumentParser(this, mapper)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CommandValueArgumentParser 的基础实现.
|
||||
*/
|
||||
public abstract class AbstractCommandValueArgumentParser<T : Any> : CommandValueArgumentParser<T> {
|
||||
public companion object {
|
||||
/**
|
||||
* 抛出一个 [CommandArgumentParserException] 的捷径
|
||||
*
|
||||
* @throws CommandArgumentParserException
|
||||
*/
|
||||
@Suppress("unused")
|
||||
@JvmSynthetic
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
public inline fun CommandValueArgumentParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing {
|
||||
@JvmStatic
|
||||
@JvmSynthetic
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
protected inline fun CommandValueArgumentParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing =
|
||||
throw CommandArgumentParserException(message, cause)
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* 检查参数 [condition]. 当它为 `false` 时调用 [message] 并以其返回值作为消息, 抛出异常 [CommandArgumentParserException]
|
||||
*
|
||||
* @throws CommandArgumentParserException
|
||||
*/
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
@JvmSynthetic
|
||||
public inline fun CommandValueArgumentParser<*>.checkArgument(
|
||||
@JvmStatic
|
||||
@Throws(CommandArgumentParserException::class)
|
||||
@JvmSynthetic
|
||||
protected inline fun CommandValueArgumentParser<*>.checkArgument(
|
||||
condition: Boolean,
|
||||
crossinline message: () -> String = { "Check failed." },
|
||||
) {
|
||||
) {
|
||||
contract {
|
||||
returns() implies condition
|
||||
callsInPlace(message, InvocationKind.AT_MOST_ONCE)
|
||||
}
|
||||
if (!condition) illegalArgument(message())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class MappingCommandValueArgumentParser<T : Any, R : Any>(
|
||||
private val original: CommandValueArgumentParser<T>,
|
||||
private val mapper: MappingCommandValueArgumentParser<T, R>.(T) -> R,
|
||||
) : AbstractCommandValueArgumentParser<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))
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.command.java
|
||||
|
||||
import net.mamoe.mirai.console.command.Command
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
|
||||
/**
|
||||
* 为 Java 用户添加协程帮助的 [Command].
|
||||
*
|
||||
* 注意, [JSimpleCommand], [JCompositeCommand], [JRawCommand] 都不实现这个接口. [JCommand] 只设计为 Java 使用者自己实现 [Command] 相关内容.
|
||||
*
|
||||
* @see Command
|
||||
*/
|
||||
@ConsoleExperimentalApi("Not yet supported")
|
||||
public interface JCommand : Command {
|
||||
// TODO: 2020/10/18 JCommand
|
||||
}
|
@ -18,7 +18,6 @@ import net.mamoe.mirai.console.command.descriptor.buildCommandArgumentContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.COMMAND_NAME
|
||||
import net.mamoe.mirai.console.permission.Permission
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
|
||||
/**
|
||||
* 复合指令. 指令注册时候会通过反射构造指令解析器.
|
||||
@ -70,7 +69,6 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
*
|
||||
* @see buildCommandArgumentContext
|
||||
*/
|
||||
@ConsoleExperimentalApi("Not yet supported")
|
||||
public abstract class JCompositeCommand
|
||||
@JvmOverloads constructor(
|
||||
owner: CommandOwner,
|
||||
|
@ -18,7 +18,6 @@ import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.COMMAND_NAME
|
||||
import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission
|
||||
import net.mamoe.mirai.console.permission.Permission
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
|
||||
/**
|
||||
* 供 Java 用户继承
|
||||
@ -46,7 +45,6 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
*
|
||||
* @see JRawCommand
|
||||
*/
|
||||
@ConsoleExperimentalApi("Not yet supported")
|
||||
public abstract class JRawCommand
|
||||
@JvmOverloads constructor(
|
||||
/**
|
||||
|
@ -17,7 +17,6 @@ import net.mamoe.mirai.console.command.descriptor.ExperimentalCommandDescriptors
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext
|
||||
import net.mamoe.mirai.console.compiler.common.ResolveContext.Kind.COMMAND_NAME
|
||||
import net.mamoe.mirai.console.permission.Permission
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
|
||||
/**
|
||||
* Java 实现:
|
||||
@ -43,7 +42,6 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
* @see SimpleCommand
|
||||
* @see [CommandManager.executeCommand]
|
||||
*/
|
||||
@ConsoleExperimentalApi("Not yet supported")
|
||||
public abstract class JSimpleCommand(
|
||||
owner: CommandOwner,
|
||||
@ResolveContext(COMMAND_NAME) primaryName: String,
|
||||
|
@ -77,7 +77,7 @@ public object BuiltInCommandCallResolver : CommandCallResolver {
|
||||
} else {
|
||||
if (valueArguments.size > valueParameters.size && zipped.last().first.isVararg) {
|
||||
// merge vararg arguments
|
||||
val (varargParameter, varargFirstArgument)
|
||||
val (varargParameter, _)
|
||||
= zipped.removeLast()
|
||||
|
||||
zipped.add(varargParameter to DefaultCommandValueArgument(valueArguments.drop(zipped.size).map { it.value }.asMessageChain()))
|
||||
|
@ -13,6 +13,7 @@ import net.mamoe.mirai.console.command.Command
|
||||
import net.mamoe.mirai.console.command.CommandSender
|
||||
import net.mamoe.mirai.console.command.CompositeCommand
|
||||
import net.mamoe.mirai.console.command.descriptor.*
|
||||
import net.mamoe.mirai.console.command.descriptor.CommandValueArgumentParser.Companion.parse
|
||||
import net.mamoe.mirai.console.command.parse.CommandCall
|
||||
import net.mamoe.mirai.console.command.parse.CommandValueArgument
|
||||
import net.mamoe.mirai.console.command.parse.mapToTypeOrNull
|
||||
|
Loading…
Reference in New Issue
Block a user