mirror of
https://github.com/mamoe/mirai.git
synced 2025-04-24 20:43:33 +08:00
rebase dev with solve
This commit is contained in:
parent
f7649d225d
commit
db5d0b327c
mirai-console/backend/mirai-console
@ -20,6 +20,7 @@ import net.mamoe.mirai.console.permission.Permission
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalApi
|
||||
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||
import kotlin.annotation.AnnotationTarget.FUNCTION
|
||||
import kotlin.annotation.AnnotationTarget.PROPERTY
|
||||
|
||||
|
||||
/**
|
||||
@ -96,6 +97,13 @@ public abstract class CompositeCommand(
|
||||
|
||||
private val reflector by lazy { CommandReflector(this, CompositeCommandSubCommandAnnotationResolver) }
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
public val overloadImpls: List<@JvmWildcard CommandSignatureFromKFunctionImpl> by lazy {
|
||||
reflector.findSubCommands().also {
|
||||
reflector.validate(it)
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalCommandDescriptors
|
||||
public final override val overloads: List<@JvmWildcard CommandSignatureFromKFunction> by lazy {
|
||||
reflector.findSubCommands().also {
|
||||
@ -126,6 +134,14 @@ public abstract class CompositeCommand(
|
||||
@ResolveContext(COMMAND_NAME) vararg val value: String = [],
|
||||
)
|
||||
|
||||
/**
|
||||
* 标记一个属性为子指令集合
|
||||
*/
|
||||
@Retention(RUNTIME)
|
||||
@Target(PROPERTY)
|
||||
protected annotation class ChildCommand(
|
||||
)
|
||||
|
||||
/** 指令描述 */
|
||||
@Retention(RUNTIME)
|
||||
@Target(FUNCTION)
|
||||
|
@ -81,6 +81,10 @@ internal object CompositeCommandSubCommandAnnotationResolver :
|
||||
|
||||
override fun getDescription(ownerCommand: Command, function: KFunction<*>): String? =
|
||||
function.findAnnotation<CompositeCommand.Description>()?.value
|
||||
|
||||
override fun hasPropertyAnnotation(command: Command, property: KProperty<*>): Boolean =
|
||||
property.hasAnnotation<CompositeCommand.ChildCommand>()
|
||||
|
||||
}
|
||||
|
||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
@ -97,6 +101,8 @@ internal object SimpleCommandSubCommandAnnotationResolver :
|
||||
|
||||
override fun getDescription(ownerCommand: Command, function: KFunction<*>): String =
|
||||
ownerCommand.description
|
||||
|
||||
override fun hasPropertyAnnotation(command: Command, kProperty: KProperty<*>): Boolean = false
|
||||
}
|
||||
|
||||
internal interface SubCommandAnnotationResolver {
|
||||
@ -104,6 +110,7 @@ internal interface SubCommandAnnotationResolver {
|
||||
fun getSubCommandNames(ownerCommand: Command, function: KFunction<*>): Array<out String>
|
||||
fun getAnnotatedName(ownerCommand: Command, parameter: KParameter): String?
|
||||
fun getDescription(ownerCommand: Command, function: KFunction<*>): String?
|
||||
fun hasPropertyAnnotation(command: Command, kProperty: KProperty<*>): Boolean
|
||||
}
|
||||
|
||||
@ConsoleExperimentalApi
|
||||
@ -139,6 +146,7 @@ internal class CommandReflector(
|
||||
throw IllegalCommandDeclarationException(command, this, message)
|
||||
}
|
||||
|
||||
private fun KProperty<*>.isSubCommandProperty(): Boolean = annotationResolver.hasPropertyAnnotation(command, this)
|
||||
private fun KFunction<*>.isSubCommandFunction(): Boolean = annotationResolver.hasAnnotation(command, this)
|
||||
private fun KFunction<*>.checkExtensionReceiver() {
|
||||
this.extensionReceiverParameter?.let { receiver ->
|
||||
@ -260,7 +268,7 @@ internal class CommandReflector(
|
||||
|
||||
@Throws(IllegalCommandDeclarationException::class)
|
||||
fun findSubCommands(): List<CommandSignatureFromKFunctionImpl> {
|
||||
return command::class.functions // exclude static later
|
||||
val fromMemberFunctions = command::class.functions // exclude static later
|
||||
.asSequence()
|
||||
.filter { it.isSubCommandFunction() }
|
||||
.onEach { it.checkExtensionReceiver() }
|
||||
@ -342,6 +350,19 @@ internal class CommandReflector(
|
||||
}
|
||||
}
|
||||
}.toList()
|
||||
|
||||
val fromMemberProperties = command::class.declaredMemberProperties
|
||||
.asSequence()
|
||||
.filter { it.isSubCommandProperty() }
|
||||
.filterIsInstance(CompositeCommand::class.java)
|
||||
.flatMap { property ->
|
||||
property.overloadImpls
|
||||
}.toList()
|
||||
|
||||
val list: MutableList<CommandSignatureFromKFunctionImpl> = ArrayList()
|
||||
list.addAll(fromMemberFunctions)
|
||||
list.addAll(fromMemberProperties)
|
||||
return list
|
||||
}
|
||||
|
||||
private fun isAcceptableReceiverType(classifier: KClass<Any>) =
|
||||
|
@ -34,6 +34,48 @@ import java.time.temporal.TemporalAccessor
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.test.*
|
||||
|
||||
class TestParentCompositeCommand : CompositeCommand(
|
||||
owner,
|
||||
"testParentComposite", "tsPC"
|
||||
) {
|
||||
|
||||
class ChildCompositeCommand1 : CompositeCommand(
|
||||
owner,
|
||||
"testChildComposite1", "tsCC1"
|
||||
) {
|
||||
@SubCommand
|
||||
fun foo(seconds: Int) {
|
||||
Testing.ok(seconds)
|
||||
}
|
||||
}
|
||||
|
||||
class ChildCompositeCommand2 : CompositeCommand(
|
||||
owner,
|
||||
"testChildComposite2", "tsCC2"
|
||||
) {
|
||||
@SubCommand
|
||||
fun bar(seconds: Int) {
|
||||
Testing.ok(seconds)
|
||||
}
|
||||
}
|
||||
|
||||
@ChildCommand
|
||||
val child1: ChildCompositeCommand1 = ChildCompositeCommand1();
|
||||
|
||||
@ChildCommand
|
||||
val child2: ChildCompositeCommand2 = ChildCompositeCommand2();
|
||||
|
||||
@SubCommand
|
||||
fun parentFoo(seconds: Int) {
|
||||
Testing.ok(seconds)
|
||||
}
|
||||
|
||||
@SubCommand
|
||||
fun parentBar(seconds: Int) {
|
||||
Testing.ok(seconds)
|
||||
}
|
||||
}
|
||||
|
||||
class TestCompositeCommand : CompositeCommand(
|
||||
owner,
|
||||
"testComposite", "tsC"
|
||||
@ -163,6 +205,7 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
|
||||
private val simpleCommand by lazy { TestSimpleCommand() }
|
||||
private val rawCommand by lazy { TestRawCommand() }
|
||||
private val compositeCommand by lazy { TestCompositeCommand() }
|
||||
private val parentCompositeCommand by lazy { TestParentCompositeCommand() }
|
||||
|
||||
@BeforeTest
|
||||
fun grantPermission() {
|
||||
@ -499,6 +542,35 @@ internal class InstanceTestCommand : AbstractConsoleInstanceTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `parent composite command executing`() = runBlocking {
|
||||
parentCompositeCommand.withRegistration {
|
||||
assertEquals(1, withTesting {
|
||||
assertSuccess(
|
||||
parentCompositeCommand.execute(sender, "parentFoo 1")
|
||||
)
|
||||
})
|
||||
assertEquals(1, withTesting {
|
||||
assertSuccess(
|
||||
parentCompositeCommand.execute(sender, "parentBar 1")
|
||||
)
|
||||
})
|
||||
assertEquals(1, withTesting {
|
||||
assertSuccess(
|
||||
parentCompositeCommand.execute(sender, "foo 1")
|
||||
)
|
||||
})
|
||||
assertEquals(1, withTesting {
|
||||
assertSuccess(
|
||||
parentCompositeCommand.execute(sender, "foo 1")
|
||||
)
|
||||
})
|
||||
assertEquals(2, withTesting {
|
||||
assertSuccess(parentCompositeCommand.execute(sender, "bar 2"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test first param command sender`() = runTest {
|
||||
object : CompositeCommand(owner, "cmd") {
|
||||
|
Loading…
Reference in New Issue
Block a user