diff --git a/cloud-annotations/src/test/java/cloud/commandframework/annotations/issue/Issue262.java b/cloud-annotations/src/test/java/cloud/commandframework/annotations/issue/Issue262.java
new file mode 100644
index 00000000..db96560a
--- /dev/null
+++ b/cloud-annotations/src/test/java/cloud/commandframework/annotations/issue/Issue262.java
@@ -0,0 +1,162 @@
+//
+// MIT License
+//
+// Copyright (c) 2021 Alexander Söderberg & Contributors
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+package cloud.commandframework.annotations.issue;
+
+import cloud.commandframework.CommandHelpHandler;
+import cloud.commandframework.CommandManager;
+import cloud.commandframework.annotations.AnnotationParser;
+import cloud.commandframework.annotations.Argument;
+import cloud.commandframework.annotations.CommandMethod;
+import cloud.commandframework.annotations.TestCommandManager;
+import cloud.commandframework.annotations.TestCommandSender;
+import cloud.commandframework.meta.SimpleCommandMeta;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static com.google.common.truth.Truth.assertThat;
+
+/**
+ * Test for https://github.com/Incendo/cloud/issues/262.
+ *
+ * It is in the annotations module, rather than the core module, in order
+ * to rule out any issues with annotation parsing.
+ */
+@ExtendWith(MockitoExtension.class)
+class Issue262 {
+
+ private CommandHelpHandler commandHelpHandler;
+ private CommandManager manager;
+ private AnnotationParser annotationParser;
+
+ @BeforeEach
+ void setup() {
+ this.manager = new TestCommandManager();
+ this.commandHelpHandler = this.manager.getCommandHelpHandler();
+ this.annotationParser = new AnnotationParser<>(
+ this.manager,
+ TestCommandSender.class,
+ (parameters) -> SimpleCommandMeta.empty()
+ );
+ }
+
+ @Test
+ void queryForCommandAliasesWorks() {
+ // Arrange
+ this.annotationParser.parse(this);
+
+ // Act
+ final CommandHelpHandler.HelpTopic result = this.commandHelpHandler.queryHelp("cc sub2");
+
+ // Assert
+ assertThat(result).isInstanceOf(CommandHelpHandler.VerboseHelpTopic.class);
+
+ final CommandHelpHandler.VerboseHelpTopic topic =
+ (CommandHelpHandler.VerboseHelpTopic) result;
+ assertThat(topic.getCommand().toString()).isEqualTo("cloudcommand sub2 argument");
+ }
+
+ @Test
+ void queryForCommandChildAliasesWorks() {
+ // Arrange
+ this.annotationParser.parse(this);
+
+ // Act
+ final CommandHelpHandler.HelpTopic result = this.commandHelpHandler.queryHelp("cc s");
+
+ // Assert
+ assertThat(result).isInstanceOf(CommandHelpHandler.VerboseHelpTopic.class);
+
+ final CommandHelpHandler.VerboseHelpTopic topic =
+ (CommandHelpHandler.VerboseHelpTopic) result;
+ assertThat(topic.getCommand().toString()).isEqualTo("cloudcommand sub2 argument");
+ }
+
+ @Test
+ void queryForRootCommandWorks() {
+ // Arrange
+ this.annotationParser.parse(this);
+
+ // Act
+ final CommandHelpHandler.HelpTopic result = this.commandHelpHandler.queryHelp(
+ "cloudcommand sub2"
+ );
+
+ // Assert
+ assertThat(result).isInstanceOf(CommandHelpHandler.VerboseHelpTopic.class);
+
+ final CommandHelpHandler.VerboseHelpTopic topic =
+ (CommandHelpHandler.VerboseHelpTopic) result;
+ assertThat(topic.getCommand().toString()).isEqualTo("cloudcommand sub2 argument");
+ }
+
+ @Test
+ void queryForRootCommandWorks2() {
+ // Arrange
+ this.annotationParser.parse(this);
+
+ // Act
+ final CommandHelpHandler.HelpTopic result = this.commandHelpHandler.queryHelp(
+ "cloudcommand sub1"
+ );
+
+ // Assert
+ assertThat(result).isInstanceOf(CommandHelpHandler.VerboseHelpTopic.class);
+
+ final CommandHelpHandler.VerboseHelpTopic topic =
+ (CommandHelpHandler.VerboseHelpTopic) result;
+ assertThat(topic.getCommand().toString()).isEqualTo("cloudcommand sub1 argument");
+ }
+
+ @Test
+ void queryForOnlyRootCommandWorks() {
+ // Arrange
+ this.annotationParser.parse(this);
+
+ // Act
+ final CommandHelpHandler.HelpTopic result = this.commandHelpHandler.queryHelp(
+ "cc"
+ );
+
+ // Assert
+ assertThat(result).isInstanceOf(CommandHelpHandler.MultiHelpTopic.class);
+
+ final CommandHelpHandler.MultiHelpTopic topic =
+ (CommandHelpHandler.MultiHelpTopic) result;
+ assertThat(topic.getChildSuggestions()).containsExactly(
+ "cloudcommand sub1 [argument]",
+ "cloudcommand sub2 [argument]"
+ );
+ assertThat(topic.getLongestPath()).isEqualTo("cloudcommand");
+ }
+
+ @CommandMethod("cloudcommand|cc sub1 [argument]")
+ public void commandSource(@Argument("argument") final String argument) {
+ }
+
+ @CommandMethod("cloudcommand sub2|s [argument]")
+ public void commandToken(@Argument("argument") final String argument) {
+ }
+}
diff --git a/cloud-core/src/main/java/cloud/commandframework/CommandHelpHandler.java b/cloud-core/src/main/java/cloud/commandframework/CommandHelpHandler.java
index d9ecbfa7..2a405799 100644
--- a/cloud-core/src/main/java/cloud/commandframework/CommandHelpHandler.java
+++ b/cloud-core/src/main/java/cloud/commandframework/CommandHelpHandler.java
@@ -190,8 +190,7 @@ public final class CommandHelpHandler {
/* Traverse command to find the most specific help topic */
final CommandTree.Node> node = this.commandManager.getCommandTree()
- .getNamedNode(availableCommandLabels.iterator()
- .next());
+ .getNamedNode(availableCommandLabels.iterator().next());
final List> traversedNodes = new LinkedList<>();
CommandTree.Node> head = node;
@@ -349,6 +348,34 @@ public final class CommandHelpHandler {
return this.description;
}
+ @Override
+ public String toString() {
+ return "VerboseHelpEntry{"
+ + "command=" + this.command
+ + ", syntaxString='" + this.syntaxString + '\''
+ + ", description='" + this.description + '\''
+ + '}';
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || this.getClass() != o.getClass()) {
+ return false;
+ }
+ final VerboseHelpEntry> that = (VerboseHelpEntry>) o;
+ return this.command.equals(that.command)
+ && this.syntaxString.equals(that.syntaxString)
+ && this.description.equals(that.description);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.command, this.syntaxString, this.description);
+ }
+
}
/**
@@ -382,6 +409,30 @@ public final class CommandHelpHandler {
return this.getEntries().isEmpty();
}
+ @Override
+ public String toString() {
+ return "IndexHelpTopic{"
+ + "entries=" + this.entries
+ + '}';
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || this.getClass() != o.getClass()) {
+ return false;
+ }
+ final IndexHelpTopic> that = (IndexHelpTopic>) o;
+ return this.entries.equals(that.entries);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.entries);
+ }
+
}
@@ -419,6 +470,31 @@ public final class CommandHelpHandler {
return this.description;
}
+ @Override
+ public String toString() {
+ return "VerboseHelpTopic{"
+ + "command=" + this.command
+ + ", description='" +this.description + '\''
+ + '}';
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || this.getClass() != o.getClass()) {
+ return false;
+ }
+ final VerboseHelpTopic> that = (VerboseHelpTopic>) o;
+ return this.command.equals(that.command) && this.description.equals(that.description);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.command, this.description);
+ }
+
}
@@ -458,6 +534,31 @@ public final class CommandHelpHandler {
return this.childSuggestions;
}
+ @Override
+ public String toString() {
+ return "MultiHelpTopic{"
+ + "longestPath='" + this.longestPath + '\''
+ + ", childSuggestions=" + this.childSuggestions
+ + '}';
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || this.getClass() != o.getClass()) {
+ return false;
+ }
+ final MultiHelpTopic> that = (MultiHelpTopic>) o;
+ return this.longestPath.equals(that.longestPath) && this.childSuggestions.equals(that.childSuggestions);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(this.longestPath, this.childSuggestions);
+ }
+
}
}