Skip to content

Commit f407fb3

Browse files
authored
Validate literals do not contain whitespace (#662)
1 parent d33fa87 commit f407fb3

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

cloud-core/src/main/java/org/incendo/cloud/parser/standard/LiteralParser.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,17 @@
2323
//
2424
package org.incendo.cloud.parser.standard;
2525

26+
import java.util.ArrayList;
2627
import java.util.Arrays;
2728
import java.util.Collection;
2829
import java.util.Collections;
2930
import java.util.HashSet;
31+
import java.util.List;
3032
import java.util.Set;
3133
import java.util.TreeSet;
3234
import org.apiguardian.api.API;
3335
import org.checkerframework.checker.nullness.qual.NonNull;
36+
import org.checkerframework.checker.nullness.qual.Nullable;
3437
import org.incendo.cloud.context.CommandContext;
3538
import org.incendo.cloud.context.CommandInput;
3639
import org.incendo.cloud.parser.ArgumentParseResult;
@@ -62,6 +65,7 @@ public final class LiteralParser<C> implements ArgumentParser<C, String>, Blocki
6265
private final String name;
6366

6467
private LiteralParser(final @NonNull String name, final @NonNull String... aliases) {
68+
validateNames(name, aliases);
6569
this.name = name;
6670
this.allAcceptedAliases.add(this.name);
6771
this.allAcceptedAliases.addAll(Arrays.asList(aliases));
@@ -119,7 +123,35 @@ private LiteralParser(final @NonNull String name, final @NonNull String... alias
119123
* @param alias New alias
120124
*/
121125
public void insertAlias(final @NonNull String alias) {
126+
validateNames("valid", new String[]{alias});
122127
this.allAcceptedAliases.add(alias);
123128
this.alternativeAliases.add(alias);
124129
}
130+
131+
private static void validateNames(final String name, final @NonNull String[] aliases) {
132+
@Nullable List<String> errors = null;
133+
errors = validateName(name, false, errors);
134+
for (final String alias : aliases) {
135+
errors = validateName(alias, true, errors);
136+
}
137+
if (errors != null && !errors.isEmpty()) {
138+
throw new IllegalArgumentException(String.join("\n", errors));
139+
}
140+
}
141+
142+
@SuppressWarnings("checkstyle:FinalParameters")
143+
private static @Nullable List<String> validateName(
144+
final @NonNull String name,
145+
final boolean alias,
146+
@Nullable List<String> errors
147+
) {
148+
final int found = name.codePoints().filter(Character::isWhitespace).findFirst().orElse(Integer.MIN_VALUE);
149+
if (found != Integer.MIN_VALUE) {
150+
if (errors == null) {
151+
errors = new ArrayList<>();
152+
}
153+
errors.add(String.format("%s '%s' is invalid: contains whitespace", alias ? "Alias" : "Name", name));
154+
}
155+
return errors;
156+
}
125157
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// MIT License
3+
//
4+
// Copyright (c) 2024 Incendo
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in all
14+
// copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
// SOFTWARE.
23+
//
24+
package org.incendo.cloud.parser.standard;
25+
26+
import org.junit.jupiter.api.Test;
27+
28+
import static com.google.common.truth.Truth.assertThat;
29+
import static org.junit.jupiter.api.Assertions.assertThrows;
30+
31+
class LiteralParserTest {
32+
33+
@Test
34+
void testInvalidName() {
35+
final IllegalArgumentException thr = assertThrows(IllegalArgumentException.class, () -> {
36+
LiteralParser.literal("invalid name", "invalid\talias", "another\ninvalid\nalias");
37+
});
38+
assertThat(thr).hasMessageThat().isEqualTo(
39+
"Name 'invalid name' is invalid: contains whitespace\n" +
40+
"Alias 'invalid\talias' is invalid: contains whitespace\n" +
41+
"Alias 'another\n" +
42+
"invalid\n" +
43+
"alias' is invalid: contains whitespace"
44+
);
45+
}
46+
}

0 commit comments

Comments
 (0)