Add param type test for primitive types and fix things
- Made subcommand list sorted - Simplified test command registration and running commands - Fixed primitive type handling where I missed it
This commit is contained in:
parent
f18c5483d8
commit
79c1cc47f7
6 changed files with 75 additions and 44 deletions
|
@ -219,7 +219,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
if (params.isEmpty() || getArgNodes(node, params.toMutableList())) {
|
||||
node.executes(::executeCommand)
|
||||
}
|
||||
return node.build().coreExecutable() ?: throw IllegalStateException("Command node should be executable but isn't: $fullPath")
|
||||
return node.build().coreExecutable() ?: error("Command node should be executable but isn't: $fullPath")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -296,19 +296,21 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
val (lowerLimit, upperLimit) = arg.limits
|
||||
return if (arg.greedy) StringArgumentType.greedyString()
|
||||
else if (ptype == String::class.java) StringArgumentType.word()
|
||||
else if (ptype == Int::class.javaPrimitiveType || ptype == Int::class.java
|
||||
|| ptype == Byte::class.javaPrimitiveType || ptype == Byte::class.java
|
||||
|| ptype == Short::class.javaPrimitiveType || ptype == Short::class.java
|
||||
else if (ptype == Int::class.javaPrimitiveType || ptype == Int::class.javaObjectType
|
||||
|| ptype == Byte::class.javaPrimitiveType || ptype == Byte::class.javaObjectType
|
||||
|| ptype == Short::class.javaPrimitiveType || ptype == Short::class.javaObjectType
|
||||
)
|
||||
IntegerArgumentType.integer(lowerLimit.toInt(), upperLimit.toInt())
|
||||
else if (ptype == Long::class.javaPrimitiveType || ptype == Long::class.java)
|
||||
else if (ptype == Long::class.javaPrimitiveType || ptype == Long::class.javaObjectType)
|
||||
LongArgumentType.longArg(lowerLimit.toLong(), upperLimit.toLong())
|
||||
else if (ptype == Float::class.javaPrimitiveType || ptype == Float::class.java)
|
||||
else if (ptype == Float::class.javaPrimitiveType || ptype == Float::class.javaObjectType)
|
||||
FloatArgumentType.floatArg(lowerLimit.toFloat(), upperLimit.toFloat())
|
||||
else if (ptype == Double::class.javaPrimitiveType || ptype == Double::class.java)
|
||||
else if (ptype == Double::class.javaPrimitiveType || ptype == Double::class.javaObjectType)
|
||||
DoubleArgumentType.doubleArg(lowerLimit, upperLimit)
|
||||
else if (ptype == Char::class.javaPrimitiveType || ptype == Char::class.java) StringArgumentType.word()
|
||||
else if (ptype == Boolean::class.javaPrimitiveType || ptype == Boolean::class.java) BoolArgumentType.bool()
|
||||
else if (ptype == Char::class.javaPrimitiveType || ptype == Char::class.javaObjectType)
|
||||
StringArgumentType.word()
|
||||
else if (ptype == Boolean::class.javaPrimitiveType || ptype == Boolean::class.javaObjectType)
|
||||
BoolArgumentType.bool()
|
||||
else StringArgumentType.word()
|
||||
}
|
||||
|
||||
|
@ -320,10 +322,10 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
* @return Vanilla command success level (0)
|
||||
*/
|
||||
private fun executeHelpText(context: CommandContext<TP>): Int {
|
||||
val node = context.nodes.lastOrNull()?.node ?: throw IllegalStateException()
|
||||
val helpText = node.subcommandDataNoOp()?.getHelpText(context.source) ?: throw IllegalStateException()
|
||||
val node = context.nodes.lastOrNull()?.node ?: error("No nodes found when executing help text for ${context.input}!")
|
||||
val helpText = node.subcommandDataNoOp()?.getHelpText(context.source) ?: error("No subcommand data found when executing help text for ${context.input}")
|
||||
if (node.isCommand()) {
|
||||
val subs = getSubcommands(node.coreCommandNoOp()!!).map { commandChar + it.data.fullPath }
|
||||
val subs = getSubcommands(node.coreCommandNoOp()!!).map { commandChar + it.data.fullPath }.sorted()
|
||||
context.source.sendMessage(helpText + "${ChatColor.GOLD}---- Subcommands ----" + subs)
|
||||
}
|
||||
return 0
|
||||
|
@ -336,7 +338,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
* @return Vanilla command success level (0)
|
||||
*/
|
||||
protected open fun executeCommand(context: CommandContext<TP>): Int {
|
||||
val sd = context.nodes.lastOrNull()?.node?.subcommandData<_, TC>() ?: throw IllegalStateException("Could not find suitable command node for command ${context.input}")
|
||||
val sd = context.nodes.lastOrNull()?.node?.subcommandData<_, TC>() ?: error("Could not find suitable command node for command ${context.input}")
|
||||
val sender = context.source
|
||||
|
||||
if (!sd.hasPermission(sender)) {
|
||||
|
@ -348,7 +350,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
val convertedSender = convertSenderType(sender, sd.senderType)
|
||||
if (convertedSender == null) {
|
||||
//TODO: Should have a prettier display of Command2 classes here
|
||||
val type = sd.senderType.simpleName.fold("") { s, ch -> s + if (ch.isUpperCase()) " " + ch.lowercase() else ch }
|
||||
val type = sd.senderType.simpleName.fold("") { s, ch -> s + if (ch.isUpperCase()) " " + ch.lowercase() else ch }.trim()
|
||||
sender.sendMessage("${ChatColor.RED}You need to be a $type to use this command.")
|
||||
executeHelpText(context) //Send what the command is about, could be useful for commands like /member where some subcommands aren't player-only
|
||||
return 0
|
||||
|
@ -373,10 +375,14 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
|||
} else {
|
||||
val userArgument = context.getArgument(argument.name, String::class.java)
|
||||
val converter = paramConverters[argument.type]?.converter
|
||||
?: throw IllegalStateException("No suitable converter found for ${argument.type} ${argument.name}")
|
||||
?: error("No suitable converter found for ${argument.type} ${argument.name}")
|
||||
params.add(converter.apply(userArgument))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
if (ChromaUtils.isTest && e.message?.contains("No such argument '${argument.name}' exists on this command") != true) {
|
||||
println("For command ${sd.fullPath}:")
|
||||
e.printStackTrace()
|
||||
}
|
||||
if (argument.optional) {
|
||||
params.add(argument.type.getDefaultForEasilyRepresentable())
|
||||
} else {
|
||||
|
|
|
@ -279,7 +279,7 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
|
|||
for (suggestion in suggestions) sbuilder.suggest(suggestion)
|
||||
}
|
||||
}
|
||||
if (argData.type === Boolean::class.javaPrimitiveType || argData.type === Boolean::class.java)
|
||||
if (argData.type === Boolean::class.javaPrimitiveType || argData.type === Boolean::class.javaObjectType)
|
||||
sbuilder.suggest("true").suggest("false")
|
||||
val loweredInput = sbuilder.remaining.lowercase(Locale.getDefault())
|
||||
// The list is automatically ordered, so we need to put the <param> at the end after that
|
||||
|
|
|
@ -7,16 +7,16 @@ import buttondevteam.lib.architecture.Component
|
|||
abstract class ICommand2MC : ICommand2<Command2MCSender>(command2MC) {
|
||||
private var _plugin: ButtonPlugin? = null
|
||||
var plugin: ButtonPlugin
|
||||
get() = _plugin ?: throw IllegalStateException("The command is not registered to a Button plugin!")
|
||||
get() = _plugin ?: error("The command is not registered to a Button plugin!")
|
||||
private set(value) {
|
||||
if (_plugin != null) throw IllegalStateException("The command is already assigned to a Button plugin!")
|
||||
if (_plugin != null) error("The command is already assigned to a Button plugin!")
|
||||
_plugin = value
|
||||
}
|
||||
private var _component: Component<*>? = null
|
||||
var component: Component<*>?
|
||||
get() = _component
|
||||
private set(value) {
|
||||
if (_component != null) throw IllegalStateException("The command is already assigned to a component!")
|
||||
if (_component != null) error("The command is already assigned to a component!")
|
||||
_component = value
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import buttondevteam.lib.chat.Command2MCSender
|
|||
import buttondevteam.lib.chat.CommandClass
|
||||
import buttondevteam.lib.chat.ICommand2MC
|
||||
import buttondevteam.lib.player.TBMCPlayer
|
||||
import org.bukkit.OfflinePlayer
|
||||
|
||||
abstract class Command2MCCommands {
|
||||
@CommandClass(helpText = ["Test command", "Used for testing"])
|
||||
|
@ -97,6 +98,16 @@ abstract class Command2MCCommands {
|
|||
}
|
||||
}
|
||||
|
||||
@CommandClass
|
||||
object TestParamsCommand : ICommand2MC(), ITestCommand2MC {
|
||||
override var testCommandReceived: String? = null
|
||||
|
||||
@Command2.Subcommand
|
||||
fun def(sender: OfflinePlayer, testInt: Int?, testLong: Long?, testDouble: Double?, testDouble2: Double) {
|
||||
testCommandReceived = "$testInt $testLong $testDouble $testDouble2 ${sender.name}"
|
||||
}
|
||||
}
|
||||
|
||||
interface ITestCommand2MC {
|
||||
var testCommandReceived: String?
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@ import buttondevteam.core.MainPlugin
|
|||
import buttondevteam.core.component.channel.Channel
|
||||
import buttondevteam.lib.architecture.ButtonPlugin
|
||||
import buttondevteam.lib.chat.Command2MCSender
|
||||
import buttondevteam.lib.chat.ICommand2MC
|
||||
import buttondevteam.lib.chat.commands.CommandUtils.coreExecutable
|
||||
import buttondevteam.lib.chat.test.Command2MCCommands.*
|
||||
import buttondevteam.lib.player.ChromaGamerBase
|
||||
import buttondevteam.lib.player.TBMCPlayer
|
||||
import org.junit.jupiter.api.MethodOrderer
|
||||
|
@ -34,22 +36,24 @@ class Command2MCTest {
|
|||
@Test
|
||||
@Order(2)
|
||||
fun testRegisterCommand() {
|
||||
MainPlugin.instance.registerCommand(Command2MCCommands.TestCommand)
|
||||
TestCommand.register()
|
||||
val nodes = ButtonPlugin.command2MC.commandNodes
|
||||
assert(nodes.size == 1)
|
||||
assert(nodes.first().literal == "test")
|
||||
val coreExecutable = nodes.first().coreExecutable<Command2MCSender, Command2MCCommands.TestCommand>()
|
||||
assertEquals(Command2MCCommands.TestCommand::class.qualifiedName, coreExecutable?.data?.command?.let { it::class.qualifiedName }, "The command class name doesn't match or command is null")
|
||||
val coreExecutable = nodes.first().coreExecutable<Command2MCSender, TestCommand>()
|
||||
assertEquals(TestCommand::class.qualifiedName, coreExecutable?.data?.command?.let { it::class.qualifiedName }, "The command class name doesn't match or command is null")
|
||||
assertEquals("test", coreExecutable?.data?.argumentsInOrder?.firstOrNull()?.name, "Failed to get correct argument name")
|
||||
assertEquals(String::class.java, coreExecutable?.data?.arguments?.get("test")?.type, "The argument could not be found or type doesn't match")
|
||||
assertEquals(Command2MCSender::class.java, coreExecutable?.data?.senderType, "The sender's type doesn't seem to be stored correctly")
|
||||
|
||||
MainPlugin.instance.registerCommand(Command2MCCommands.NoArgTestCommand)
|
||||
assertEquals("No sender parameter for method '${Command2MCCommands.ErroringTestCommand::class.java.getMethod("def")}'", assertFails { MainPlugin.instance.registerCommand(Command2MCCommands.ErroringTestCommand) }.message)
|
||||
MainPlugin.instance.registerCommand(Command2MCCommands.MultiArgTestCommand)
|
||||
NoArgTestCommand.register()
|
||||
val errCmd = ErroringTestCommand
|
||||
assertEquals("No sender parameter for method '${errCmd::class.java.getMethod("def")}'", assertFails { ErroringTestCommand.register() }.message)
|
||||
MultiArgTestCommand.register()
|
||||
|
||||
MainPlugin.instance.registerCommand(Command2MCCommands.TestNoMainCommand1)
|
||||
MainPlugin.instance.registerCommand(Command2MCCommands.TestNoMainCommand2)
|
||||
TestNoMainCommand1.register()
|
||||
TestNoMainCommand2.register()
|
||||
TestParamsCommand.register()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -95,20 +99,20 @@ class Command2MCTest {
|
|||
return messageReceived
|
||||
}
|
||||
}
|
||||
runCommand(sender, "/test hmm", Command2MCCommands.TestCommand, "hmm")
|
||||
runCommand(sender, "/noargtest", Command2MCCommands.NoArgTestCommand, "TestPlayer")
|
||||
sender.runCommand("/test hmm", TestCommand, "hmm")
|
||||
sender.runCommand("/noargtest", NoArgTestCommand, "TestPlayer")
|
||||
assertFails { ButtonPlugin.command2MC.handleCommand(sender, "/noargtest failing") }
|
||||
runFailingCommand(sender, "/erroringtest")
|
||||
runCommand(sender, "/multiargtest test hmm mhm", Command2MCCommands.MultiArgTestCommand, "hmmmhm")
|
||||
runCommand(sender, "/multiargtest test2 true 19", Command2MCCommands.MultiArgTestCommand, "true 19")
|
||||
sender.runCommand("/multiargtest test hmm mhm", MultiArgTestCommand, "hmmmhm")
|
||||
sender.runCommand("/multiargtest test2 true 19", MultiArgTestCommand, "true 19")
|
||||
|
||||
runCommand(sender, "/multiargtest testoptional", Command2MCCommands.MultiArgTestCommand, "false")
|
||||
runCommand(sender, "/multiargtest testoptional true", Command2MCCommands.MultiArgTestCommand, "true")
|
||||
runCommand(sender, "/multiargtest testoptionalmulti true teszt", Command2MCCommands.MultiArgTestCommand, "true teszt")
|
||||
runCommand(sender, "/multiargtest testoptionalmulti true", Command2MCCommands.MultiArgTestCommand, "true null")
|
||||
runCommand(sender, "/multiargtest testoptionalmulti", Command2MCCommands.MultiArgTestCommand, "false null")
|
||||
sender.runCommand("/multiargtest testoptional", MultiArgTestCommand, "false")
|
||||
sender.runCommand("/multiargtest testoptional true", MultiArgTestCommand, "true")
|
||||
sender.runCommand("/multiargtest testoptionalmulti true teszt", MultiArgTestCommand, "true teszt")
|
||||
sender.runCommand("/multiargtest testoptionalmulti true", MultiArgTestCommand, "true null")
|
||||
sender.runCommand("/multiargtest testoptionalmulti", MultiArgTestCommand, "false null")
|
||||
|
||||
runCommand(sender, "/test plugin Chroma-Core", Command2MCCommands.TestCommand, "Chroma-Core")
|
||||
sender.runCommand("/test plugin Chroma-Core", TestCommand, "Chroma-Core")
|
||||
assertFails { ButtonPlugin.command2MC.handleCommand(sender, "/test playerfail TestPlayer") }
|
||||
|
||||
assertEquals("Test command\n" +
|
||||
|
@ -117,16 +121,22 @@ class Command2MCTest {
|
|||
"/test playerfail\n" +
|
||||
"/test plugin", sender.withMessageReceive { ButtonPlugin.command2MC.handleCommand(sender, "/test") })
|
||||
|
||||
runCommand(sender, "/some test cmd", Command2MCCommands.TestNoMainCommand1, "TestPlayer")
|
||||
runCommand(sender, "/some another cmd", Command2MCCommands.TestNoMainCommand2, "TestPlayer")
|
||||
sender.runCommand("/some test cmd", TestNoMainCommand1, "TestPlayer")
|
||||
sender.runCommand("/some another cmd", TestNoMainCommand2, "TestPlayer")
|
||||
|
||||
assertEquals("§6---- Subcommands ----\n" +
|
||||
"/some test cmd\n" +
|
||||
"/some another cmd", sender.withMessageReceive { ButtonPlugin.command2MC.handleCommand(sender, "/some") })
|
||||
"/some another cmd\n" +
|
||||
"/some test cmd", sender.withMessageReceive { ButtonPlugin.command2MC.handleCommand(sender, "/some") })
|
||||
|
||||
sender.runCommand("/testparams 12 34 56 78", TestParamsCommand, "12 34 56.0 78.0 Player0")
|
||||
}
|
||||
|
||||
private fun runCommand(sender: Command2MCSender, command: String, obj: Command2MCCommands.ITestCommand2MC, expected: String) {
|
||||
assert(ButtonPlugin.command2MC.handleCommand(sender, command)) { "Could not find command $command" }
|
||||
private fun ICommand2MC.register() {
|
||||
MainPlugin.instance.registerCommand(this)
|
||||
}
|
||||
|
||||
private fun Command2MCSender.runCommand(command: String, obj: ITestCommand2MC, expected: String) {
|
||||
assert(ButtonPlugin.command2MC.handleCommand(this, command)) { "Could not find command $command" }
|
||||
assertEquals(expected, obj.testCommandReceived)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ buttondevteam:
|
|||
lib:
|
||||
chat:
|
||||
test:
|
||||
Command2MCTest:
|
||||
Command2MCCommands:
|
||||
TestCommand:
|
||||
def:
|
||||
method: def()
|
||||
|
@ -33,6 +33,10 @@ buttondevteam:
|
|||
def:
|
||||
method: def()
|
||||
params: ''
|
||||
TestParamsCommand:
|
||||
def:
|
||||
method: def()
|
||||
params: 'testInt testLong testDouble testDouble2'
|
||||
core:
|
||||
ComponentCommand:
|
||||
def:
|
||||
|
|
Loading…
Reference in a new issue