Consider arguments when literal is impermissible

Fixes https://github.com/Mojang/brigadier/issues/87
This commit is contained in:
Hugo Manrique 2021-04-03 21:53:22 +02:00
parent cf754c4ef6
commit 901d6bf0ca
No known key found for this signature in database
GPG key ID: A60730A4A4ACE782
2 changed files with 52 additions and 1 deletions

View file

@ -14,6 +14,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
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 abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
input.setCursor(cursor);
final LiteralCommandNode<S> 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<CommandNode<S>> nodes = new ArrayList<>(argumentsCount + 1);
nodes.add(literal); // literals have priority over arguments
nodes.addAll(arguments.values());
return nodes;
}
} else {
return arguments.values();
}

View file

@ -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 class CommandDispatcherTest {
verify(command, never()).run(any());
}
@SuppressWarnings("unchecked")
@Test
public void testPreferExecuteLiteralOverArguments() throws Exception {
final Command<Object> 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 {