diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b9e3385..d71fe7b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixes + - Fixes chained optionals not allowing the command to be executed when more than one optional is omitted ## [1.0.1] - 2020-10-14 diff --git a/cloud-core/src/main/java/cloud/commandframework/CommandTree.java b/cloud-core/src/main/java/cloud/commandframework/CommandTree.java index 21b6f161..7e8bb5fb 100644 --- a/cloud-core/src/main/java/cloud/commandframework/CommandTree.java +++ b/cloud-core/src/main/java/cloud/commandframework/CommandTree.java @@ -287,7 +287,20 @@ public final class CommandTree { if (child.getValue().hasDefaultValue()) { commandQueue.add(child.getValue().getDefaultValue()); } else if (!child.getValue().isRequired()) { - return Pair.of(this.cast(child.getValue().getOwningCommand()), null); + if (child.getValue().getOwningCommand() == null) { + /* + * If there are multiple children with different owning commands then it's ambiguous and + * not allowed, therefore we're able to pick any child command, as long as we can find it + */ + Node> node = child; + while (!node.isLeaf()) { + node = node.getChildren().get(0); + if (node.getValue() != null && node.getValue().getOwningCommand() != null) { + child.getValue().setOwningCommand(node.getValue().getOwningCommand()); + } + } + } + return Pair.of(child.getValue().getOwningCommand(), null); } else if (child.isLeaf()) { if (root.getValue() != null && root.getValue().getOwningCommand() != null) { final Command command = root.getValue().getOwningCommand(); diff --git a/cloud-core/src/test/java/cloud/commandframework/CommandTreeTest.java b/cloud-core/src/test/java/cloud/commandframework/CommandTreeTest.java index 6f3adc02..1f6acfa2 100644 --- a/cloud-core/src/test/java/cloud/commandframework/CommandTreeTest.java +++ b/cloud-core/src/test/java/cloud/commandframework/CommandTreeTest.java @@ -143,6 +143,13 @@ class CommandTreeTest { .addPreprocessor(RegexPreprocessor.of("[A-Za-z]{3,5}")) ) ); + + /* Build command for testing multiple optionals */ + manager.command( + manager.commandBuilder("optionals") + .argument(StringArgument.optional("opt1")) + .argument(StringArgument.optional("opt2")) + ); } @Test @@ -301,6 +308,11 @@ class CommandTreeTest { ); } + @Test + void testOptionals() { + manager.executeCommand(new TestCommandSender(), "optionals").join(); + } + public static final class SpecificCommandSender extends TestCommandSender {