From 3f60c32923ff8c6dea180d2244f0e1a1641dc5cd Mon Sep 17 00:00:00 2001 From: AlmightySatan <43804777+Almighty-Satan@users.noreply.github.com> Date: Sat, 29 Nov 2025 14:32:20 +0100 Subject: [PATCH] Improve message of AmbiguousNodeException --- .../java/org/incendo/cloud/CommandTree.java | 6 +++-- .../exception/AmbiguousNodeException.java | 25 ++++++++++++++++--- .../org/incendo/cloud/CommandTreeTest.java | 8 ++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/cloud-core/src/main/java/org/incendo/cloud/CommandTree.java b/cloud-core/src/main/java/org/incendo/cloud/CommandTree.java index c18f80845..9de0cef65 100644 --- a/cloud-core/src/main/java/org/incendo/cloud/CommandTree.java +++ b/cloud-core/src/main/java/org/incendo/cloud/CommandTree.java @@ -1170,7 +1170,8 @@ private void checkAmbiguity(final @NonNull CommandNode node) throws Ambiguous node.children() .stream() .filter(n -> n.component() != null) - .collect(Collectors.toList()) + .collect(Collectors.toList()), + null ); } @@ -1194,7 +1195,8 @@ private void checkAmbiguity(final @NonNull CommandNode node) throws Ambiguous node.children() .stream() .filter(n -> n.component() != null) - .collect(Collectors.toList()) + .collect(Collectors.toList()), + nameOrAlias ); } } diff --git a/cloud-core/src/main/java/org/incendo/cloud/exception/AmbiguousNodeException.java b/cloud-core/src/main/java/org/incendo/cloud/exception/AmbiguousNodeException.java index 26a546927..161337e10 100644 --- a/cloud-core/src/main/java/org/incendo/cloud/exception/AmbiguousNodeException.java +++ b/cloud-core/src/main/java/org/incendo/cloud/exception/AmbiguousNodeException.java @@ -45,23 +45,27 @@ public final class AmbiguousNodeException extends IllegalStateException { private final CommandNode parentNode; private final CommandNode ambiguousNode; private final List> children; + private final String ambiguousName; /** * Construct a new ambiguous node exception * * @param parentNode Parent node * @param ambiguousNode Node that caused exception + * @param ambiguousName Ambiguous name or alias * @param children All children of the parent */ @API(status = API.Status.INTERNAL, consumers = "org.incendo.cloud.*") public AmbiguousNodeException( final @Nullable CommandNode parentNode, final @NonNull CommandNode ambiguousNode, - final @NonNull List<@NonNull CommandNode> children + final @NonNull List<@NonNull CommandNode> children, + final @Nullable String ambiguousName ) { this.parentNode = parentNode; this.ambiguousNode = ambiguousNode; this.children = children; + this.ambiguousName = ambiguousName; } /** @@ -91,13 +95,28 @@ public AmbiguousNodeException( return Collections.unmodifiableList(this.children); } + /** + * Returns the ambiguous name or alias of the node. + * Might be null if the reason for this exception is not an ambiguous name or alias (e.g. multiple child nodes with a + * variable argument). + * + * @return the ambiguous name or alias of the node + */ + public @Nullable String getAmbiguousName() { + return this.ambiguousName; + } + @Override public String getMessage() { final StringBuilder stringBuilder = new StringBuilder("Ambiguous Node: ") .append(this.ambiguousNode.component().name()) .append(" cannot be added as a child to ") - .append(this.parentNode == null ? "" : this.parentNode.component().name()) - .append(" (All children: "); + .append(this.parentNode == null ? "" : this.parentNode.component().name()); + if (this.ambiguousName != null) { + stringBuilder.append(" because of ambiguous name ") + .append(this.ambiguousName); + } + stringBuilder.append(" (All children: "); final Iterator> childIterator = this.children.iterator(); while (childIterator.hasNext()) { stringBuilder.append(childIterator.next().component().name()); diff --git a/cloud-core/src/test/java/org/incendo/cloud/CommandTreeTest.java b/cloud-core/src/test/java/org/incendo/cloud/CommandTreeTest.java index 6cb5e7070..be5e40dd1 100644 --- a/cloud-core/src/test/java/org/incendo/cloud/CommandTreeTest.java +++ b/cloud-core/src/test/java/org/incendo/cloud/CommandTreeTest.java @@ -446,6 +446,14 @@ void testAmbiguousNodes() { this.commandManager.command(this.commandManager.commandBuilder("ambiguous") .literal("literal"))); this.setup(); + + // Two literals with the same alias can not co-exist, causes AmbiguousNodeException + this.commandManager.command(this.commandManager.commandBuilder("ambiguous") + .literal("literal", "alias")); + assertThrows(AmbiguousNodeException.class, () -> + this.commandManager.command(this.commandManager.commandBuilder("ambiguous") + .literal("literal2", "alias"))); + this.setup(); } @Test