Fix CompositeCommand; Rename CommandParam to CommandParameter

This commit is contained in:
Him188 2020-08-20 14:26:44 +08:00
parent 2843f91d02
commit d240ba7b83
5 changed files with 46 additions and 28 deletions

View File

@ -146,6 +146,7 @@ public interface CommandManager {
override fun Command.findDuplicate(): Command? = CommandManagerImpl.run { findDuplicate() }
override fun Command.unregister(): Boolean = CommandManagerImpl.run { unregister() }
override fun Command.isRegistered(): Boolean = CommandManagerImpl.run { isRegistered() }
override val commandPrefix: String get() = CommandManagerImpl.commandPrefix
override suspend fun CommandSender.executeCommand(vararg messages: Any): Command? =
CommandManagerImpl.run { executeCommand(*messages) }
@ -196,4 +197,4 @@ public abstract class PluginCommandOwner(
/**
* 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner].
*/
public object ConsoleCommandOwner : CommandOwner()
internal object ConsoleCommandOwner : CommandOwner()

View File

@ -15,9 +15,9 @@ import net.mamoe.mirai.console.command.CompositeCommand
import java.lang.reflect.Parameter
import kotlin.reflect.KClass
internal fun Parameter.toCommandParam(): CommandParam<*> {
internal fun Parameter.toCommandParam(): CommandParameter<*> {
val name = getAnnotation(CompositeCommand.Name::class.java)
return CommandParam(
return CommandParameter(
name?.value ?: this.name
?: throw IllegalArgumentException("Cannot construct CommandParam from a unnamed param"),
this.type.kotlin
@ -28,7 +28,7 @@ internal fun Parameter.toCommandParam(): CommandParam<*> {
* 指令形式参数.
* @see toCommandParam
*/
internal data class CommandParam<T : Any>(
internal data class CommandParameter<T : Any>(
/**
* 参数名. 不允许重复.
*/

View File

@ -12,10 +12,9 @@
package net.mamoe.mirai.console.internal.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.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.SingleMessage
import kotlin.reflect.KAnnotatedElement
@ -90,7 +89,7 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
}.map { function ->
createSubCommand(function, context)
}.toTypedArray().also {
_usage = it.firstOrNull()?.usage ?: description
_usage = it.createUsage(this)
}.also { checkSubCommand(it) }
}
@ -112,16 +111,16 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
val onCommand: suspend (sender: CommandSender, rawArgs: Array<out Any>) -> Unit
)
internal class SubCommandDescriptor(
internal inner class SubCommandDescriptor(
val names: Array<out String>,
val params: Array<CommandParam<*>>,
val params: Array<CommandParameter<*>>,
val description: String,
val permission: CommandPermission,
val onCommand: suspend (sender: CommandSender, parsedArgs: Array<out Any>) -> Boolean,
val context: CommandArgumentContext,
val usage: String
val context: CommandArgumentContext
) {
internal suspend inline fun parseAndExecute(
val usage: String = createUsage(this@AbstractReflectionCommand)
internal suspend fun parseAndExecute(
sender: CommandSender,
argsWithSubCommandNameNotRemoved: Array<out Any>,
removeSubName: Boolean
@ -159,7 +158,7 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
* @param rawArgs 元素类型必须为 [SingleMessage] [String], 且已经经过扁平化处理. 否则抛出异常 [IllegalArgumentException]
*/
internal fun matchSubCommand(rawArgs: Array<out Any>): SubCommandDescriptor? {
val maxCount = rawArgs.size - 1
val maxCount = rawArgs.size
var cur = 0
bakedCommandNameToSubDescriptorArray.forEach { (name, descriptor) ->
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 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(
function: KFunction<*>,
context: CommandArgumentContext
@ -216,7 +238,7 @@ internal fun AbstractReflectionCommand.createSubCommand(
val notStatic = !function.hasAnnotation<JvmStatic>()
val overridePermission = function.findAnnotation<CompositeCommand.Permission>()//optional
val subDescription =
function.findAnnotation<CompositeCommand.Description>()?.value ?: "<no description available>"
function.findAnnotation<CompositeCommand.Description>()?.value ?: ""
fun KClass<*>.isValidReturnType(): Boolean {
return when (this) {
@ -269,26 +291,20 @@ internal fun AbstractReflectionCommand.createSubCommand(
}
}
val buildUsage = StringBuilder(this.description).append(": \n")
//map parameter
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)")
val argName = param.findAnnotation<CompositeCommand.Name>()?.value ?: param.name ?: "unknown"
buildUsage.append("<").append(argName).append("> ").append(" ")
CommandParam(
argName,
val paramName = param.findAnnotation<CompositeCommand.Name>()?.value ?: param.name ?: "unknown"
CommandParameter(
paramName,
(param.type.classifier as? KClass<*>)
?: throw IllegalArgumentException("unsolved type reference from param " + param.name + ". (at ${this::class.qualifiedNameOrTip}.${function.name}.$param)")
)
}.toTypedArray()
buildUsage.append(subDescription).append("\n")
return AbstractReflectionCommand.SubCommandDescriptor(
return SubCommandDescriptor(
commandName,
params,
subDescription,
@ -309,7 +325,6 @@ internal fun AbstractReflectionCommand.createSubCommand(
result as? Boolean ?: true // Unit, void is considered as true.
},
context = context,
usage = buildUsage.toString()
context = context
)
}

View File

@ -15,6 +15,7 @@ import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeout
import net.mamoe.mirai.Bot
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.plugin.DeferredPluginLoader
import net.mamoe.mirai.console.plugin.PluginLoader
@ -54,6 +55,7 @@ fun initTestEnvironment() {
override val settingStorageForBuiltIns: SettingStorage get() = MemorySettingStorage()
override val coroutineContext: CoroutineContext = SupervisorJob()
}.start()
CommandManager
}
internal object Testing {

View File

@ -27,8 +27,8 @@ import net.mamoe.mirai.console.command.description.CommandArgumentParser
import net.mamoe.mirai.console.initTestEnvironment
import net.mamoe.mirai.console.internal.command.flattenCommandComponents
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.toMessage
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
@ -107,7 +107,7 @@ internal class TestCommand {
@Test
fun testSimpleArgsSplitting() = runBlocking {
assertEquals(arrayOf("test", "ttt", "tt").contentToString(), withTesting<Array<String>> {
TestSimpleCommand.execute(sender, "test ttt tt".toMessage())
TestSimpleCommand.execute(sender, PlainText("test ttt tt"))
}.contentToString())
}