Make sure arguments are preserved after redirects

https://github.com/Mojang/brigadier/pull/142
This commit is contained in:
2024-08-13 03:33:01 +08:00
parent 8d48b13cdf
commit 6ce25e6370
5 changed files with 56 additions and 1 deletions
@@ -330,6 +330,7 @@ public class CommandDispatcher<S> {
} while (reader.canRead() && reader.peek() == ARGUMENT_SEPARATOR_CHAR);
if (child.getRedirect() != null) {
final CommandContextBuilder<S> childContext = new CommandContextBuilder<>(this, source, child.getRedirect(), reader.getCursor());
childContext.withArguments(context.getArguments());
final ParseResults<S> parse = parseNodes(child.getRedirect(), reader, childContext);
context.withChild(parse.getContext());
final ParseResults<S> redirect = new ParseResults<>(context, parse.getReader(), parse.getExceptions());
@@ -50,6 +50,11 @@ public class CommandContextBuilder<S> {
return this;
}
public CommandContextBuilder<S> withArguments(Map<String, ParsedArgument<S, ?>> arguments) {
this.arguments.putAll(arguments);
return this;
}
public Map<String, ParsedArgument<S, ?>> getArguments() {
return arguments;
}
@@ -12,6 +12,7 @@ import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.Suggestion;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.tree.ArgumentCommandNode;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
@@ -415,6 +416,22 @@ public class CommandDispatcherTest {
assertThat(result, is(0)); // No commands executed, so result is 0
}
@Test
public void testRedirectPreservesPreviousArguments() throws CommandSyntaxException {
final LiteralCommandNode<Object> ending = literal("ending")
.executes(context -> context.getArgument("number", int.class)).build();
final ArgumentCommandNode<Object, Integer> lowNumber = argument("number", integer(1, 10))
.then(ending).build();
final ArgumentCommandNode<Object, Integer> highNumber = argument("number", integer(11, 20))
.redirect(lowNumber).build();
subject.register(literal("base")
.then(literal("low").then(lowNumber))
.then(literal("high").then(highNumber)));
assertThat(subject.execute("base low 5 ending", source), is(5));
assertThat(subject.execute("base high 15 ending", source), is(15));
}
@Test
public void testExecuteOrphanedSubcommand() {
subject.register(literal("foo").then(
@@ -253,6 +253,26 @@ public class CommandSuggestionsTest {
assertThat(result.getList(), equalTo(Lists.newArrayList(new Suggestion(StringRange.at(33), "loop"))));
}
@Test
public void getCompletionSuggestions_redirectPreservesArguments() throws Exception {
subject.register(literal("command")
.then(
argument("first", integer())
.then(
argument("second", integer())
.suggests((context, builder) -> {
builder.suggest(String.valueOf(context.getLastChild().getArgument("first", int.class) + 1));
return builder.buildFuture();
})
)
));
subject.register(literal("redirect").redirect(subject.getRoot()));
testSuggestions("command 1 ", 10, StringRange.at(10), "2");
testSuggestions("redirect command 1 ", 19, StringRange.at(19), "2");
testSuggestions("redirect redirect command 1 ", 28, StringRange.at(28), "2");
}
@Test
public void getCompletionSuggestions_execute_simulation() throws Exception {
final LiteralCommandNode<Object> execute = subject.register(literal("execute"));
@@ -7,13 +7,15 @@ import com.google.common.testing.EqualsTester;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
@@ -51,6 +53,16 @@ public class CommandContextTest {
assertThat(context.getArgument("foo", int.class), is(123));
}
@Test
public void testGetArguments() throws Exception {
Map<String, ParsedArgument<Object, ?>> arguments = new HashMap<>();
arguments.put("foo", new ParsedArgument<>(0, 1, 123));
arguments.put("bar", new ParsedArgument<>(0, 1, "123"));
final CommandContext<Object> context = builder.withArguments(arguments).build("123");
assertThat(context.getArgument("foo", int.class), is(123));
assertThat(context.getArgument("bar", String.class), is("123"));
}
@Test
public void testSource() throws Exception {
assertThat(builder.build("").getSource(), is(source));