Made suggestions async
This commit is contained in:
parent
b48dbe7916
commit
4f7c6d4e32
13 changed files with 66 additions and 67 deletions
|
@ -23,6 +23,12 @@ import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.FutureTask;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -285,11 +291,8 @@ public class CommandDispatcher<S> {
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandSuggestions getCompletionSuggestions(final ParseResults<S> parse) {
|
public CompletableFuture<CommandSuggestions> getCompletionSuggestions(final ParseResults<S> parse) {
|
||||||
final CommandContextBuilder<S> context = parse.getContext();
|
final CommandContextBuilder<S> context = parse.getContext();
|
||||||
|
|
||||||
final Set<String> suggestions = new LinkedHashSet<>();
|
|
||||||
|
|
||||||
final CommandNode<S> parent;
|
final CommandNode<S> parent;
|
||||||
final int start;
|
final int start;
|
||||||
|
|
||||||
|
@ -309,13 +312,24 @@ public class CommandDispatcher<S> {
|
||||||
start = 0;
|
start = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") final CompletableFuture<Collection<String>>[] futures = new CompletableFuture[parent.getChildren().size()];
|
||||||
|
int i = 0;
|
||||||
for (final CommandNode<S> node : parent.getChildren()) {
|
for (final CommandNode<S> node : parent.getChildren()) {
|
||||||
node.listSuggestions(parse.getReader().getString().substring(start), suggestions, context);
|
futures[i++] = node.listSuggestions(parse.getReader().getString().substring(start));
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<String> result = new ArrayList<>(suggestions);
|
final CompletableFuture<CommandSuggestions> result = new CompletableFuture<>();
|
||||||
Collections.sort(result);
|
CompletableFuture.allOf(futures).thenRun(() -> {
|
||||||
return new CommandSuggestions(new StringRange(start, parse.getReader().getTotalLength()), result);
|
final Set<String> suggestions = Sets.newHashSet();
|
||||||
|
for (final CompletableFuture<Collection<String>> future : futures) {
|
||||||
|
suggestions.addAll(future.join());
|
||||||
|
}
|
||||||
|
final List<String> sorted = new ArrayList<>(suggestions);
|
||||||
|
Collections.sort(sorted);
|
||||||
|
result.complete(new CommandSuggestions(new StringRange(start, parse.getReader().getTotalLength()), sorted));
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RootCommandNode<S> getRoot() {
|
public RootCommandNode<S> getRoot() {
|
||||||
|
|
|
@ -4,11 +4,14 @@ import com.mojang.brigadier.StringReader;
|
||||||
import com.mojang.brigadier.context.CommandContextBuilder;
|
import com.mojang.brigadier.context.CommandContextBuilder;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public interface ArgumentType<T> {
|
public interface ArgumentType<T> {
|
||||||
<S> T parse(StringReader reader, CommandContextBuilder<S> contextBuilder) throws CommandSyntaxException;
|
<S> T parse(StringReader reader, CommandContextBuilder<S> contextBuilder) throws CommandSyntaxException;
|
||||||
|
|
||||||
default <S> void listSuggestions(final String command, final Set<String> output, final CommandContextBuilder<S> contextBuilder) {
|
default <S> CompletableFuture<Collection<String>> listSuggestions(final String command) {
|
||||||
|
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,12 @@ import com.mojang.brigadier.RedirectModifier;
|
||||||
import com.mojang.brigadier.StringReader;
|
import com.mojang.brigadier.StringReader;
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
|
||||||
import com.mojang.brigadier.context.CommandContextBuilder;
|
import com.mojang.brigadier.context.CommandContextBuilder;
|
||||||
import com.mojang.brigadier.context.ParsedArgument;
|
import com.mojang.brigadier.context.ParsedArgument;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class ArgumentCommandNode<S, T> extends CommandNode<S> {
|
public class ArgumentCommandNode<S, T> extends CommandNode<S> {
|
||||||
|
@ -57,8 +55,8 @@ public class ArgumentCommandNode<S, T> extends CommandNode<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void listSuggestions(final String command, final Set<String> output, final CommandContextBuilder<S> contextBuilder) {
|
public CompletableFuture<Collection<String>> listSuggestions(final String command) {
|
||||||
type.listSuggestions(command, output, contextBuilder);
|
return type.listSuggestions(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -14,6 +14,8 @@ import java.util.Collection;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -97,7 +99,7 @@ public abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
|
||||||
|
|
||||||
public abstract void parse(StringReader reader, CommandContextBuilder<S> contextBuilder) throws CommandSyntaxException;
|
public abstract void parse(StringReader reader, CommandContextBuilder<S> contextBuilder) throws CommandSyntaxException;
|
||||||
|
|
||||||
public abstract void listSuggestions(String command, Set<String> output, CommandContextBuilder<S> contextBuilder);
|
public abstract CompletableFuture<Collection<String>> listSuggestions(String command);
|
||||||
|
|
||||||
public abstract ArgumentBuilder<S, ?> createBuilder();
|
public abstract ArgumentBuilder<S, ?> createBuilder();
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,16 @@ import com.mojang.brigadier.Command;
|
||||||
import com.mojang.brigadier.RedirectModifier;
|
import com.mojang.brigadier.RedirectModifier;
|
||||||
import com.mojang.brigadier.StringReader;
|
import com.mojang.brigadier.StringReader;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
|
||||||
import com.mojang.brigadier.context.CommandContextBuilder;
|
import com.mojang.brigadier.context.CommandContextBuilder;
|
||||||
import com.mojang.brigadier.context.StringRange;
|
import com.mojang.brigadier.context.StringRange;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import com.mojang.brigadier.exceptions.ParameterizedCommandExceptionType;
|
import com.mojang.brigadier.exceptions.ParameterizedCommandExceptionType;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Function;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class LiteralCommandNode<S> extends CommandNode<S> {
|
public class LiteralCommandNode<S> extends CommandNode<S> {
|
||||||
|
@ -50,9 +51,11 @@ public class LiteralCommandNode<S> extends CommandNode<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void listSuggestions(final String command, final Set<String> output, final CommandContextBuilder<S> contextBuilder) {
|
public CompletableFuture<Collection<String>> listSuggestions(final String command) {
|
||||||
if (literal.startsWith(command)) {
|
if (literal.startsWith(command)) {
|
||||||
output.add(literal);
|
return CompletableFuture.completedFuture(Collections.singleton(literal));
|
||||||
|
} else {
|
||||||
|
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,9 @@ import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContextBuilder;
|
import com.mojang.brigadier.context.CommandContextBuilder;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
public class RootCommandNode<S> extends CommandNode<S> {
|
public class RootCommandNode<S> extends CommandNode<S> {
|
||||||
public RootCommandNode() {
|
public RootCommandNode() {
|
||||||
|
@ -28,7 +29,8 @@ public class RootCommandNode<S> extends CommandNode<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void listSuggestions(final String command, final Set<String> output, final CommandContextBuilder<S> contextBuilder) {
|
public CompletableFuture<Collection<String>> listSuggestions(final String command) {
|
||||||
|
return CompletableFuture.completedFuture(Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -29,7 +29,7 @@ public class CommandSuggestionsTest {
|
||||||
subject.register(literal("bar"));
|
subject.register(literal("bar"));
|
||||||
subject.register(literal("baz"));
|
subject.register(literal("baz"));
|
||||||
|
|
||||||
final CommandSuggestions result = subject.getCompletionSuggestions(subject.parse("", source));
|
final CommandSuggestions result = subject.getCompletionSuggestions(subject.parse("", source)).join();
|
||||||
|
|
||||||
assertThat(result.getRange(), equalTo(new StringRange(0, 0)));
|
assertThat(result.getRange(), equalTo(new StringRange(0, 0)));
|
||||||
assertThat(result.getSuggestions(), equalTo(Lists.newArrayList("bar", "baz", "foo")));
|
assertThat(result.getSuggestions(), equalTo(Lists.newArrayList("bar", "baz", "foo")));
|
||||||
|
@ -41,7 +41,7 @@ public class CommandSuggestionsTest {
|
||||||
subject.register(literal("bar"));
|
subject.register(literal("bar"));
|
||||||
subject.register(literal("baz"));
|
subject.register(literal("baz"));
|
||||||
|
|
||||||
final CommandSuggestions result = subject.getCompletionSuggestions(subject.parse("b", source));
|
final CommandSuggestions result = subject.getCompletionSuggestions(subject.parse("b", source)).join();
|
||||||
|
|
||||||
assertThat(result.getRange(), equalTo(new StringRange(0, 1)));
|
assertThat(result.getRange(), equalTo(new StringRange(0, 1)));
|
||||||
assertThat(result.getSuggestions(), equalTo(Lists.newArrayList("bar", "baz")));
|
assertThat(result.getSuggestions(), equalTo(Lists.newArrayList("bar", "baz")));
|
||||||
|
@ -56,7 +56,7 @@ public class CommandSuggestionsTest {
|
||||||
.then(literal("baz"))
|
.then(literal("baz"))
|
||||||
);
|
);
|
||||||
|
|
||||||
final CommandSuggestions result = subject.getCompletionSuggestions(subject.parse("parent ", source));
|
final CommandSuggestions result = subject.getCompletionSuggestions(subject.parse("parent ", source)).join();
|
||||||
|
|
||||||
assertThat(result.getRange(), equalTo(new StringRange(7, 7)));
|
assertThat(result.getRange(), equalTo(new StringRange(7, 7)));
|
||||||
assertThat(result.getSuggestions(), equalTo(Lists.newArrayList("bar", "baz", "foo")));
|
assertThat(result.getSuggestions(), equalTo(Lists.newArrayList("bar", "baz", "foo")));
|
||||||
|
@ -71,7 +71,7 @@ public class CommandSuggestionsTest {
|
||||||
.then(literal("baz"))
|
.then(literal("baz"))
|
||||||
);
|
);
|
||||||
|
|
||||||
final CommandSuggestions result = subject.getCompletionSuggestions(subject.parse("parent b", source));
|
final CommandSuggestions result = subject.getCompletionSuggestions(subject.parse("parent b", source)).join();
|
||||||
|
|
||||||
assertThat(result.getRange(), equalTo(new StringRange(7, 8)));
|
assertThat(result.getRange(), equalTo(new StringRange(7, 8)));
|
||||||
assertThat(result.getSuggestions(), equalTo(Lists.newArrayList("bar", "baz")));
|
assertThat(result.getSuggestions(), equalTo(Lists.newArrayList("bar", "baz")));
|
||||||
|
|
|
@ -67,14 +67,6 @@ public class FloatArgumentTypeTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuggestions() throws Exception {
|
|
||||||
final Set<String> set = Sets.newHashSet();
|
|
||||||
@SuppressWarnings("unchecked") final CommandContextBuilder<Object> context = Mockito.mock(CommandContextBuilder.class);
|
|
||||||
type.listSuggestions("", set, context);
|
|
||||||
assertThat(set, is(empty()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEquals() throws Exception {
|
public void testEquals() throws Exception {
|
||||||
new EqualsTester()
|
new EqualsTester()
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||||
|
@ -69,10 +70,8 @@ public class IntegerArgumentTypeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestions() throws Exception {
|
public void testSuggestions() throws Exception {
|
||||||
final Set<String> set = Sets.newHashSet();
|
final Collection<String> result = type.listSuggestions("").join();
|
||||||
@SuppressWarnings("unchecked") final CommandContextBuilder<Object> context = Mockito.mock(CommandContextBuilder.class);
|
assertThat(result, is(empty()));
|
||||||
type.listSuggestions("", set, context);
|
|
||||||
assertThat(set, is(empty()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -51,13 +51,6 @@ public class StringArgumentTypeTest {
|
||||||
assertThat(reader.canRead(), is(false));
|
assertThat(reader.canRead(), is(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuggestions() throws Exception {
|
|
||||||
final Set<String> set = Sets.newHashSet();
|
|
||||||
string().listSuggestions("", set, context);
|
|
||||||
assertThat(set, is(empty()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToString() throws Exception {
|
public void testToString() throws Exception {
|
||||||
assertThat(string(), hasToString("string()"));
|
assertThat(string(), hasToString("string()"));
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||||
|
@ -53,10 +54,8 @@ public class ArgumentCommandNodeTest extends AbstractCommandNodeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestions() throws Exception {
|
public void testSuggestions() throws Exception {
|
||||||
final Set<String> set = Sets.newHashSet();
|
final Collection<String> result = node.listSuggestions("").join();
|
||||||
@SuppressWarnings("unchecked") final CommandContextBuilder<Object> context = Mockito.mock(CommandContextBuilder.class);
|
assertThat(result, is(empty()));
|
||||||
node.listSuggestions("", set, context);
|
|
||||||
assertThat(set, is(empty()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal;
|
import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal;
|
||||||
|
@ -80,23 +81,17 @@ public class LiteralCommandNodeTest extends AbstractCommandNodeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestions() throws Exception {
|
public void testSuggestions() throws Exception {
|
||||||
final Set<String> set = Sets.newHashSet();
|
final Collection<String> empty = node.listSuggestions("").join();
|
||||||
@SuppressWarnings("unchecked") final CommandContextBuilder<Object> context = Mockito.mock(CommandContextBuilder.class);
|
assertThat(empty, equalTo(Sets.newHashSet("foo")));
|
||||||
|
|
||||||
node.listSuggestions("", set, context);
|
final Collection<String> foo = node.listSuggestions("foo").join();
|
||||||
assertThat(set, equalTo(Sets.newHashSet("foo")));
|
assertThat(foo, equalTo(Sets.newHashSet("foo")));
|
||||||
|
|
||||||
set.clear();
|
final Collection<String> food = node.listSuggestions("food").join();
|
||||||
node.listSuggestions("foo", set, context);
|
assertThat(food, is(empty()));
|
||||||
assertThat(set, equalTo(Sets.newHashSet("foo")));
|
|
||||||
|
|
||||||
set.clear();
|
final Collection<String> b = node.listSuggestions("b").join();
|
||||||
node.listSuggestions("food", set, context);
|
assertThat(b, is(empty()));
|
||||||
assertThat(set, is(empty()));
|
|
||||||
|
|
||||||
set.clear();
|
|
||||||
node.listSuggestions("b", set, context);
|
|
||||||
assertThat(set, is(empty()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal;
|
import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal;
|
||||||
|
@ -48,10 +49,8 @@ public class RootCommandNodeTest extends AbstractCommandNodeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuggestions() throws Exception {
|
public void testSuggestions() throws Exception {
|
||||||
final Set<String> set = Sets.newHashSet();
|
final Collection<String> result = node.listSuggestions("").join();
|
||||||
@SuppressWarnings("unchecked") final CommandContextBuilder<Object> context = Mockito.mock(CommandContextBuilder.class);
|
assertThat(result, is(empty()));
|
||||||
node.listSuggestions("", set, context);
|
|
||||||
assertThat(set, is(empty()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
|
|
Loading…
Reference in a new issue