Skip to content

Commit 1ff4f27

Browse files
authored
Merge pull request #152 from SkytAsul/v4
fix: sibling detection false positive when prefix
2 parents 6f3d5c5 + 2235bd2 commit 1ff4f27

File tree

4 files changed

+118
-12
lines changed

4 files changed

+118
-12
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ plugins {
1616
}
1717

1818
group = "io.github.revxrsal"
19-
version = "4.0.0-rc.14"
19+
version = "4.0.0-rc.15"
2020

2121
java {
2222
toolchain {

common/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ plugins {
33
}
44

55
dependencies {
6-
testImplementation(platform("org.junit:junit-bom:5.10.0"))
7-
testImplementation("org.junit.jupiter:junit-jupiter")
6+
testImplementation("org.junit.jupiter:junit-jupiter:5.14.2")
7+
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
88
compileOnly(kotlin("stdlib-jdk8"))
99
}
1010

common/src/main/java/revxrsal/commands/node/parser/Execution.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ final class Execution<A extends CommandActor> implements ExecutableCommand<A> {
5757
private final boolean isSecret;
5858
private final String description, usage;
5959
private final OptionalInt priority;
60-
private final String siblingPath;
60+
private final String[] siblingPath;
6161
private final String path;
6262
private final int flagCount;
6363
private final boolean lowPriority;
@@ -114,8 +114,8 @@ private String computePath() {
114114
return joiner.toString();
115115
}
116116

117-
private @NotNull String computeSiblingPath() {
118-
StringJoiner joiner = new StringJoiner(" ");
117+
private @NotNull String[] computeSiblingPath() {
118+
List<String> path = new ArrayList<>();
119119
int index = 0;
120120
for (int i = nodes.size() - 1; i >= 0; i--) {
121121
CommandNode<A> n = nodes.get(i);
@@ -124,11 +124,20 @@ private String computePath() {
124124
break;
125125
}
126126
}
127-
for (int i = 0; i < index; i++) {
128-
CommandNode<A> n = nodes.get(i);
129-
joiner.add(n.representation());
127+
if (index == 0) {
128+
// This is a top-level command: the sibling path should be the
129+
// actual command label.
130+
CommandNode<A> n = nodes.get(0);
131+
if (!n.isLiteral())
132+
throw new IllegalArgumentException("The command does not start with a literal.");
133+
path.add(n.representation());
134+
} else {
135+
for (int i = 0; i < index; i++) {
136+
CommandNode<A> n = nodes.get(i);
137+
path.add(n.representation());
138+
}
130139
}
131-
return joiner.toString();
140+
return path.toArray(new String[0]);
132141
}
133142

134143
@Override
@@ -243,8 +252,11 @@ && isSiblingOf(command)
243252
}
244253

245254
@Override public boolean isSiblingOf(@NotNull ExecutableCommand<A> command) {
246-
String otherPath = ((Execution<A>) command).siblingPath;
247-
return command != this && otherPath.startsWith(siblingPath) || siblingPath.startsWith(otherPath);
255+
if (command == this)
256+
return false;
257+
258+
String[] otherPath = ((Execution<A>) command).siblingPath;
259+
return Arrays.equals(siblingPath, otherPath);
248260
}
249261

250262
@Override public boolean isChildOf(@NotNull ExecutableCommand<A> command) {
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package revxrsal.commands.command;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import org.junit.jupiter.api.BeforeEach;
5+
import org.junit.jupiter.api.Test;
6+
import revxrsal.commands.Lamp;
7+
import revxrsal.commands.annotation.Command;
8+
import revxrsal.commands.annotation.CommandPlaceholder;
9+
import revxrsal.commands.annotation.Subcommand;
10+
import revxrsal.commands.help.Help;
11+
import java.util.Arrays;
12+
import java.util.HashSet;
13+
import java.util.stream.Collectors;
14+
15+
class ExecutableCommandHelpTest {
16+
17+
private Lamp<CommandActor> lamp;
18+
19+
@BeforeEach
20+
void setUp() {
21+
lamp = Lamp.builder().build();
22+
}
23+
24+
@Test
25+
void testSiblingCommands() {
26+
lamp.register(new CommandA(), new CommandB());
27+
ExecutableCommand<CommandActor> commandA = getCommand("a");
28+
ExecutableCommand<CommandActor> commandAA = getCommand("a a");
29+
ExecutableCommand<CommandActor> commandB = getCommand("b");
30+
31+
assertPathsEquals(commandAA.siblingCommands(), "a b", "a");
32+
assertPathsEquals(commandA.siblingCommands(), "a a", "a b");
33+
assertPathsEquals(commandB.siblingCommands());
34+
}
35+
36+
@Test
37+
void testChildrenCommands() {
38+
lamp.register(new CommandA(), new CommandB());
39+
ExecutableCommand<CommandActor> commandA = getCommand("a");
40+
ExecutableCommand<CommandActor> commandAA = getCommand("a a");
41+
ExecutableCommand<CommandActor> commandB = getCommand("b");
42+
43+
assertPathsEquals(commandAA.childrenCommands());
44+
assertPathsEquals(commandA.childrenCommands(), "a a", "a b");
45+
assertPathsEquals(commandB.childrenCommands());
46+
}
47+
48+
@Test
49+
void testRelatedCommands() {
50+
lamp.register(new CommandA(), new CommandB());
51+
ExecutableCommand<CommandActor> commandA = getCommand("a");
52+
ExecutableCommand<CommandActor> commandAA = getCommand("a a");
53+
ExecutableCommand<CommandActor> commandB = getCommand("b");
54+
55+
assertPathsEquals(commandAA.relatedCommands(), "a b", "a");
56+
assertPathsEquals(commandA.relatedCommands(), "a a", "a b");
57+
assertPathsEquals(commandB.relatedCommands());
58+
}
59+
60+
private ExecutableCommand<CommandActor> getCommand(String path) {
61+
return lamp.registry().commands().stream().filter(cmd -> cmd.path().equals(path))
62+
.findFirst().get();
63+
}
64+
65+
private static void assertPathsEquals(Help.CommandList<CommandActor> commands,
66+
String... paths) {
67+
// we use sets here because we don't care about ordering
68+
assertEquals(new HashSet<>(Arrays.asList(paths)),
69+
commands.all().stream().map(cmd -> cmd.path()).collect(Collectors.toSet()));
70+
}
71+
72+
@Command("a")
73+
class CommandA {
74+
75+
@CommandPlaceholder
76+
public void placeholder() {}
77+
78+
@Subcommand("a")
79+
public void a() {}
80+
81+
@Subcommand("b")
82+
public void b() {}
83+
84+
}
85+
86+
@Command("b")
87+
class CommandB {
88+
89+
@CommandPlaceholder
90+
public void b() {}
91+
92+
}
93+
94+
}

0 commit comments

Comments
 (0)