mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-27 00:30:17 +08:00
Fix CompositeCommand; Rename CommandParam to CommandParameter
This commit is contained in:
parent
2843f91d02
commit
d240ba7b83
@ -146,6 +146,7 @@ public interface CommandManager {
|
|||||||
override fun Command.findDuplicate(): Command? = CommandManagerImpl.run { findDuplicate() }
|
override fun Command.findDuplicate(): Command? = CommandManagerImpl.run { findDuplicate() }
|
||||||
override fun Command.unregister(): Boolean = CommandManagerImpl.run { unregister() }
|
override fun Command.unregister(): Boolean = CommandManagerImpl.run { unregister() }
|
||||||
override fun Command.isRegistered(): Boolean = CommandManagerImpl.run { isRegistered() }
|
override fun Command.isRegistered(): Boolean = CommandManagerImpl.run { isRegistered() }
|
||||||
|
override val commandPrefix: String get() = CommandManagerImpl.commandPrefix
|
||||||
override suspend fun CommandSender.executeCommand(vararg messages: Any): Command? =
|
override suspend fun CommandSender.executeCommand(vararg messages: Any): Command? =
|
||||||
CommandManagerImpl.run { executeCommand(*messages) }
|
CommandManagerImpl.run { executeCommand(*messages) }
|
||||||
|
|
||||||
@ -196,4 +197,4 @@ public abstract class PluginCommandOwner(
|
|||||||
/**
|
/**
|
||||||
* 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner].
|
* 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner].
|
||||||
*/
|
*/
|
||||||
public object ConsoleCommandOwner : CommandOwner()
|
internal object ConsoleCommandOwner : CommandOwner()
|
||||||
|
@ -15,9 +15,9 @@ import net.mamoe.mirai.console.command.CompositeCommand
|
|||||||
import java.lang.reflect.Parameter
|
import java.lang.reflect.Parameter
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
internal fun Parameter.toCommandParam(): CommandParam<*> {
|
internal fun Parameter.toCommandParam(): CommandParameter<*> {
|
||||||
val name = getAnnotation(CompositeCommand.Name::class.java)
|
val name = getAnnotation(CompositeCommand.Name::class.java)
|
||||||
return CommandParam(
|
return CommandParameter(
|
||||||
name?.value ?: this.name
|
name?.value ?: this.name
|
||||||
?: throw IllegalArgumentException("Cannot construct CommandParam from a unnamed param"),
|
?: throw IllegalArgumentException("Cannot construct CommandParam from a unnamed param"),
|
||||||
this.type.kotlin
|
this.type.kotlin
|
||||||
@ -28,7 +28,7 @@ internal fun Parameter.toCommandParam(): CommandParam<*> {
|
|||||||
* 指令形式参数.
|
* 指令形式参数.
|
||||||
* @see toCommandParam
|
* @see toCommandParam
|
||||||
*/
|
*/
|
||||||
internal data class CommandParam<T : Any>(
|
internal data class CommandParameter<T : Any>(
|
||||||
/**
|
/**
|
||||||
* 参数名. 不允许重复.
|
* 参数名. 不允许重复.
|
||||||
*/
|
*/
|
||||||
|
@ -12,10 +12,9 @@
|
|||||||
package net.mamoe.mirai.console.internal.command
|
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.Command.Companion.primaryName
|
|
||||||
import net.mamoe.mirai.console.command.description.CommandArgumentContext
|
import net.mamoe.mirai.console.command.description.CommandArgumentContext
|
||||||
import net.mamoe.mirai.console.command.description.CommandArgumentContextAware
|
import net.mamoe.mirai.console.command.description.CommandArgumentContextAware
|
||||||
import net.mamoe.mirai.console.command.description.CommandParam
|
import net.mamoe.mirai.console.command.description.CommandParameter
|
||||||
import net.mamoe.mirai.message.data.PlainText
|
import net.mamoe.mirai.message.data.PlainText
|
||||||
import net.mamoe.mirai.message.data.SingleMessage
|
import net.mamoe.mirai.message.data.SingleMessage
|
||||||
import kotlin.reflect.KAnnotatedElement
|
import kotlin.reflect.KAnnotatedElement
|
||||||
@ -90,7 +89,7 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
|
|||||||
}.map { function ->
|
}.map { function ->
|
||||||
createSubCommand(function, context)
|
createSubCommand(function, context)
|
||||||
}.toTypedArray().also {
|
}.toTypedArray().also {
|
||||||
_usage = it.firstOrNull()?.usage ?: description
|
_usage = it.createUsage(this)
|
||||||
}.also { checkSubCommand(it) }
|
}.also { checkSubCommand(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,16 +111,16 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
|
|||||||
val onCommand: suspend (sender: CommandSender, rawArgs: Array<out Any>) -> Unit
|
val onCommand: suspend (sender: CommandSender, rawArgs: Array<out Any>) -> Unit
|
||||||
)
|
)
|
||||||
|
|
||||||
internal class SubCommandDescriptor(
|
internal inner class SubCommandDescriptor(
|
||||||
val names: Array<out String>,
|
val names: Array<out String>,
|
||||||
val params: Array<CommandParam<*>>,
|
val params: Array<CommandParameter<*>>,
|
||||||
val description: String,
|
val description: String,
|
||||||
val permission: CommandPermission,
|
val permission: CommandPermission,
|
||||||
val onCommand: suspend (sender: CommandSender, parsedArgs: Array<out Any>) -> Boolean,
|
val onCommand: suspend (sender: CommandSender, parsedArgs: Array<out Any>) -> Boolean,
|
||||||
val context: CommandArgumentContext,
|
val context: CommandArgumentContext
|
||||||
val usage: String
|
|
||||||
) {
|
) {
|
||||||
internal suspend inline fun parseAndExecute(
|
val usage: String = createUsage(this@AbstractReflectionCommand)
|
||||||
|
internal suspend fun parseAndExecute(
|
||||||
sender: CommandSender,
|
sender: CommandSender,
|
||||||
argsWithSubCommandNameNotRemoved: Array<out Any>,
|
argsWithSubCommandNameNotRemoved: Array<out Any>,
|
||||||
removeSubName: Boolean
|
removeSubName: Boolean
|
||||||
@ -159,7 +158,7 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
|
|||||||
* @param rawArgs 元素类型必须为 [SingleMessage] 或 [String], 且已经经过扁平化处理. 否则抛出异常 [IllegalArgumentException]
|
* @param rawArgs 元素类型必须为 [SingleMessage] 或 [String], 且已经经过扁平化处理. 否则抛出异常 [IllegalArgumentException]
|
||||||
*/
|
*/
|
||||||
internal fun matchSubCommand(rawArgs: Array<out Any>): SubCommandDescriptor? {
|
internal fun matchSubCommand(rawArgs: Array<out Any>): SubCommandDescriptor? {
|
||||||
val maxCount = rawArgs.size - 1
|
val maxCount = rawArgs.size
|
||||||
var cur = 0
|
var cur = 0
|
||||||
bakedCommandNameToSubDescriptorArray.forEach { (name, descriptor) ->
|
bakedCommandNameToSubDescriptorArray.forEach { (name, descriptor) ->
|
||||||
if (name.size != cur) {
|
if (name.size != cur) {
|
||||||
@ -209,6 +208,29 @@ internal inline fun <T : Any> KClass<out T>.getInstance(): T {
|
|||||||
|
|
||||||
internal val KClass<*>.qualifiedNameOrTip: String get() = this.qualifiedName ?: "<anonymous class>"
|
internal val KClass<*>.qualifiedNameOrTip: String get() = this.qualifiedName ?: "<anonymous class>"
|
||||||
|
|
||||||
|
internal fun Array<AbstractReflectionCommand.SubCommandDescriptor>.createUsage(baseCommand: AbstractReflectionCommand): String =
|
||||||
|
buildString {
|
||||||
|
appendLine(baseCommand.description)
|
||||||
|
appendLine()
|
||||||
|
|
||||||
|
for (subCommandDescriptor in this@createUsage) {
|
||||||
|
appendLine(subCommandDescriptor.usage)
|
||||||
|
}
|
||||||
|
}.trimEnd()
|
||||||
|
|
||||||
|
internal fun AbstractReflectionCommand.SubCommandDescriptor.createUsage(baseCommand: AbstractReflectionCommand): String =
|
||||||
|
buildString {
|
||||||
|
if (!baseCommand.prefixOptional) {
|
||||||
|
append(CommandManager.commandPrefix)
|
||||||
|
}
|
||||||
|
append(names.first())
|
||||||
|
append(" ")
|
||||||
|
append(params.joinToString(" ") { "<${it.name}>" })
|
||||||
|
append(" ")
|
||||||
|
append(description)
|
||||||
|
appendLine()
|
||||||
|
}.trimEnd()
|
||||||
|
|
||||||
internal fun AbstractReflectionCommand.createSubCommand(
|
internal fun AbstractReflectionCommand.createSubCommand(
|
||||||
function: KFunction<*>,
|
function: KFunction<*>,
|
||||||
context: CommandArgumentContext
|
context: CommandArgumentContext
|
||||||
@ -216,7 +238,7 @@ internal fun AbstractReflectionCommand.createSubCommand(
|
|||||||
val notStatic = !function.hasAnnotation<JvmStatic>()
|
val notStatic = !function.hasAnnotation<JvmStatic>()
|
||||||
val overridePermission = function.findAnnotation<CompositeCommand.Permission>()//optional
|
val overridePermission = function.findAnnotation<CompositeCommand.Permission>()//optional
|
||||||
val subDescription =
|
val subDescription =
|
||||||
function.findAnnotation<CompositeCommand.Description>()?.value ?: "<no description available>"
|
function.findAnnotation<CompositeCommand.Description>()?.value ?: ""
|
||||||
|
|
||||||
fun KClass<*>.isValidReturnType(): Boolean {
|
fun KClass<*>.isValidReturnType(): Boolean {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
@ -269,26 +291,20 @@ internal fun AbstractReflectionCommand.createSubCommand(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val buildUsage = StringBuilder(this.description).append(": \n")
|
|
||||||
|
|
||||||
//map parameter
|
//map parameter
|
||||||
val params = parameters.map { param ->
|
val params = parameters.map { param ->
|
||||||
buildUsage.append("/$primaryName ")
|
|
||||||
|
|
||||||
if (param.isOptional) error("optional parameters are not yet supported. (at ${this::class.qualifiedNameOrTip}.${function.name}.$param)")
|
if (param.isOptional) error("optional parameters are not yet supported. (at ${this::class.qualifiedNameOrTip}.${function.name}.$param)")
|
||||||
|
|
||||||
val argName = param.findAnnotation<CompositeCommand.Name>()?.value ?: param.name ?: "unknown"
|
val paramName = param.findAnnotation<CompositeCommand.Name>()?.value ?: param.name ?: "unknown"
|
||||||
buildUsage.append("<").append(argName).append("> ").append(" ")
|
CommandParameter(
|
||||||
CommandParam(
|
paramName,
|
||||||
argName,
|
|
||||||
(param.type.classifier as? KClass<*>)
|
(param.type.classifier as? KClass<*>)
|
||||||
?: throw IllegalArgumentException("unsolved type reference from param " + param.name + ". (at ${this::class.qualifiedNameOrTip}.${function.name}.$param)")
|
?: throw IllegalArgumentException("unsolved type reference from param " + param.name + ". (at ${this::class.qualifiedNameOrTip}.${function.name}.$param)")
|
||||||
)
|
)
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
|
|
||||||
buildUsage.append(subDescription).append("\n")
|
return SubCommandDescriptor(
|
||||||
|
|
||||||
return AbstractReflectionCommand.SubCommandDescriptor(
|
|
||||||
commandName,
|
commandName,
|
||||||
params,
|
params,
|
||||||
subDescription,
|
subDescription,
|
||||||
@ -309,7 +325,6 @@ internal fun AbstractReflectionCommand.createSubCommand(
|
|||||||
|
|
||||||
result as? Boolean ?: true // Unit, void is considered as true.
|
result as? Boolean ?: true // Unit, void is considered as true.
|
||||||
},
|
},
|
||||||
context = context,
|
context = context
|
||||||
usage = buildUsage.toString()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -15,6 +15,7 @@ import kotlinx.coroutines.suspendCancellableCoroutine
|
|||||||
import kotlinx.coroutines.withTimeout
|
import kotlinx.coroutines.withTimeout
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start
|
import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start
|
||||||
|
import net.mamoe.mirai.console.command.CommandManager
|
||||||
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||||
import net.mamoe.mirai.console.plugin.DeferredPluginLoader
|
import net.mamoe.mirai.console.plugin.DeferredPluginLoader
|
||||||
import net.mamoe.mirai.console.plugin.PluginLoader
|
import net.mamoe.mirai.console.plugin.PluginLoader
|
||||||
@ -54,6 +55,7 @@ fun initTestEnvironment() {
|
|||||||
override val settingStorageForBuiltIns: SettingStorage get() = MemorySettingStorage()
|
override val settingStorageForBuiltIns: SettingStorage get() = MemorySettingStorage()
|
||||||
override val coroutineContext: CoroutineContext = SupervisorJob()
|
override val coroutineContext: CoroutineContext = SupervisorJob()
|
||||||
}.start()
|
}.start()
|
||||||
|
CommandManager
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object Testing {
|
internal object Testing {
|
||||||
|
@ -27,8 +27,8 @@ import net.mamoe.mirai.console.command.description.CommandArgumentParser
|
|||||||
import net.mamoe.mirai.console.initTestEnvironment
|
import net.mamoe.mirai.console.initTestEnvironment
|
||||||
import net.mamoe.mirai.console.internal.command.flattenCommandComponents
|
import net.mamoe.mirai.console.internal.command.flattenCommandComponents
|
||||||
import net.mamoe.mirai.message.data.Image
|
import net.mamoe.mirai.message.data.Image
|
||||||
|
import net.mamoe.mirai.message.data.PlainText
|
||||||
import net.mamoe.mirai.message.data.SingleMessage
|
import net.mamoe.mirai.message.data.SingleMessage
|
||||||
import net.mamoe.mirai.message.data.toMessage
|
|
||||||
import org.junit.jupiter.api.AfterAll
|
import org.junit.jupiter.api.AfterAll
|
||||||
import org.junit.jupiter.api.BeforeAll
|
import org.junit.jupiter.api.BeforeAll
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
@ -107,7 +107,7 @@ internal class TestCommand {
|
|||||||
@Test
|
@Test
|
||||||
fun testSimpleArgsSplitting() = runBlocking {
|
fun testSimpleArgsSplitting() = runBlocking {
|
||||||
assertEquals(arrayOf("test", "ttt", "tt").contentToString(), withTesting<Array<String>> {
|
assertEquals(arrayOf("test", "ttt", "tt").contentToString(), withTesting<Array<String>> {
|
||||||
TestSimpleCommand.execute(sender, "test ttt tt".toMessage())
|
TestSimpleCommand.execute(sender, PlainText("test ttt tt"))
|
||||||
}.contentToString())
|
}.contentToString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user