Remove 'main command' and test empty command to improve coverage

This commit is contained in:
Norbi Peti 2023-07-31 20:43:20 +02:00
parent 7e511c169b
commit 2787c280f5
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
4 changed files with 17 additions and 23 deletions

View file

@ -154,25 +154,21 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
* @param command The command to register * @param command The command to register
* @return The Brigadier command node if you need it for something (like tab completion) * @return The Brigadier command node if you need it for something (like tab completion)
*/ */
protected fun registerCommandSuper(command: TC): CoreCommandNode<TP, *> { protected fun registerCommandSuper(command: TC): List<CoreExecutableNode<TP, TC>> {
var mainCommandNode: CoreCommandNode<TP, *>? = null val registeredNodes = mutableListOf<CoreExecutableNode<TP, TC>>()
for (meth in command.javaClass.methods) { for (meth in command.javaClass.methods) {
val ann = meth.getAnnotation(Subcommand::class.java) ?: continue val ann = meth.getAnnotation(Subcommand::class.java) ?: continue
val fullPath = command.commandPath + CommandUtils.getCommandPath(meth.name, ' ') val fullPath = command.commandPath + CommandUtils.getCommandPath(meth.name, ' ')
assert(fullPath.isNotBlank()) { "No path found for command class ${command.javaClass.name} and method ${meth.name}" } assert(fullPath.isNotBlank()) { "No path found for command class ${command.javaClass.name} and method ${meth.name}" }
val (lastNode, mainNodeMaybe, remainingPath) = registerNodeFromPath(fullPath) val (lastNode, remainingPath) = registerNodeFromPath(fullPath)
val execNode = getExecutableNode(meth, command, ann, remainingPath, CommandArgumentHelpManager(command), fullPath) val execNode = getExecutableNode(meth, command, ann, remainingPath, CommandArgumentHelpManager(command), fullPath)
lastNode.addChild(execNode) lastNode.addChild(execNode)
val mainNode = mainNodeMaybe ?: execNode registeredNodes.add(execNode)
if (mainCommandNode == null) mainCommandNode = mainNode
else if (mainNode.name != mainCommandNode.name) {
MainPlugin.instance.logger.warning("Multiple commands are defined in the same class! This is not supported. Class: " + command.javaClass.simpleName)
}
} }
if (mainCommandNode == null) { if (registeredNodes.isEmpty()) {
throw RuntimeException("There are no subcommands defined in the command class " + command.javaClass.simpleName + "!") throw RuntimeException("There are no subcommands defined in the command class ${command.javaClass.simpleName}!")
} }
return mainCommandNode return registeredNodes.toList()
} }
/** /**
@ -236,19 +232,16 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
* @return The last no-op node that can be used to register the executable node, * @return The last no-op node that can be used to register the executable node,
* the main command node and the last part of the command path (that isn't registered yet) * the main command node and the last part of the command path (that isn't registered yet)
*/ */
private fun registerNodeFromPath(path: String): Triple<CommandNode<TP>, CoreCommandNode<TP, *>?, String> { private fun registerNodeFromPath(path: String): Pair<CommandNode<TP>, String> {
val split = path.split(" ") val split = path.split(" ")
var parent: CommandNode<TP> = dispatcher.root var parent: CommandNode<TP> = dispatcher.root
var mainCommand: CoreCommandNode<TP, *>? = null split.dropLast(1).forEach { part ->
split.dropLast(1).forEachIndexed { i, part ->
val child = parent.getChild(part) val child = parent.getChild(part)
if (child == null) parent.addChild(CoreCommandBuilder.literalNoOp<TP, TC>(part) { emptyArray() } if (child == null) parent.addChild(CoreCommandBuilder.literalNoOp<TP, TC>(part) { emptyArray() }
.executes(::executeHelpText).build().also { parent = it }) .executes(::executeHelpText).build().also { parent = it })
else parent = child else parent = child
if (i == 0) mainCommand =
parent as CoreCommandNode<TP, *> // Has to be our own literal node, if not, well, error
} }
return Triple(parent, mainCommand, split.last()) return Pair(parent, split.last())
} }
fun getCommandList(sender: TP): Array<String> { fun getCommandList(sender: TP): Array<String> {

View file

@ -7,7 +7,6 @@ import buttondevteam.lib.architecture.ButtonPlugin
import buttondevteam.lib.architecture.Component import buttondevteam.lib.architecture.Component
import buttondevteam.lib.chat.commands.CommandUtils import buttondevteam.lib.chat.commands.CommandUtils
import buttondevteam.lib.chat.commands.CommandUtils.coreArgument import buttondevteam.lib.chat.commands.CommandUtils.coreArgument
import buttondevteam.lib.chat.commands.CommandUtils.coreExecutable
import buttondevteam.lib.chat.commands.MCCommandSettings import buttondevteam.lib.chat.commands.MCCommandSettings
import buttondevteam.lib.chat.commands.SubcommandData import buttondevteam.lib.chat.commands.SubcommandData
import buttondevteam.lib.player.ChromaGamerBase import buttondevteam.lib.player.ChromaGamerBase
@ -37,14 +36,12 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
* @param command The command to register * @param command The command to register
*/ */
override fun registerCommand(command: ICommand2MC) { override fun registerCommand(command: ICommand2MC) {
val commandNode = super.registerCommandSuper(command) val nodes = super.registerCommandSuper(command)
val bcmd = registerOfficially(command, commandNode)
// TODO: Support aliases
val permPrefix = "chroma.command." val permPrefix = "chroma.command."
//Allow commands by default, it will check mod-only //Allow commands by default, it will check mod-only
val nodes = commandNode.coreExecutable<Command2MCSender, ICommand2MC>()
?.let { getSubcommands(commandNode) + it } ?: getSubcommands(commandNode)
for (node in nodes) { for (node in nodes) {
val bcmd = registerOfficially(command, node)
// TODO: Support aliases
val subperm = permPrefix + node.data.fullPath.replace(' ', '.') val subperm = permPrefix + node.data.fullPath.replace(' ', '.')
if (Bukkit.getPluginManager().getPermission(subperm) == null) //Check needed for plugin reset if (Bukkit.getPluginManager().getPermission(subperm) == null) //Check needed for plugin reset
Bukkit.getPluginManager().addPermission(Permission(subperm, PermissionDefault.TRUE)) Bukkit.getPluginManager().addPermission(Permission(subperm, PermissionDefault.TRUE))

View file

@ -119,6 +119,9 @@ abstract class Command2MCCommands {
} }
} }
@CommandClass
object TestEmptyCommand : ICommand2MC()
interface ITestCommand2MC { interface ITestCommand2MC {
var testCommandReceived: String? var testCommandReceived: String?
} }

View file

@ -53,6 +53,7 @@ class Command2MCTest {
TestNoMainCommand1.register() TestNoMainCommand1.register()
TestNoMainCommand2.register() TestNoMainCommand2.register()
TestParamsCommand.register() TestParamsCommand.register()
assertEquals("There are no subcommands defined in the command class TestEmptyCommand!", assertFails { TestEmptyCommand.register() }.message)
} }
@Test @Test