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())) {
|
if (params.isEmpty() || getArgNodes(node, params.toMutableList())) {
|
||||||
node.executes(::executeCommand)
|
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
|
val (lowerLimit, upperLimit) = arg.limits
|
||||||
return if (arg.greedy) StringArgumentType.greedyString()
|
return if (arg.greedy) StringArgumentType.greedyString()
|
||||||
else if (ptype == String::class.java) StringArgumentType.word()
|
else if (ptype == String::class.java) StringArgumentType.word()
|
||||||
else if (ptype == Int::class.javaPrimitiveType || ptype == Int::class.java
|
else if (ptype == Int::class.javaPrimitiveType || ptype == Int::class.javaObjectType
|
||||||
|| ptype == Byte::class.javaPrimitiveType || ptype == Byte::class.java
|
|| ptype == Byte::class.javaPrimitiveType || ptype == Byte::class.javaObjectType
|
||||||
|| ptype == Short::class.javaPrimitiveType || ptype == Short::class.java
|
|| ptype == Short::class.javaPrimitiveType || ptype == Short::class.javaObjectType
|
||||||
)
|
)
|
||||||
IntegerArgumentType.integer(lowerLimit.toInt(), upperLimit.toInt())
|
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())
|
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())
|
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)
|
DoubleArgumentType.doubleArg(lowerLimit, upperLimit)
|
||||||
else if (ptype == Char::class.javaPrimitiveType || ptype == Char::class.java) StringArgumentType.word()
|
else if (ptype == Char::class.javaPrimitiveType || ptype == Char::class.javaObjectType)
|
||||||
else if (ptype == Boolean::class.javaPrimitiveType || ptype == Boolean::class.java) BoolArgumentType.bool()
|
StringArgumentType.word()
|
||||||
|
else if (ptype == Boolean::class.javaPrimitiveType || ptype == Boolean::class.javaObjectType)
|
||||||
|
BoolArgumentType.bool()
|
||||||
else StringArgumentType.word()
|
else StringArgumentType.word()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,10 +322,10 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
* @return Vanilla command success level (0)
|
* @return Vanilla command success level (0)
|
||||||
*/
|
*/
|
||||||
private fun executeHelpText(context: CommandContext<TP>): Int {
|
private fun executeHelpText(context: CommandContext<TP>): Int {
|
||||||
val node = context.nodes.lastOrNull()?.node ?: 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) ?: throw IllegalStateException()
|
val helpText = node.subcommandDataNoOp()?.getHelpText(context.source) ?: error("No subcommand data found when executing help text for ${context.input}")
|
||||||
if (node.isCommand()) {
|
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)
|
context.source.sendMessage(helpText + "${ChatColor.GOLD}---- Subcommands ----" + subs)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -336,7 +338,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
* @return Vanilla command success level (0)
|
* @return Vanilla command success level (0)
|
||||||
*/
|
*/
|
||||||
protected open fun executeCommand(context: CommandContext<TP>): Int {
|
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
|
val sender = context.source
|
||||||
|
|
||||||
if (!sd.hasPermission(sender)) {
|
if (!sd.hasPermission(sender)) {
|
||||||
|
@ -348,7 +350,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
val convertedSender = convertSenderType(sender, sd.senderType)
|
val convertedSender = convertSenderType(sender, sd.senderType)
|
||||||
if (convertedSender == null) {
|
if (convertedSender == null) {
|
||||||
//TODO: Should have a prettier display of Command2 classes here
|
//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.")
|
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
|
executeHelpText(context) //Send what the command is about, could be useful for commands like /member where some subcommands aren't player-only
|
||||||
return 0
|
return 0
|
||||||
|
@ -373,10 +375,14 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
} else {
|
} else {
|
||||||
val userArgument = context.getArgument(argument.name, String::class.java)
|
val userArgument = context.getArgument(argument.name, String::class.java)
|
||||||
val converter = paramConverters[argument.type]?.converter
|
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))
|
params.add(converter.apply(userArgument))
|
||||||
}
|
}
|
||||||
} catch (e: IllegalArgumentException) {
|
} 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) {
|
if (argument.optional) {
|
||||||
params.add(argument.type.getDefaultForEasilyRepresentable())
|
params.add(argument.type.getDefaultForEasilyRepresentable())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -279,7 +279,7 @@ class Command2MC : Command2<ICommand2MC, Command2MCSender>('/', true), Listener
|
||||||
for (suggestion in suggestions) sbuilder.suggest(suggestion)
|
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")
|
sbuilder.suggest("true").suggest("false")
|
||||||
val loweredInput = sbuilder.remaining.lowercase(Locale.getDefault())
|
val loweredInput = sbuilder.remaining.lowercase(Locale.getDefault())
|
||||||
// The list is automatically ordered, so we need to put the <param> at the end after that
|
// 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) {
|
abstract class ICommand2MC : ICommand2<Command2MCSender>(command2MC) {
|
||||||
private var _plugin: ButtonPlugin? = null
|
private var _plugin: ButtonPlugin? = null
|
||||||
var plugin: ButtonPlugin
|
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) {
|
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
|
_plugin = value
|
||||||
}
|
}
|
||||||
private var _component: Component<*>? = null
|
private var _component: Component<*>? = null
|
||||||
var component: Component<*>?
|
var component: Component<*>?
|
||||||
get() = _component
|
get() = _component
|
||||||
private set(value) {
|
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
|
_component = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import buttondevteam.lib.chat.Command2MCSender
|
||||||
import buttondevteam.lib.chat.CommandClass
|
import buttondevteam.lib.chat.CommandClass
|
||||||
import buttondevteam.lib.chat.ICommand2MC
|
import buttondevteam.lib.chat.ICommand2MC
|
||||||
import buttondevteam.lib.player.TBMCPlayer
|
import buttondevteam.lib.player.TBMCPlayer
|
||||||
|
import org.bukkit.OfflinePlayer
|
||||||
|
|
||||||
abstract class Command2MCCommands {
|
abstract class Command2MCCommands {
|
||||||
@CommandClass(helpText = ["Test command", "Used for testing"])
|
@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 {
|
interface ITestCommand2MC {
|
||||||
var testCommandReceived: String?
|
var testCommandReceived: String?
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@ import buttondevteam.core.MainPlugin
|
||||||
import buttondevteam.core.component.channel.Channel
|
import buttondevteam.core.component.channel.Channel
|
||||||
import buttondevteam.lib.architecture.ButtonPlugin
|
import buttondevteam.lib.architecture.ButtonPlugin
|
||||||
import buttondevteam.lib.chat.Command2MCSender
|
import buttondevteam.lib.chat.Command2MCSender
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC
|
||||||
import buttondevteam.lib.chat.commands.CommandUtils.coreExecutable
|
import buttondevteam.lib.chat.commands.CommandUtils.coreExecutable
|
||||||
|
import buttondevteam.lib.chat.test.Command2MCCommands.*
|
||||||
import buttondevteam.lib.player.ChromaGamerBase
|
import buttondevteam.lib.player.ChromaGamerBase
|
||||||
import buttondevteam.lib.player.TBMCPlayer
|
import buttondevteam.lib.player.TBMCPlayer
|
||||||
import org.junit.jupiter.api.MethodOrderer
|
import org.junit.jupiter.api.MethodOrderer
|
||||||
|
@ -34,22 +36,24 @@ class Command2MCTest {
|
||||||
@Test
|
@Test
|
||||||
@Order(2)
|
@Order(2)
|
||||||
fun testRegisterCommand() {
|
fun testRegisterCommand() {
|
||||||
MainPlugin.instance.registerCommand(Command2MCCommands.TestCommand)
|
TestCommand.register()
|
||||||
val nodes = ButtonPlugin.command2MC.commandNodes
|
val nodes = ButtonPlugin.command2MC.commandNodes
|
||||||
assert(nodes.size == 1)
|
assert(nodes.size == 1)
|
||||||
assert(nodes.first().literal == "test")
|
assert(nodes.first().literal == "test")
|
||||||
val coreExecutable = nodes.first().coreExecutable<Command2MCSender, Command2MCCommands.TestCommand>()
|
val coreExecutable = nodes.first().coreExecutable<Command2MCSender, TestCommand>()
|
||||||
assertEquals(Command2MCCommands.TestCommand::class.qualifiedName, coreExecutable?.data?.command?.let { it::class.qualifiedName }, "The command class name doesn't match or command is null")
|
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("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(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")
|
assertEquals(Command2MCSender::class.java, coreExecutable?.data?.senderType, "The sender's type doesn't seem to be stored correctly")
|
||||||
|
|
||||||
MainPlugin.instance.registerCommand(Command2MCCommands.NoArgTestCommand)
|
NoArgTestCommand.register()
|
||||||
assertEquals("No sender parameter for method '${Command2MCCommands.ErroringTestCommand::class.java.getMethod("def")}'", assertFails { MainPlugin.instance.registerCommand(Command2MCCommands.ErroringTestCommand) }.message)
|
val errCmd = ErroringTestCommand
|
||||||
MainPlugin.instance.registerCommand(Command2MCCommands.MultiArgTestCommand)
|
assertEquals("No sender parameter for method '${errCmd::class.java.getMethod("def")}'", assertFails { ErroringTestCommand.register() }.message)
|
||||||
|
MultiArgTestCommand.register()
|
||||||
|
|
||||||
MainPlugin.instance.registerCommand(Command2MCCommands.TestNoMainCommand1)
|
TestNoMainCommand1.register()
|
||||||
MainPlugin.instance.registerCommand(Command2MCCommands.TestNoMainCommand2)
|
TestNoMainCommand2.register()
|
||||||
|
TestParamsCommand.register()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -95,20 +99,20 @@ class Command2MCTest {
|
||||||
return messageReceived
|
return messageReceived
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
runCommand(sender, "/test hmm", Command2MCCommands.TestCommand, "hmm")
|
sender.runCommand("/test hmm", TestCommand, "hmm")
|
||||||
runCommand(sender, "/noargtest", Command2MCCommands.NoArgTestCommand, "TestPlayer")
|
sender.runCommand("/noargtest", NoArgTestCommand, "TestPlayer")
|
||||||
assertFails { ButtonPlugin.command2MC.handleCommand(sender, "/noargtest failing") }
|
assertFails { ButtonPlugin.command2MC.handleCommand(sender, "/noargtest failing") }
|
||||||
runFailingCommand(sender, "/erroringtest")
|
runFailingCommand(sender, "/erroringtest")
|
||||||
runCommand(sender, "/multiargtest test hmm mhm", Command2MCCommands.MultiArgTestCommand, "hmmmhm")
|
sender.runCommand("/multiargtest test hmm mhm", MultiArgTestCommand, "hmmmhm")
|
||||||
runCommand(sender, "/multiargtest test2 true 19", Command2MCCommands.MultiArgTestCommand, "true 19")
|
sender.runCommand("/multiargtest test2 true 19", MultiArgTestCommand, "true 19")
|
||||||
|
|
||||||
runCommand(sender, "/multiargtest testoptional", Command2MCCommands.MultiArgTestCommand, "false")
|
sender.runCommand("/multiargtest testoptional", MultiArgTestCommand, "false")
|
||||||
runCommand(sender, "/multiargtest testoptional true", Command2MCCommands.MultiArgTestCommand, "true")
|
sender.runCommand("/multiargtest testoptional true", MultiArgTestCommand, "true")
|
||||||
runCommand(sender, "/multiargtest testoptionalmulti true teszt", Command2MCCommands.MultiArgTestCommand, "true teszt")
|
sender.runCommand("/multiargtest testoptionalmulti true teszt", MultiArgTestCommand, "true teszt")
|
||||||
runCommand(sender, "/multiargtest testoptionalmulti true", Command2MCCommands.MultiArgTestCommand, "true null")
|
sender.runCommand("/multiargtest testoptionalmulti true", MultiArgTestCommand, "true null")
|
||||||
runCommand(sender, "/multiargtest testoptionalmulti", Command2MCCommands.MultiArgTestCommand, "false 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") }
|
assertFails { ButtonPlugin.command2MC.handleCommand(sender, "/test playerfail TestPlayer") }
|
||||||
|
|
||||||
assertEquals("Test command\n" +
|
assertEquals("Test command\n" +
|
||||||
|
@ -117,16 +121,22 @@ class Command2MCTest {
|
||||||
"/test playerfail\n" +
|
"/test playerfail\n" +
|
||||||
"/test plugin", sender.withMessageReceive { ButtonPlugin.command2MC.handleCommand(sender, "/test") })
|
"/test plugin", sender.withMessageReceive { ButtonPlugin.command2MC.handleCommand(sender, "/test") })
|
||||||
|
|
||||||
runCommand(sender, "/some test cmd", Command2MCCommands.TestNoMainCommand1, "TestPlayer")
|
sender.runCommand("/some test cmd", TestNoMainCommand1, "TestPlayer")
|
||||||
runCommand(sender, "/some another cmd", Command2MCCommands.TestNoMainCommand2, "TestPlayer")
|
sender.runCommand("/some another cmd", TestNoMainCommand2, "TestPlayer")
|
||||||
|
|
||||||
assertEquals("§6---- Subcommands ----\n" +
|
assertEquals("§6---- Subcommands ----\n" +
|
||||||
"/some test cmd\n" +
|
"/some another cmd\n" +
|
||||||
"/some another cmd", sender.withMessageReceive { ButtonPlugin.command2MC.handleCommand(sender, "/some") })
|
"/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) {
|
private fun ICommand2MC.register() {
|
||||||
assert(ButtonPlugin.command2MC.handleCommand(sender, command)) { "Could not find command $command" }
|
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)
|
assertEquals(expected, obj.testCommandReceived)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ buttondevteam:
|
||||||
lib:
|
lib:
|
||||||
chat:
|
chat:
|
||||||
test:
|
test:
|
||||||
Command2MCTest:
|
Command2MCCommands:
|
||||||
TestCommand:
|
TestCommand:
|
||||||
def:
|
def:
|
||||||
method: def()
|
method: def()
|
||||||
|
@ -33,6 +33,10 @@ buttondevteam:
|
||||||
def:
|
def:
|
||||||
method: def()
|
method: def()
|
||||||
params: ''
|
params: ''
|
||||||
|
TestParamsCommand:
|
||||||
|
def:
|
||||||
|
method: def()
|
||||||
|
params: 'testInt testLong testDouble testDouble2'
|
||||||
core:
|
core:
|
||||||
ComponentCommand:
|
ComponentCommand:
|
||||||
def:
|
def:
|
||||||
|
|
Loading…
Reference in a new issue