diff --git a/src/main/java/com/mojang/brigadier/CommandDispatcher.java b/src/main/java/com/mojang/brigadier/CommandDispatcher.java index 3205fe6..e45eceb 100644 --- a/src/main/java/com/mojang/brigadier/CommandDispatcher.java +++ b/src/main/java/com/mojang/brigadier/CommandDispatcher.java @@ -560,16 +560,15 @@ public class CommandDispatcher { futures[i++] = future; } - final CompletableFuture result = new CompletableFuture<>(); - CompletableFuture.allOf(futures).thenRun(() -> { + return CompletableFuture.allOf(futures).handle((voidResult, exception) -> { final List suggestions = new ArrayList<>(); for (final CompletableFuture future : futures) { - suggestions.add(future.join()); + if (!future.isCompletedExceptionally()) { + suggestions.add(future.join()); + } } - result.complete(Suggestions.merge(fullInput, suggestions)); + return Suggestions.merge(fullInput, suggestions); }); - - return result; } /** diff --git a/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java b/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java index e516dfc..7ff1b0f 100644 --- a/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java +++ b/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java @@ -10,6 +10,8 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContextBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.suggestion.Suggestion; +import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.RootCommandNode; @@ -22,7 +24,10 @@ import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger; import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; @@ -495,6 +500,25 @@ public class CommandDispatcherTest { assertThat(subject.findNode(Lists.newArrayList("foo", "bar")), is(nullValue())); } + @SuppressWarnings("unchecked") + @Test + public void testCompletionWithErroredFutureReturnsCompletedFuture() { + final LiteralCommandNode bar = literal("bar").build(); + final LiteralCommandNode baz = mock(LiteralCommandNode.class); + when(baz.getLiteral()).thenReturn("baz"); + when(baz.listSuggestions(any(), any())).thenAnswer(x -> { + final CompletableFuture future = new CompletableFuture<>(); + future.completeExceptionally(new IllegalArgumentException()); + return future; + }); + subject.register(literal("foo").then(bar).then(baz)); + + final ParseResults parseResults = subject.parse("foo b", source); + final Suggestions suggestions = subject.getCompletionSuggestions(parseResults).join(); + final Collection suggestionCollection = suggestions.getList().stream().map(Suggestion::getText).collect(Collectors.toList()); + assertThat(Lists.newArrayList("bar"), is(suggestionCollection)); + } + @Test public void testResultConsumerInNonErrorRun() throws CommandSyntaxException { subject.setConsumer(consumer);