Don't store string arguments in contexts, ranges are more useful

This commit is contained in:
Nathan Adams
2017-11-07 15:53:12 +01:00
parent e342380600
commit 8ae247bb6a
13 changed files with 122 additions and 94 deletions
@@ -7,6 +7,7 @@ import com.google.common.collect.Sets;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.context.StringRange;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.tree.CommandNode;
@@ -70,7 +71,7 @@ public class CommandDispatcher<S> {
if (parse.getReader().canRead()) {
if (parse.getExceptions().size() == 1) {
throw parse.getExceptions().values().iterator().next();
} else if (parse.getContext().getInput().isEmpty()) {
} else if (parse.getContext().getRange().isEmpty()) {
throw ERROR_UNKNOWN_COMMAND.createWithContext(parse.getReader());
} else {
throw ERROR_UNKNOWN_ARGUMENT.createWithContext(parse.getReader());
@@ -111,7 +112,7 @@ public class CommandDispatcher<S> {
public ParseResults<S> parse(final String command, final S source) {
final StringReader reader = new StringReader(command);
final CommandContextBuilder<S> context = new CommandContextBuilder<>(this, source);
final CommandContextBuilder<S> context = new CommandContextBuilder<>(this, source, 0);
return parseNodes(root, reader, context);
}
@@ -154,8 +155,8 @@ public class CommandDispatcher<S> {
if (reader.canRead()) {
reader.skip();
if (child.getRedirect() != null) {
final CommandContextBuilder<S> childContext = new CommandContextBuilder<>(this, source);
childContext.withNode(child.getRedirect(), "");
final CommandContextBuilder<S> childContext = new CommandContextBuilder<>(this, source, reader.getCursor());
childContext.withNode(child.getRedirect(), new StringRange(reader.getCursor(), reader.getCursor()));
final ParseResults<S> parse = parseNodes(child.getRedirect(), reader, childContext);
context.withChild(parse.getContext());
return new ParseResults<>(context, parse.getReader(), parse.getExceptions());
@@ -317,7 +318,7 @@ public class CommandDispatcher<S> {
public String[] getCompletionSuggestions(final String command, final S source) {
final StringReader reader = new StringReader(command);
final Set<String> nodes = findSuggestions(root, reader, new CommandContextBuilder<>(this, source), Sets.newLinkedHashSet());
final Set<String> nodes = findSuggestions(root, reader, new CommandContextBuilder<>(this, source, 0), Sets.newLinkedHashSet());
return nodes.toArray(new String[nodes.size()]);
}
@@ -11,16 +11,16 @@ public class CommandContext<S> {
private final S source;
private final Command<S> command;
private final Map<String, ParsedArgument<S, ?>> arguments;
private final Map<CommandNode<S>, String> nodes;
private final String input;
private final Map<CommandNode<S>, StringRange> nodes;
private final StringRange range;
private final CommandContext<S> child;
public CommandContext(final S source, final Map<String, ParsedArgument<S, ?>> arguments, final Command<S> command, final Map<CommandNode<S>, String> nodes, final String input, final CommandContext<S> child) {
public CommandContext(final S source, final Map<String, ParsedArgument<S, ?>> arguments, final Command<S> command, final Map<CommandNode<S>, StringRange> nodes, final StringRange range, final CommandContext<S> child) {
this.source = source;
this.arguments = arguments;
this.command = command;
this.nodes = nodes;
this.input = input;
this.range = range;
this.child = child;
}
@@ -78,12 +78,11 @@ public class CommandContext<S> {
return result;
}
public String getInput() {
return input;
public StringRange getRange() {
return range;
}
public Map<CommandNode<S>, String> getNodes() {
public Map<CommandNode<S>, StringRange> getNodes() {
return nodes;
}
}
@@ -9,15 +9,17 @@ import java.util.Map;
public class CommandContextBuilder<S> {
private final Map<String, ParsedArgument<S, ?>> arguments = Maps.newLinkedHashMap();
private final Map<CommandNode<S>, String> nodes = Maps.newLinkedHashMap();
private final Map<CommandNode<S>, StringRange> nodes = Maps.newLinkedHashMap();
private final CommandDispatcher<S> dispatcher;
private S source;
private Command<S> command;
private CommandContextBuilder<S> child;
private StringRange range;
public CommandContextBuilder(final CommandDispatcher<S> dispatcher, final S source) {
public CommandContextBuilder(final CommandDispatcher<S> dispatcher, final S source, final int start) {
this.dispatcher = dispatcher;
this.source = source;
this.range = new StringRange(start, start);
}
public CommandContextBuilder<S> withSource(final S source) {
@@ -43,17 +45,19 @@ public class CommandContextBuilder<S> {
return this;
}
public CommandContextBuilder<S> withNode(final CommandNode<S> node, final String raw) {
nodes.put(node, raw);
public CommandContextBuilder<S> withNode(final CommandNode<S> node, final StringRange range) {
nodes.put(node, range);
this.range = new StringRange(Math.min(this.range.getStart(), range.getStart()), Math.max(this.range.getEnd(), range.getEnd()));
return this;
}
public CommandContextBuilder<S> copy() {
final CommandContextBuilder<S> copy = new CommandContextBuilder<>(dispatcher, source);
final CommandContextBuilder<S> copy = new CommandContextBuilder<>(dispatcher, source, range.getStart());
copy.command = command;
copy.arguments.putAll(arguments);
copy.nodes.putAll(nodes);
copy.child = child;
copy.range = range;
return copy;
}
@@ -70,31 +74,19 @@ public class CommandContextBuilder<S> {
return command;
}
public String getInput() {
final StringBuilder result = new StringBuilder();
boolean first = true;
for (final String node : nodes.values()) {
if (first) {
if (!node.isEmpty()) {
first = false;
}
} else {
result.append(CommandDispatcher.ARGUMENT_SEPARATOR);
}
result.append(node);
}
return result.toString();
}
public Map<CommandNode<S>, String> getNodes() {
public Map<CommandNode<S>, StringRange> getNodes() {
return nodes;
}
public CommandContext<S> build() {
return new CommandContext<>(source, arguments, command, nodes, getInput(), child == null ? null : child.build());
return new CommandContext<>(source, arguments, command, nodes, range, child == null ? null : child.build());
}
public CommandDispatcher<S> getDispatcher() {
return dispatcher;
}
public StringRange getRange() {
return range;
}
}
@@ -1,28 +1,18 @@
package com.mojang.brigadier.context;
import com.mojang.brigadier.ImmutableStringReader;
import java.util.Objects;
public class ParsedArgument<S, T> {
private final int start;
private final int end;
private final StringRange range;
private final T result;
public ParsedArgument(final int start, final int end, final T result) {
this.start = start;
this.end = end;
this.range = new StringRange(start, end);
this.result = result;
}
public String getRaw(final ImmutableStringReader reader) {
return reader.getString().substring(start, end);
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
public StringRange getRange() {
return range;
}
public T getResult() {
@@ -31,24 +21,18 @@ public class ParsedArgument<S, T> {
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (!(o instanceof ParsedArgument)) return false;
final ParsedArgument that = (ParsedArgument) o;
if (start != that.start) return false;
if (end != that.end) return false;
if (!result.equals(that.result)) return false;
return true;
if (this == o) {
return true;
}
if (!(o instanceof ParsedArgument)) {
return false;
}
final ParsedArgument<?, ?> that = (ParsedArgument<?, ?>) o;
return Objects.equals(range, that.range) && Objects.equals(result, that.result);
}
@Override
public int hashCode() {
int result = start;
result = 31 * result + end;
result = 31 * result + this.result.hashCode();
return result;
return Objects.hash(range, result);
}
}
@@ -0,0 +1,56 @@
package com.mojang.brigadier.context;
import com.mojang.brigadier.ImmutableStringReader;
import java.util.Objects;
public class StringRange {
private final int start;
private final int end;
public StringRange(final int start, final int end) {
this.start = start;
this.end = end;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
public String get(final ImmutableStringReader reader) {
return reader.getString().substring(start, end);
}
public String get(final String string) {
return string.substring(start, end);
}
public boolean isEmpty() {
return start == end;
}
public int getLength() {
return end - start;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (!(o instanceof StringRange)) {
return false;
}
final StringRange that = (StringRange) o;
return start == that.start && end == that.end;
}
@Override
public int hashCode() {
return Objects.hash(start, end);
}
}
@@ -53,7 +53,7 @@ public class ArgumentCommandNode<S, T> extends CommandNode<S> {
final ParsedArgument<S, T> parsed = new ParsedArgument<>(start, reader.getCursor(), result);
contextBuilder.withArgument(name, parsed);
contextBuilder.withNode(this, parsed.getRaw(reader));
contextBuilder.withNode(this, parsed.getRange());
}
@Override
@@ -6,6 +6,7 @@ import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.context.StringRange;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.ParameterizedCommandExceptionType;
@@ -45,7 +46,7 @@ public class LiteralCommandNode<S> extends CommandNode<S> {
}
}
contextBuilder.withNode(this, literal);
contextBuilder.withNode(this, new StringRange(start, reader.getCursor()));
}
@Override