Fix for issue 109

This commit is contained in:
Richard DiPippo 2023-02-21 11:43:26 -05:00
parent a6c4baa1b6
commit ac27904cd4
5 changed files with 77 additions and 5 deletions

View file

@ -9,6 +9,8 @@ import com.mojang.brigadier.tree.LiteralCommandNode;
public class LiteralArgumentBuilder<S> extends ArgumentBuilder<S, LiteralArgumentBuilder<S>> {
private final String literal;
private boolean isCaseInsensitive = false;
protected LiteralArgumentBuilder(final String literal) {
this.literal = literal;
}
@ -26,9 +28,16 @@ public class LiteralArgumentBuilder<S> extends ArgumentBuilder<S, LiteralArgumen
return literal;
}
public boolean isCaseInsensitive() { return isCaseInsensitive; }
public LiteralArgumentBuilder<S> caseInsensitive(boolean isCaseInsensitive) {
this.isCaseInsensitive = isCaseInsensitive;
return getThis();
}
@Override
public LiteralCommandNode<S> build() {
final LiteralCommandNode<S> result = new LiteralCommandNode<>(getLiteral(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork());
final LiteralCommandNode<S> result = new LiteralCommandNode<>(getLiteral(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), isCaseInsensitive());
for (final CommandNode<S> argument : getArguments()) {
result.addChild(argument);

View file

@ -8,6 +8,7 @@ import com.mojang.brigadier.Command;
import com.mojang.brigadier.RedirectModifier;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@ -82,7 +83,13 @@ public abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
} else {
children.put(node.getName(), node);
if (node instanceof LiteralCommandNode) {
literals.put(node.getName(), (LiteralCommandNode<S>) node);
LiteralCommandNode literalNode = (LiteralCommandNode)node;
if (literalNode.isCaseInsensitive()) {
literals.put(node.getName().toLowerCase(), (LiteralCommandNode<S>) node);
} else {
literals.put(node.getName(), (LiteralCommandNode<S>) node);
}
} else if (node instanceof ArgumentCommandNode) {
arguments.put(node.getName(), (ArgumentCommandNode<S, ?>) node);
}
@ -158,7 +165,13 @@ public abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
}
final String text = input.getString().substring(cursor, input.getCursor());
input.setCursor(cursor);
final LiteralCommandNode<S> literal = literals.get(text);
boolean caseInsensitive = false;
if (this instanceof LiteralCommandNode) {
caseInsensitive = ((LiteralCommandNode)this).isCaseInsensitive();
}
final LiteralCommandNode<S> literal = literals.get(caseInsensitive ? text.toLowerCase() : text);
if (literal != null) {
return Collections.singleton(literal);
} else {

View file

@ -23,11 +23,14 @@ import java.util.function.Predicate;
public class LiteralCommandNode<S> extends CommandNode<S> {
private final String literal;
private final String literalLowerCase;
private boolean isCaseInsensitive = false;
public LiteralCommandNode(final String literal, final Command<S> command, final Predicate<S> requirement, final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks) {
public LiteralCommandNode(final String literal, final Command<S> command, final Predicate<S> requirement, final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks,
final boolean isCaseInsensitive) {
super(command, requirement, redirect, modifier, forks);
this.literal = literal;
this.literalLowerCase = literal.toLowerCase(Locale.ROOT);
this.isCaseInsensitive = isCaseInsensitive;
}
public String getLiteral() {
@ -39,6 +42,12 @@ public class LiteralCommandNode<S> extends CommandNode<S> {
return literal;
}
public boolean isCaseInsensitive() { return isCaseInsensitive; }
public void caseInsensitive(boolean isCaseInsensitive) {
this.isCaseInsensitive = isCaseInsensitive;
}
@Override
public void parse(final StringReader reader, final CommandContextBuilder<S> contextBuilder) throws CommandSyntaxException {
final int start = reader.getCursor();
@ -55,7 +64,17 @@ public class LiteralCommandNode<S> extends CommandNode<S> {
final int start = reader.getCursor();
if (reader.canRead(literal.length())) {
final int end = start + literal.length();
if (reader.getString().substring(start, end).equals(literal)) {
boolean foundMatch = false;
String subString = reader.getString().substring(start, end);
if (isCaseInsensitive) {
foundMatch = subString.equalsIgnoreCase(literal);
} else {
foundMatch = subString.equals(literal);
}
if (foundMatch) {
reader.setCursor(end);
if (!reader.canRead() || reader.peek() == ' ') {
return end;

View file

@ -4,6 +4,8 @@
package com.mojang.brigadier;
import com.google.common.collect.Lists;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
@ -61,6 +63,15 @@ public class CommandDispatcherTest {
verify(command).run(any(CommandContext.class));
}
@SuppressWarnings("unchecked")
@Test
public void testCreateAndExecuteCaseInsensitiveCommand() throws Exception {
subject.register(literal("Foo").then(argument("bar", integer()).executes(command)).caseInsensitive(true));
assertThat(subject.execute("foo 123", source), is(42));
verify(command).run(any(CommandContext.class));
}
@SuppressWarnings("unchecked")
@Test
public void testCreateAndExecuteOffsetCommand() throws Exception {
@ -70,6 +81,14 @@ public class CommandDispatcherTest {
verify(command).run(any(CommandContext.class));
}
@Test
public void testCreateAndExecuteCaseInsensitiveOffsetCommand() throws Exception {
subject.register(literal("Foo").executes(command).caseInsensitive(true));
assertThat(subject.execute(inputWithOffset("/foo", 1), source), is(42));
verify(command).run(any(CommandContext.class));
}
@SuppressWarnings("unchecked")
@Test
public void testCreateAndMergeCommands() throws Exception {

View file

@ -47,6 +47,18 @@ public class LiteralCommandNodeTest extends AbstractCommandNodeTest {
assertThat(reader.getRemaining(), equalTo(" bar"));
}
@Test
public void testCaseInsensitiveParse() throws Exception {
try {
node.caseInsensitive(true);
final StringReader reader = new StringReader("FoO bar");
node.parse(reader, contextBuilder);
assertThat(reader.getRemaining(), equalTo(" bar"));
} finally {
node.caseInsensitive(false);
}
}
@Test
public void testParseExact() throws Exception {
final StringReader reader = new StringReader("foo");