Add command test and fix command path handling
- It feels so good to be able to debug this code
This commit is contained in:
parent
29f7883f9b
commit
f05305cb0a
7 changed files with 141 additions and 37 deletions
|
@ -37,7 +37,7 @@
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.8.1</version>
|
<version>3.8.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<compilerArgument>-proc:none</compilerArgument>
|
<proc>none</proc>
|
||||||
<source>17</source>
|
<source>17</source>
|
||||||
<target>17</target>
|
<target>17</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -249,6 +249,12 @@
|
||||||
<artifactId>mccoroutine-bukkit-core</artifactId>
|
<artifactId>mccoroutine-bukkit-core</artifactId>
|
||||||
<version>2.11.0</version>
|
<version>2.11.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.seeseemelk</groupId>
|
||||||
|
<artifactId>MockBukkit-v1.19</artifactId>
|
||||||
|
<version>2.29.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<organization>
|
<organization>
|
||||||
<name>TBMCPlugins</name>
|
<name>TBMCPlugins</name>
|
||||||
|
|
|
@ -90,8 +90,14 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
paramConverters[cl] = ParamConverter(converter, errormsg, allSupplier)
|
paramConverters[cl] = ParamConverter(converter, errormsg, allSupplier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the given command line as sent by the sender.
|
||||||
|
*
|
||||||
|
* @param sender The sender who sent the command
|
||||||
|
* @param commandline The command line, including the leading command char
|
||||||
|
*/
|
||||||
open fun handleCommand(sender: TP, commandline: String): Boolean {
|
open fun handleCommand(sender: TP, commandline: String): Boolean {
|
||||||
val results = dispatcher.parse(commandline, sender)
|
val results = dispatcher.parse(commandline.removePrefix("/"), sender)
|
||||||
if (results.reader.canRead()) {
|
if (results.reader.canRead()) {
|
||||||
return false // Unknown command
|
return false // Unknown command
|
||||||
}
|
}
|
||||||
|
@ -138,6 +144,7 @@ abstract class Command2<TC : ICommand2<TP>, TP : Command2Sender>(
|
||||||
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}" }
|
||||||
val (lastNode, mainNode, remainingPath) = registerNodeFromPath(fullPath)
|
val (lastNode, mainNode, remainingPath) = registerNodeFromPath(fullPath)
|
||||||
lastNode.addChild(getExecutableNode(meth, command, ann, remainingPath, CommandArgumentHelpManager(command), fullPath))
|
lastNode.addChild(getExecutableNode(meth, command, ann, remainingPath, CommandArgumentHelpManager(command), fullPath))
|
||||||
if (mainCommandNode == null) mainCommandNode = mainNode
|
if (mainCommandNode == null) mainCommandNode = mainNode
|
||||||
|
|
|
@ -74,32 +74,31 @@ abstract class ICommand2<TP : Command2Sender>(val manager: Command2<*, TP>) {
|
||||||
get() = EMPTY_PATHS // TODO: Deal with this (used for channel IDs)
|
get() = EMPTY_PATHS // TODO: Deal with this (used for channel IDs)
|
||||||
|
|
||||||
private fun getcmdpath(): String {
|
private fun getcmdpath(): String {
|
||||||
if (!javaClass.isAnnotationPresent(CommandClass::class.java)) throw RuntimeException(
|
if (!javaClass.isAnnotationPresent(CommandClass::class.java))
|
||||||
"No @CommandClass annotation on command class " + javaClass.simpleName + "!"
|
throw RuntimeException("No @CommandClass annotation on command class ${javaClass.simpleName}!")
|
||||||
)
|
|
||||||
val getFromClass = Function { cl: Class<*> ->
|
val getFromClass = Function { cl: Class<*> ->
|
||||||
cl.simpleName.lowercase(Locale.getDefault()).replace("commandbase", "") // <-- ...
|
cl.simpleName.lowercase(Locale.getDefault()).replace("commandbase", "") // <-- ...
|
||||||
.replace("command", "")
|
.replace("command", "")
|
||||||
}
|
}
|
||||||
var path = javaClass.getAnnotation(CommandClass::class.java).path
|
val classList = mutableListOf<Class<*>>(javaClass)
|
||||||
var prevpath = if (path.isEmpty()) getFromClass.apply(javaClass) else path.also { path = it }
|
while (true) {
|
||||||
var cl: Class<*>? = javaClass.superclass
|
val superClass = classList.last().superclass
|
||||||
while (cl != null && cl.getPackage().name != ICommand2MC::class.java.getPackage().name) {
|
if (superClass != null && superClass.getPackage().name != ICommand2MC::class.java.getPackage().name) {
|
||||||
//
|
classList.add(superClass)
|
||||||
var newpath: String
|
} else {
|
||||||
val ccann: CommandClass? = cl.getAnnotation(CommandClass::class.java)
|
break
|
||||||
if (ccann?.path.isNullOrEmpty() || ccann?.path == prevpath) {
|
|
||||||
if (ccann?.excludeFromPath ?: Modifier.isAbstract(cl.modifiers)) {
|
|
||||||
cl = cl.superclass
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
newpath = getFromClass.apply(cl)
|
|
||||||
} else newpath = ccann!!.path
|
|
||||||
path = "$newpath $path"
|
|
||||||
prevpath = newpath
|
|
||||||
cl = cl.superclass
|
|
||||||
}
|
}
|
||||||
return path
|
return classList.reversed().associateWith { it.getAnnotation(CommandClass::class.java) }
|
||||||
|
.mapNotNull {
|
||||||
|
if (it.value?.path.isNullOrEmpty())
|
||||||
|
if (it.value?.excludeFromPath ?: Modifier.isAbstract(it.key.modifiers))
|
||||||
|
null
|
||||||
|
else
|
||||||
|
it.key.simpleName.lowercase().removeSuffix("commandbase").removeSuffix("command")
|
||||||
|
else
|
||||||
|
it.value.path
|
||||||
|
}.joinToString(" ")
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package buttondevteam.lib.chat.test
|
||||||
|
|
||||||
|
import be.seeseemelk.mockbukkit.MockBukkit
|
||||||
|
import buttondevteam.core.MainPlugin
|
||||||
|
import buttondevteam.core.component.channel.Channel
|
||||||
|
import buttondevteam.lib.architecture.ButtonPlugin
|
||||||
|
import buttondevteam.lib.chat.Command2
|
||||||
|
import buttondevteam.lib.chat.Command2MCSender
|
||||||
|
import buttondevteam.lib.chat.CommandClass
|
||||||
|
import buttondevteam.lib.chat.ICommand2MC
|
||||||
|
import buttondevteam.lib.player.ChromaGamerBase
|
||||||
|
import buttondevteam.lib.player.TBMCPlayer
|
||||||
|
import org.junit.jupiter.api.MethodOrderer
|
||||||
|
import org.junit.jupiter.api.Order
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.TestMethodOrder
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
@TestMethodOrder(MethodOrderer.OrderAnnotation::class)
|
||||||
|
class Command2MCTest {
|
||||||
|
|
||||||
|
init {
|
||||||
|
if (!initialized) {
|
||||||
|
try {
|
||||||
|
MockBukkit.mock()
|
||||||
|
} catch (e: IllegalStateException) {
|
||||||
|
throw RuntimeException("Failed to init tests! Something in here fails to initialize. Check the first test case.", e)
|
||||||
|
}
|
||||||
|
MockBukkit.load(MainPlugin::class.java, true)
|
||||||
|
ButtonPlugin.command2MC.unregisterCommands(MainPlugin.instance) // FIXME should have the init code separate of the plugin init code
|
||||||
|
initialized = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(1)
|
||||||
|
fun testRegisterCommand() {
|
||||||
|
MainPlugin.instance.registerCommand(TestCommand)
|
||||||
|
assert(ButtonPlugin.command2MC.commandNodes.size == 1)
|
||||||
|
assert(ButtonPlugin.command2MC.commandNodes.first().literal == "test")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasPermission() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAddParamConverter() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testUnregisterCommands() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(2)
|
||||||
|
fun testHandleCommand() {
|
||||||
|
val user = ChromaGamerBase.getUser(UUID.randomUUID().toString(), TBMCPlayer::class.java)
|
||||||
|
assert(ButtonPlugin.command2MC.handleCommand(Command2MCSender(user, Channel.globalChat, user), "/test hmm"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@CommandClass
|
||||||
|
object TestCommand : ICommand2MC() {
|
||||||
|
@Command2.Subcommand
|
||||||
|
fun def(sender: Command2MCSender, test: String) {
|
||||||
|
println(test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private var initialized = false
|
||||||
|
}
|
||||||
|
}
|
18
Chroma-Core/src/test/resources/commands.yml
Normal file
18
Chroma-Core/src/test/resources/commands.yml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
buttondevteam:
|
||||||
|
lib:
|
||||||
|
chat:
|
||||||
|
test:
|
||||||
|
Command2MCTest:
|
||||||
|
TestCommand:
|
||||||
|
def:
|
||||||
|
method: def()
|
||||||
|
params: ''
|
||||||
|
core:
|
||||||
|
ComponentCommand:
|
||||||
|
def:
|
||||||
|
method: def()
|
||||||
|
params: ''
|
||||||
|
ChromaCommand:
|
||||||
|
def:
|
||||||
|
method: def()
|
||||||
|
params: ''
|
7
pom.xml
7
pom.xml
|
@ -41,10 +41,11 @@
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
<version>4.13.1</version>
|
<version>5.9.3</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
||||||
|
|
Loading…
Reference in a new issue