Made node parsing also use readers

This commit is contained in:
Nathan Adams
2017-07-25 16:00:38 +02:00
parent d2a5eeedc5
commit 3bb1a888fb
10 changed files with 69 additions and 69 deletions
@@ -23,6 +23,7 @@ import java.util.stream.Collectors;
public class CommandDispatcher<S> {
public static final SimpleCommandExceptionType ERROR_UNKNOWN_COMMAND = new SimpleCommandExceptionType("command.unknown.command", "Unknown command");
public static final ParameterizedCommandExceptionType ERROR_UNKNOWN_ARGUMENT = new ParameterizedCommandExceptionType("command.unknown.argument", "Incorrect argument for command, couldn't parse: ${argument}", "argument");
public static final SimpleCommandExceptionType ERROR_EXPECTED_ARGUMENT_SEPARATOR = new SimpleCommandExceptionType("command.expected.separator", "Expected whitespace to end one argument, but found trailing data");
public static final String ARGUMENT_SEPARATOR = " ";
public static final char ARGUMENT_SEPARATOR_CHAR = ' ';
@@ -69,10 +70,11 @@ public class CommandDispatcher<S> {
}
public ParseResults<S> parse(String command, S source) throws CommandException {
return parseNodes(root, command, new CommandContextBuilder<>(this, source));
StringReader reader = new StringReader(command);
return parseNodes(root, reader, new CommandContextBuilder<>(this, source));
}
private ParseResults<S> parseNodes(CommandNode<S> node, String command, CommandContextBuilder<S> contextBuilder) throws CommandException {
private ParseResults<S> parseNodes(CommandNode<S> node, StringReader reader, CommandContextBuilder<S> contextBuilder) throws CommandException {
final S source = contextBuilder.getSource();
Map<CommandNode<S>, CommandException> errors = Maps.newHashMap();
@@ -81,23 +83,28 @@ public class CommandDispatcher<S> {
continue;
}
CommandContextBuilder<S> context = contextBuilder.copy();
String remaining;
int cursor = reader.getCursor();
try {
remaining = child.parse(command, context);
child.parse(reader, context);
} catch (CommandException ex) {
errors.put(child, ex);
reader.setCursor(cursor);
continue;
}
context.withCommand(child.getCommand());
if (remaining.isEmpty()) {
return new ParseResults<>(context);
if (reader.canRead()) {
if (reader.peek() != ARGUMENT_SEPARATOR_CHAR) {
throw ERROR_EXPECTED_ARGUMENT_SEPARATOR.create();
}
reader.skip();
return parseNodes(child, reader, context);
} else {
return parseNodes(child, remaining.substring(1), context);
return new ParseResults<>(context);
}
}
return new ParseResults<>(contextBuilder, command, errors);
return new ParseResults<>(contextBuilder, reader.getRemaining(), errors);
}
public String[] getAllUsage(CommandNode<S> node, S source) {
@@ -184,22 +191,28 @@ public class CommandDispatcher<S> {
return self;
}
private Set<String> findSuggestions(CommandNode<S> node, String command, CommandContextBuilder<S> contextBuilder, Set<String> result) {
private Set<String> findSuggestions(CommandNode<S> node, StringReader reader, CommandContextBuilder<S> contextBuilder, Set<String> result) {
final S source = contextBuilder.getSource();
for (CommandNode<S> child : node.getChildren()) {
if (!child.canUse(source)) {
continue;
}
CommandContextBuilder<S> context = contextBuilder.copy();
int cursor = reader.getCursor();
try {
String remaining = child.parse(command, context);
if (remaining.isEmpty()) {
child.listSuggestions(command, result, context);
child.parse(reader, context);
if (reader.canRead()) {
if (reader.peek() == ARGUMENT_SEPARATOR_CHAR) {
reader.skip();
return findSuggestions(child, reader, context, result);
}
} else {
return findSuggestions(child, remaining.substring(1), context, result);
reader.setCursor(cursor);
child.listSuggestions(reader.getRemaining(), result, context);
}
} catch (CommandException e) {
child.listSuggestions(command, result, context);
reader.setCursor(cursor);
child.listSuggestions(reader.getRemaining(), result, context);
}
}
@@ -207,7 +220,8 @@ public class CommandDispatcher<S> {
}
public String[] getCompletionSuggestions(String command, S source) {
final Set<String> nodes = findSuggestions(root, command, new CommandContextBuilder<>(this, source), Sets.newLinkedHashSet());
StringReader reader = new StringReader(command);
final Set<String> nodes = findSuggestions(root, reader, new CommandContextBuilder<>(this, source), Sets.newLinkedHashSet());
return nodes.toArray(new String[nodes.size()]);
}
@@ -8,13 +8,6 @@ import com.mojang.brigadier.exceptions.CommandException;
import java.util.Set;
public interface ArgumentType<T> {
@Deprecated
default <S> ParsedArgument<S, T> parse(String command, CommandContextBuilder<S> contextBuilder) throws CommandException {
StringReader reader = new StringReader(command);
T result = parse(reader, contextBuilder);
return new ParsedArgument<>(reader.getRead(), result);
}
<S> T parse(StringReader reader, CommandContextBuilder<S> contextBuilder) throws CommandException;
default <S> void listSuggestions(String command, Set<String> output, CommandContextBuilder<S> contextBuilder) {}
@@ -1,6 +1,7 @@
package com.mojang.brigadier.tree;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.context.CommandContextBuilder;
@@ -50,18 +51,13 @@ public class ArgumentCommandNode<S, T> extends CommandNode<S> {
}
@Override
public String parse(String command, CommandContextBuilder<S> contextBuilder) throws CommandException {
ParsedArgument<S, T> parsed = type.parse(command, contextBuilder);
int start = parsed.getRaw().length();
public void parse(StringReader reader, CommandContextBuilder<S> contextBuilder) throws CommandException {
int start = reader.getCursor();
T result = type.parse(reader, contextBuilder);
ParsedArgument<S, T> parsed = new ParsedArgument<>(reader.getString().substring(start, reader.getCursor()), result);
contextBuilder.withArgument(name, parsed);
contextBuilder.withNode(this, parsed.getRaw());
if (command.length() > start) {
return command.substring(start);
} else {
return "";
}
}
@Override
@@ -3,6 +3,7 @@ package com.mojang.brigadier.tree;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Maps;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandException;
@@ -79,7 +80,7 @@ public abstract class CommandNode<S> implements Comparable<CommandNode<S>> {
public abstract String getUsageText();
public abstract String parse(String command, CommandContextBuilder<S> contextBuilder) throws CommandException;
public abstract void parse(StringReader reader, CommandContextBuilder<S> contextBuilder) throws CommandException;
public abstract void listSuggestions(String command, Set<String> output, CommandContextBuilder<S> contextBuilder);
@@ -2,6 +2,7 @@ package com.mojang.brigadier.tree;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandException;
@@ -30,16 +31,16 @@ public class LiteralCommandNode<S> extends CommandNode<S> {
}
@Override
public String parse(String command, CommandContextBuilder<S> contextBuilder) throws CommandException {
String expected = literal + (command.length() > literal.length() ? CommandDispatcher.ARGUMENT_SEPARATOR : "");
if (!command.startsWith(expected)) {
throw ERROR_INCORRECT_LITERAL.create(literal);
public void parse(StringReader reader, CommandContextBuilder<S> contextBuilder) throws CommandException {
for (int i = 0; i < literal.length(); i++) {
if (reader.canRead() && reader.peek() == literal.charAt(i)) {
reader.skip();
} else {
throw ERROR_INCORRECT_LITERAL.create(literal);
}
}
contextBuilder.withNode(this, literal);
int start = literal.length();
return command.substring(start);
}
@Override
@@ -1,5 +1,6 @@
package com.mojang.brigadier.tree;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.exceptions.CommandException;
@@ -22,8 +23,7 @@ public class RootCommandNode<S> extends CommandNode<S> {
}
@Override
public String parse(String command, CommandContextBuilder<S> contextBuilder) throws CommandException {
return command;
public void parse(StringReader reader, CommandContextBuilder<S> contextBuilder) throws CommandException {
}
@Override