From db1e4a4d49b50840b9cdc16e96dd9e894e54df57 Mon Sep 17 00:00:00 2001 From: valaphee <32491319+valaphee@users.noreply.github.com> Date: Thu, 15 Aug 2024 21:17:37 +0200 Subject: [PATCH 1/3] Relax string() type and add wordRelaxed() --- .../com/mojang/brigadier/StringReader.java | 14 ++++++- .../arguments/StringArgumentType.java | 42 ++++++++++++------- .../mojang/brigadier/StringReaderTest.java | 28 ++++++++----- .../arguments/StringArgumentTypeTest.java | 13 ++++-- 4 files changed, 68 insertions(+), 29 deletions(-) diff --git a/src/main/java/com/mojang/brigadier/StringReader.java b/src/main/java/com/mojang/brigadier/StringReader.java index c1465df63..a3d7c570f 100644 --- a/src/main/java/com/mojang/brigadier/StringReader.java +++ b/src/main/java/com/mojang/brigadier/StringReader.java @@ -174,6 +174,10 @@ public static boolean isAllowedInUnquotedString(final char c) { || c == '.' || c == '+'; } + public static boolean isAllowedInUnquotedStringRelaxed(final char c) { + return c != ' ' && c != '\\' && c != '"'; + } + public String readUnquotedString() { final int start = cursor; while (canRead() && isAllowedInUnquotedString(peek())) { @@ -182,6 +186,14 @@ public String readUnquotedString() { return string.substring(start, cursor); } + public String readUnquotedStringRelaxed() { + final int start = cursor; + while (canRead() && isAllowedInUnquotedStringRelaxed(peek())) { + skip(); + } + return string.substring(start, cursor); + } + public String readQuotedString() throws CommandSyntaxException { if (!canRead()) { return ""; @@ -228,7 +240,7 @@ public String readString() throws CommandSyntaxException { skip(); return readStringUntil(next); } - return readUnquotedString(); + return readUnquotedStringRelaxed(); } public boolean readBoolean() throws CommandSyntaxException { diff --git a/src/main/java/com/mojang/brigadier/arguments/StringArgumentType.java b/src/main/java/com/mojang/brigadier/arguments/StringArgumentType.java index 0e36f3401..dc304c633 100644 --- a/src/main/java/com/mojang/brigadier/arguments/StringArgumentType.java +++ b/src/main/java/com/mojang/brigadier/arguments/StringArgumentType.java @@ -21,6 +21,10 @@ public static StringArgumentType word() { return new StringArgumentType(StringType.SINGLE_WORD); } + public static StringArgumentType wordRelaxed() { + return new StringArgumentType(StringType.SINGLE_WORD_RELAXED); + } + public static StringArgumentType string() { return new StringArgumentType(StringType.QUOTABLE_PHRASE); } @@ -39,20 +43,23 @@ public StringType getType() { @Override public String parse(final StringReader reader) throws CommandSyntaxException { - if (type == StringType.GREEDY_PHRASE) { - final String text = reader.getRemaining(); - reader.setCursor(reader.getTotalLength()); - return text; - } else if (type == StringType.SINGLE_WORD) { - return reader.readUnquotedString(); - } else { - return reader.readString(); + switch (type) { + case SINGLE_WORD: + return reader.readUnquotedString(); + case QUOTABLE_PHRASE: + return reader.readString(); + case GREEDY_PHRASE: + final String text = reader.getRemaining(); + reader.setCursor(reader.getTotalLength()); + return text; + default: + return reader.readUnquotedStringRelaxed(); } } @Override public String toString() { - return "string()"; + return type.name; } @Override @@ -62,7 +69,7 @@ public Collection getExamples() { public static String escapeIfRequired(final String input) { for (final char c : input.toCharArray()) { - if (!StringReader.isAllowedInUnquotedString(c)) { + if (!StringReader.isAllowedInUnquotedStringRelaxed(c)) { return escape(input); } } @@ -85,16 +92,23 @@ private static String escape(final String input) { } public enum StringType { - SINGLE_WORD("word", "words_with_underscores"), - QUOTABLE_PHRASE("\"quoted phrase\"", "word", "\"\""), - GREEDY_PHRASE("word", "words with spaces", "\"and symbols\""),; + SINGLE_WORD("word()", "word", "words_with_underscores"), + QUOTABLE_PHRASE("string()", "\"quoted phrase\"", "word", "wörd!", "\"\""), + GREEDY_PHRASE("greedyString()", "word", "words with spaces", "\"and symbols\""), + SINGLE_WORD_RELAXED("wordRelaxed()", "word", "wörd!"); + private final String name; private final Collection examples; - StringType(final String... examples) { + StringType(final String name, final String... examples) { + this.name = name; this.examples = Arrays.asList(examples); } + public String getName() { + return name; + } + public Collection getExamples() { return examples; } diff --git a/src/test/java/com/mojang/brigadier/StringReaderTest.java b/src/test/java/com/mojang/brigadier/StringReaderTest.java index 23e2c14d4..6f46300ef 100644 --- a/src/test/java/com/mojang/brigadier/StringReaderTest.java +++ b/src/test/java/com/mojang/brigadier/StringReaderTest.java @@ -148,6 +148,14 @@ public void readUnquotedString_empty_withRemaining() throws Exception { assertThat(reader.getRemaining(), equalTo(" hello world")); } + @Test + public void readUnquotedStringRelaxed() throws Exception { + final StringReader reader = new StringReader("héllö world"); + assertThat(reader.readUnquotedStringRelaxed(), equalTo("héllö")); + assertThat(reader.getRead(), equalTo("héllö")); + assertThat(reader.getRemaining(), equalTo(" world")); + } + @Test public void readQuotedString() throws Exception { final StringReader reader = new StringReader("\"hello world\""); @@ -278,25 +286,25 @@ public void readQuotedString_invalidQuoteEscape() throws Exception { @Test public void readString_noQuotes() throws Exception { - final StringReader reader = new StringReader("hello world"); - assertThat(reader.readString(), equalTo("hello")); - assertThat(reader.getRead(), equalTo("hello")); - assertThat(reader.getRemaining(), equalTo(" world")); + final StringReader reader = new StringReader("héllo wörld"); + assertThat(reader.readString(), equalTo("héllo")); + assertThat(reader.getRead(), equalTo("héllo")); + assertThat(reader.getRemaining(), equalTo(" wörld")); } @Test public void readString_singleQuotes() throws Exception { - final StringReader reader = new StringReader("'hello world'"); - assertThat(reader.readString(), equalTo("hello world")); - assertThat(reader.getRead(), equalTo("'hello world'")); + final StringReader reader = new StringReader("'héllo wörld'"); + assertThat(reader.readString(), equalTo("héllo wörld")); + assertThat(reader.getRead(), equalTo("'héllo wörld'")); assertThat(reader.getRemaining(), equalTo("")); } @Test public void readString_doubleQuotes() throws Exception { - final StringReader reader = new StringReader("\"hello world\""); - assertThat(reader.readString(), equalTo("hello world")); - assertThat(reader.getRead(), equalTo("\"hello world\"")); + final StringReader reader = new StringReader("\"héllo wörld\""); + assertThat(reader.readString(), equalTo("héllo wörld")); + assertThat(reader.getRead(), equalTo("\"héllo wörld\"")); assertThat(reader.getRemaining(), equalTo("")); } diff --git a/src/test/java/com/mojang/brigadier/arguments/StringArgumentTypeTest.java b/src/test/java/com/mojang/brigadier/arguments/StringArgumentTypeTest.java index 68e52e168..f30c6bc33 100644 --- a/src/test/java/com/mojang/brigadier/arguments/StringArgumentTypeTest.java +++ b/src/test/java/com/mojang/brigadier/arguments/StringArgumentTypeTest.java @@ -10,10 +10,7 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import static com.mojang.brigadier.arguments.StringArgumentType.escapeIfRequired; -import static com.mojang.brigadier.arguments.StringArgumentType.greedyString; -import static com.mojang.brigadier.arguments.StringArgumentType.string; -import static com.mojang.brigadier.arguments.StringArgumentType.word; +import static com.mojang.brigadier.arguments.StringArgumentType.*; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasToString; import static org.hamcrest.Matchers.is; @@ -35,6 +32,14 @@ public void testParseWord() throws Exception { verify(reader).readUnquotedString(); } + @Test + public void testParseWordRelaxed() throws Exception { + final StringReader reader = mock(StringReader.class); + when(reader.readUnquotedStringRelaxed()).thenReturn("héllo"); + assertThat(wordRelaxed().parse(reader), equalTo("héllo")); + verify(reader).readUnquotedStringRelaxed(); + } + @Test public void testParseString() throws Exception { final StringReader reader = mock(StringReader.class); From 9336fe3bc5cc5e774247d14cb00d3da264ea3cfb Mon Sep 17 00:00:00 2001 From: valaphee <32491319+valaphee@users.noreply.github.com> Date: Thu, 15 Aug 2024 21:20:31 +0200 Subject: [PATCH 2/3] Disallow single quotes without quoting --- src/main/java/com/mojang/brigadier/StringReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/mojang/brigadier/StringReader.java b/src/main/java/com/mojang/brigadier/StringReader.java index a3d7c570f..9d4a2089c 100644 --- a/src/main/java/com/mojang/brigadier/StringReader.java +++ b/src/main/java/com/mojang/brigadier/StringReader.java @@ -175,7 +175,7 @@ public static boolean isAllowedInUnquotedString(final char c) { } public static boolean isAllowedInUnquotedStringRelaxed(final char c) { - return c != ' ' && c != '\\' && c != '"'; + return c != ' ' && c != '\\' && !isQuotedStringStart(c); } public String readUnquotedString() { From 099d9437566a8bdeb199f5073681f3844d535800 Mon Sep 17 00:00:00 2001 From: valaphee <32491319+valaphee@users.noreply.github.com> Date: Thu, 15 Aug 2024 21:21:41 +0200 Subject: [PATCH 3/3] Rename wordRelaxed to relaxedWord --- .../com/mojang/brigadier/arguments/StringArgumentType.java | 2 +- .../mojang/brigadier/arguments/StringArgumentTypeTest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/mojang/brigadier/arguments/StringArgumentType.java b/src/main/java/com/mojang/brigadier/arguments/StringArgumentType.java index dc304c633..0d728722f 100644 --- a/src/main/java/com/mojang/brigadier/arguments/StringArgumentType.java +++ b/src/main/java/com/mojang/brigadier/arguments/StringArgumentType.java @@ -21,7 +21,7 @@ public static StringArgumentType word() { return new StringArgumentType(StringType.SINGLE_WORD); } - public static StringArgumentType wordRelaxed() { + public static StringArgumentType relaxedWord() { return new StringArgumentType(StringType.SINGLE_WORD_RELAXED); } diff --git a/src/test/java/com/mojang/brigadier/arguments/StringArgumentTypeTest.java b/src/test/java/com/mojang/brigadier/arguments/StringArgumentTypeTest.java index f30c6bc33..2d83e25f4 100644 --- a/src/test/java/com/mojang/brigadier/arguments/StringArgumentTypeTest.java +++ b/src/test/java/com/mojang/brigadier/arguments/StringArgumentTypeTest.java @@ -33,10 +33,10 @@ public void testParseWord() throws Exception { } @Test - public void testParseWordRelaxed() throws Exception { + public void testParseRelaxedWord() throws Exception { final StringReader reader = mock(StringReader.class); when(reader.readUnquotedStringRelaxed()).thenReturn("héllo"); - assertThat(wordRelaxed().parse(reader), equalTo("héllo")); + assertThat(relaxedWord().parse(reader), equalTo("héllo")); verify(reader).readUnquotedStringRelaxed(); }