From 901d6bf0ca52446f55ce031e03fea92bb869b0d1 Mon Sep 17 00:00:00 2001 From: Hugo Manrique Date: Sat, 3 Apr 2021 21:53:22 +0200 Subject: [PATCH] Consider arguments when literal is impermissible Fixes https://github.com/Mojang/brigadier/issues/87 --- .../mojang/brigadier/tree/CommandNode.java | 11 ++++- .../brigadier/CommandDispatcherTest.java | 42 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/mojang/brigadier/tree/CommandNode.java b/src/main/java/com/mojang/brigadier/tree/CommandNode.java index 47f8e3db..3dd78097 100644 --- a/src/main/java/com/mojang/brigadier/tree/CommandNode.java +++ b/src/main/java/com/mojang/brigadier/tree/CommandNode.java @@ -14,6 +14,7 @@ import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -160,7 +161,15 @@ public Collection> getRelevantNodes(final StringReader input.setCursor(cursor); final LiteralCommandNode literal = literals.get(text); if (literal != null) { - return Collections.singleton(literal); + final int argumentsCount = arguments.size(); + if (argumentsCount == 0) { + return Collections.singletonList(literal); + } else { + final Collection> nodes = new ArrayList<>(argumentsCount + 1); + nodes.add(literal); // literals have priority over arguments + nodes.addAll(arguments.values()); + return nodes; + } } else { return arguments.values(); } diff --git a/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java b/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java index f2bab4a9..4b62d741 100644 --- a/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java +++ b/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java @@ -4,6 +4,7 @@ package com.mojang.brigadier; import com.google.common.collect.Lists; +import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContextBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -256,6 +257,47 @@ public void testExecuteAmbiguiousParentSubcommandViaRedirect() throws Exception verify(command, never()).run(any()); } + @SuppressWarnings("unchecked") + @Test + public void testPreferExecuteLiteralOverArguments() throws Exception { + final Command literalCommand = mock(Command.class); + when(literalCommand.run(any())).thenReturn(100); + + subject.register( + literal("test") + .then( + argument("incorrect", StringArgumentType.word()) + .executes(command) + ) + .then( + literal("hello") + .executes(literalCommand) + ) + ); + + assertThat(subject.execute("test hello", source), is(100)); + verify(literalCommand).run(any(CommandContext.class)); + verify(command, never()).run(any()); + } + + @SuppressWarnings("unchecked") + @Test + public void testExecuteAmbiguousArgumentIfImpermissibleLiteral() throws Exception { + subject.register(literal("foo") + .then( + literal("bar") + .requires(source -> false) + ) + .then( + argument("argument", StringArgumentType.word()) + .executes(command) + ) + ); + + assertThat(subject.execute("foo bar", source), is(42)); + verify(command).run(any(CommandContext.class)); + } + @SuppressWarnings("unchecked") @Test public void testExecuteRedirectedMultipleTimes() throws Exception {