Made all exceptions throw with context

This commit is contained in:
Nathan Adams 2017-07-27 09:58:14 +02:00
parent 9276feddd4
commit 5181559f46
16 changed files with 275 additions and 61 deletions

View file

@ -22,7 +22,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_UNKNOWN_ARGUMENT = new SimpleCommandExceptionType("command.unknown.argument", "Incorrect argument for command");
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 = " ";
@ -52,19 +52,19 @@ public class CommandDispatcher<S> {
}
public int execute(final ParseResults<S> parse) throws CommandException {
if (parse.getRemaining().length() > 0) {
if (parse.getReader().canRead()) {
if (parse.getExceptions().size() == 1) {
throw parse.getExceptions().values().iterator().next();
} else if (parse.getContext().getInput().isEmpty()) {
throw ERROR_UNKNOWN_COMMAND.create();
throw ERROR_UNKNOWN_COMMAND.createWithContext(parse.getReader());
} else {
throw ERROR_UNKNOWN_ARGUMENT.create(parse.getRemaining());
throw ERROR_UNKNOWN_ARGUMENT.createWithContext(parse.getReader());
}
}
final CommandContext<S> context = parse.getContext().build();
final Command<S> command = context.getCommand();
if (command == null) {
throw ERROR_UNKNOWN_COMMAND.create();
throw ERROR_UNKNOWN_COMMAND.createWithContext(parse.getReader());
}
return command.run(context);
}
@ -95,7 +95,7 @@ public class CommandDispatcher<S> {
context.withCommand(child.getCommand());
if (reader.canRead()) {
if (reader.peek() != ARGUMENT_SEPARATOR_CHAR) {
throw ERROR_EXPECTED_ARGUMENT_SEPARATOR.create();
throw ERROR_EXPECTED_ARGUMENT_SEPARATOR.createWithContext(reader);
}
reader.skip();
return parseNodes(child, reader, context);
@ -104,7 +104,7 @@ public class CommandDispatcher<S> {
}
}
return new ParseResults<>(contextBuilder, reader.getRemaining(), errors);
return new ParseResults<>(contextBuilder, reader, errors);
}
public String[] getAllUsage(final CommandNode<S> node, final S source) {

View file

@ -0,0 +1,23 @@
package com.mojang.brigadier;
public interface ImmutableStringReader {
String getString();
int getRemainingLength();
int getTotalLength();
int getCursor();
String getRead();
String getRemaining();
boolean canRead(int length);
boolean canRead();
char peek();
char peek(int offset);
}

View file

@ -9,25 +9,25 @@ import java.util.Map;
public class ParseResults<S> {
private final CommandContextBuilder<S> context;
private final String remaining;
private final Map<CommandNode<S>, CommandException> exceptions;
private final ImmutableStringReader reader;
public ParseResults(final CommandContextBuilder<S> context, final String remaining, final Map<CommandNode<S>, CommandException> exceptions) {
public ParseResults(final CommandContextBuilder<S> context, final ImmutableStringReader reader, final Map<CommandNode<S>, CommandException> exceptions) {
this.context = context;
this.remaining = remaining;
this.reader = reader;
this.exceptions = exceptions;
}
public ParseResults(final CommandContextBuilder<S> context) {
this(context, "", Collections.emptyMap());
this(context, new StringReader(""), Collections.emptyMap());
}
public CommandContextBuilder<S> getContext() {
return context;
}
public String getRemaining() {
return remaining;
public ImmutableStringReader getReader() {
return reader;
}
public Map<CommandNode<S>, CommandException> getExceptions() {

View file

@ -4,7 +4,7 @@ import com.mojang.brigadier.exceptions.CommandException;
import com.mojang.brigadier.exceptions.ParameterizedCommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
public class StringReader {
public class StringReader implements ImmutableStringReader {
private static final char SYNTAX_ESCAPE = '\\';
private static final char SYNTAX_QUOTE = '"';
@ -16,6 +16,7 @@ public class StringReader {
public static final SimpleCommandExceptionType ERROR_EXPECTED_INT = new SimpleCommandExceptionType("parsing.int.expected", "Expected integer");
public static final ParameterizedCommandExceptionType ERROR_INVALID_DOUBLE = new ParameterizedCommandExceptionType("parsing.double.invalid", "Invalid double '${value}'", "value");
public static final SimpleCommandExceptionType ERROR_EXPECTED_DOUBLE = new SimpleCommandExceptionType("parsing.double.expected", "Expected double");
public static final SimpleCommandExceptionType ERROR_EXPECTED_BOOL = new SimpleCommandExceptionType("parsing.bool.expected", "Expected bool");
public static final ParameterizedCommandExceptionType ERROR_EXPECTED_SYMBOL = new ParameterizedCommandExceptionType("parsing.expected", "Expected '${symbol}'", "symbol");
private final String string;
@ -25,6 +26,7 @@ public class StringReader {
this.string = string;
}
@Override
public String getString() {
return string;
}
@ -33,38 +35,47 @@ public class StringReader {
this.cursor = cursor;
}
@Override
public int getRemainingLength() {
return string.length() - cursor;
}
@Override
public int getTotalLength() {
return string.length();
}
@Override
public int getCursor() {
return cursor;
}
@Override
public String getRead() {
return string.substring(0, cursor);
}
@Override
public String getRemaining() {
return string.substring(cursor);
}
@Override
public boolean canRead(final int length) {
return cursor + length <= string.length();
}
@Override
public boolean canRead() {
return canRead(1);
}
@Override
public char peek() {
return string.charAt(cursor);
}
@Override
public char peek(final int offset) {
return string.charAt(cursor + offset);
}
@ -94,12 +105,13 @@ public class StringReader {
}
final String number = string.substring(start, cursor);
if (number.isEmpty()) {
throw ERROR_EXPECTED_INT.create();
throw ERROR_EXPECTED_INT.createWithContext(this);
}
try {
return Integer.parseInt(number);
} catch (final NumberFormatException ex) {
throw ERROR_INVALID_INT.create(number);
cursor = start;
throw ERROR_INVALID_INT.createWithContext(this, number);
}
}
@ -110,12 +122,13 @@ public class StringReader {
}
final String number = string.substring(start, cursor);
if (number.isEmpty()) {
throw ERROR_EXPECTED_DOUBLE.create();
throw ERROR_EXPECTED_DOUBLE.createWithContext(this);
}
try {
return Double.parseDouble(number);
} catch (final NumberFormatException ex) {
throw ERROR_INVALID_DOUBLE.create(number);
cursor = start;
throw ERROR_INVALID_DOUBLE.createWithContext(this, number);
}
}
@ -139,7 +152,7 @@ public class StringReader {
if (!canRead()) {
return "";
} else if (peek() != SYNTAX_QUOTE) {
throw ERROR_EXPECTED_START_OF_QUOTE.create();
throw ERROR_EXPECTED_START_OF_QUOTE.createWithContext(this);
}
skip();
final StringBuilder result = new StringBuilder();
@ -151,7 +164,8 @@ public class StringReader {
result.append(c);
escaped = false;
} else {
throw ERROR_INVALID_ESCAPE.create(String.valueOf(c));
setCursor(getCursor() - 1);
throw ERROR_INVALID_ESCAPE.createWithContext(this, String.valueOf(c));
}
} else if (c == SYNTAX_ESCAPE) {
escaped = true;
@ -162,7 +176,7 @@ public class StringReader {
}
}
throw ERROR_EXPECTED_END_OF_QUOTE.create();
throw ERROR_EXPECTED_END_OF_QUOTE.createWithContext(this);
}
public String readString() throws CommandException {
@ -174,19 +188,25 @@ public class StringReader {
}
public boolean readBoolean() throws CommandException {
final int start = cursor;
final String value = readString();
if (value.isEmpty()) {
throw ERROR_EXPECTED_BOOL.createWithContext(this);
}
if (value.equals("true")) {
return true;
} else if (value.equals("false")) {
return false;
} else {
throw ERROR_INVALID_BOOL.create(value);
cursor = start;
throw ERROR_INVALID_BOOL.createWithContext(this, value);
}
}
public void expect(final char c) throws CommandException {
if (!canRead() || peek() != c) {
throw ERROR_EXPECTED_SYMBOL.create(String.valueOf(c));
throw ERROR_EXPECTED_SYMBOL.createWithContext(this, String.valueOf(c));
}
skip();
}

View file

@ -45,19 +45,23 @@ public class IntegerArgumentType implements ArgumentType<Integer> {
@Override
public <S> Integer parse(final StringReader reader, final CommandContextBuilder<S> contextBuilder) throws CommandException {
final int start = reader.getCursor();
final int result = reader.readInt();
for (int i = 0; i < suffix.length(); i++) {
if (reader.canRead() && reader.peek() == suffix.charAt(i)) {
reader.skip();
} else {
throw ERROR_WRONG_SUFFIX.create(suffix);
reader.setCursor(start);
throw ERROR_WRONG_SUFFIX.createWithContext(reader, suffix);
}
}
if (result < minimum) {
throw ERROR_TOO_SMALL.create(result, minimum);
reader.setCursor(start);
throw ERROR_TOO_SMALL.createWithContext(reader, result, minimum);
}
if (result > maximum) {
throw ERROR_TOO_BIG.create(result, maximum);
reader.setCursor(start);
throw ERROR_TOO_BIG.createWithContext(reader, result, maximum);
}
return result;
}

View file

@ -3,27 +3,70 @@ package com.mojang.brigadier.exceptions;
import java.util.Map;
public class CommandException extends Exception {
public static final int CONTEXT_AMOUNT = 10;
public static boolean ENABLE_COMMAND_STACK_TRACES = true;
private final CommandExceptionType type;
private final Map<String, Object> data;
private final Map<String, String> data;
private final String input;
private final int cursor;
public CommandException(final CommandExceptionType type, final Map<String, Object> data) {
public CommandException(final CommandExceptionType type, final Map<String, String> data) {
super(type.getTypeName(), null, ENABLE_COMMAND_STACK_TRACES, ENABLE_COMMAND_STACK_TRACES);
this.type = type;
this.data = data;
this.input = null;
this.cursor = -1;
}
public CommandException(final CommandExceptionType type, final Map<String, String> data, final String input, final int cursor) {
super(type.getTypeName(), null, ENABLE_COMMAND_STACK_TRACES, ENABLE_COMMAND_STACK_TRACES);
this.type = type;
this.data = data;
this.input = input;
this.cursor = cursor;
}
@Override
public String getMessage() {
return type.getErrorMessage(this);
String message = type.getErrorMessage(data);
final String context = getContext();
if (context != null) {
message += " at position " + cursor + ": " + context;
}
return message;
}
public String getContext() {
if (input == null || cursor < 0) {
return null;
}
final StringBuilder builder = new StringBuilder();
final int cursor = Math.min(input.length(), this.cursor);
if (cursor > CONTEXT_AMOUNT) {
builder.append("...");
}
builder.append(input.substring(Math.max(0, cursor - CONTEXT_AMOUNT), cursor));
builder.append("<--[HERE]");
return builder.toString();
}
public CommandExceptionType getType() {
return type;
}
public Map<String, Object> getData() {
public Map<String, String> getData() {
return data;
}
public String getInput() {
return input;
}
public int getCursor() {
return cursor;
}
}

View file

@ -1,7 +1,9 @@
package com.mojang.brigadier.exceptions;
import java.util.Map;
public interface CommandExceptionType {
String getTypeName();
String getErrorMessage(CommandException exception);
String getErrorMessage(Map<String, String> data);
}

View file

@ -2,7 +2,10 @@ package com.mojang.brigadier.exceptions;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.mojang.brigadier.ImmutableStringReader;
import com.mojang.brigadier.StringReader;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -26,28 +29,31 @@ public class ParameterizedCommandExceptionType implements CommandExceptionType {
}
@Override
public String getErrorMessage(final CommandException exception) {
public String getErrorMessage(final Map<String, String> data) {
final Matcher matcher = PATTERN.matcher(message);
final StringBuffer result = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(result, Matcher.quoteReplacement(exception.getData().get(matcher.group(1)).toString()));
matcher.appendReplacement(result, Matcher.quoteReplacement(data.get(matcher.group(1))));
}
matcher.appendTail(result);
return result.toString();
}
public CommandException create(final Object... values) {
public CommandException createWithContext(final ImmutableStringReader reader, final Object... values) {
return new CommandException(this, createMap(values), reader.getString(), reader.getCursor());
}
public Map<String, String> createMap(final Object... values) {
if (values.length != keys.length) {
throw new IllegalArgumentException("Invalid values! (Expected: " + JOINER.join(keys) + ")");
}
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
for (int i = 0; i < keys.length; i++) {
builder = builder.put(keys[i], values[i]);
builder = builder.put(keys[i], String.valueOf(values[i]));
}
return new CommandException(this, builder.build());
return builder.build();
}
@Override

View file

@ -1,6 +1,10 @@
package com.mojang.brigadier.exceptions;
import com.google.common.collect.ImmutableMap;
import com.mojang.brigadier.ImmutableStringReader;
import com.mojang.brigadier.StringReader;
import java.util.Map;
public class SimpleCommandExceptionType implements CommandExceptionType {
private final String name;
@ -17,12 +21,12 @@ public class SimpleCommandExceptionType implements CommandExceptionType {
}
@Override
public String getErrorMessage(final CommandException exception) {
public String getErrorMessage(final Map<String, String> data) {
return message;
}
public CommandException create() {
return new CommandException(this, ImmutableMap.of());
public CommandException createWithContext(final ImmutableStringReader reader) {
return new CommandException(this, ImmutableMap.of(), reader.getString(), reader.getCursor());
}
@Override

View file

@ -31,11 +31,13 @@ public class LiteralCommandNode<S> extends CommandNode<S> {
@Override
public void parse(final StringReader reader, final CommandContextBuilder<S> contextBuilder) throws CommandException {
final int start = reader.getCursor();
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);
reader.setCursor(start);
throw ERROR_INCORRECT_LITERAL.createWithContext(reader, literal);
}
}

View file

@ -68,6 +68,7 @@ public class CommandDispatcherTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(CommandDispatcher.ERROR_UNKNOWN_COMMAND));
assertThat(ex.getData(), is(Collections.<String, Object>emptyMap()));
assertThat(ex.getCursor(), is(0));
}
}
@ -81,6 +82,7 @@ public class CommandDispatcherTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(CommandDispatcher.ERROR_UNKNOWN_COMMAND));
assertThat(ex.getData(), is(Collections.<String, Object>emptyMap()));
assertThat(ex.getCursor(), is(0));
}
}
@ -94,6 +96,7 @@ public class CommandDispatcherTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(CommandDispatcher.ERROR_UNKNOWN_COMMAND));
assertThat(ex.getData(), is(Collections.<String, Object>emptyMap()));
assertThat(ex.getCursor(), is(0));
}
}
@ -106,7 +109,8 @@ public class CommandDispatcherTest {
fail();
} catch (final CommandException ex) {
assertThat(ex.getType(), is(CommandDispatcher.ERROR_UNKNOWN_ARGUMENT));
assertThat(ex.getData(), is(Collections.singletonMap("argument", "bar")));
assertThat(ex.getData(), is(Collections.emptyMap()));
assertThat(ex.getCursor(), is(4));
}
}
@ -120,6 +124,7 @@ public class CommandDispatcherTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(LiteralCommandNode.ERROR_INCORRECT_LITERAL));
assertThat(ex.getData(), is(Collections.singletonMap("expected", "bar")));
assertThat(ex.getCursor(), is(4));
}
}
@ -136,7 +141,8 @@ public class CommandDispatcherTest {
fail();
} catch (final CommandException ex) {
assertThat(ex.getType(), is(CommandDispatcher.ERROR_UNKNOWN_ARGUMENT));
assertThat(ex.getData(), is(Collections.singletonMap("argument", "unknown")));
assertThat(ex.getData(), is(Collections.emptyMap()));
assertThat(ex.getCursor(), is(4));
}
}
@ -158,6 +164,36 @@ public class CommandDispatcherTest {
verify(subCommand).run(any(CommandContext.class));
}
@Test
public void testExecuteOrphanedSubcommand() throws Exception {
subject.register(literal("foo").then(
argument("bar", integer())
).executes(command));
try {
subject.execute("foo 5", source);
fail();
} catch (final CommandException ex) {
assertThat(ex.getType(), is(CommandDispatcher.ERROR_UNKNOWN_COMMAND));
assertThat(ex.getData(), is(Collections.emptyMap()));
assertThat(ex.getCursor(), is(0));
}
}
@Test
public void parse_noSpaceSeparator() throws Exception {
subject.register(literal("foo").then(argument("bar", integer()).executes(command)));
try {
subject.execute("foo5", source);
fail();
} catch (final CommandException ex) {
assertThat(ex.getType(), is(CommandDispatcher.ERROR_EXPECTED_ARGUMENT_SEPARATOR));
assertThat(ex.getData(), is(Collections.emptyMap()));
assertThat(ex.getCursor(), is(3));
}
}
@Test
public void testExecuteInvalidSubcommand() throws Exception {
subject.register(literal("foo").then(
@ -170,6 +206,7 @@ public class CommandDispatcherTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_EXPECTED_INT));
assertThat(ex.getData(), is(Collections.emptyMap()));
assertThat(ex.getCursor(), is(4));
}
}
}

View file

@ -219,6 +219,7 @@ public class StringReaderTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_EXPECTED_START_OF_QUOTE));
assertThat(ex.getData(), equalTo(Collections.emptyMap()));
assertThat(ex.getCursor(), is(0));
}
}
@ -229,6 +230,7 @@ public class StringReaderTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_EXPECTED_END_OF_QUOTE));
assertThat(ex.getData(), equalTo(Collections.emptyMap()));
assertThat(ex.getCursor(), is(12));
}
}
@ -239,6 +241,7 @@ public class StringReaderTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_INVALID_ESCAPE));
assertThat(ex.getData(), equalTo(ImmutableMap.of("character", "n")));
assertThat(ex.getCursor(), is(7));
}
}
@ -265,6 +268,7 @@ public class StringReaderTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_INVALID_INT));
assertThat(ex.getData(), equalTo(ImmutableMap.of("value", "12.34")));
assertThat(ex.getCursor(), is(0));
}
}
@ -275,6 +279,7 @@ public class StringReaderTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_EXPECTED_INT));
assertThat(ex.getData(), equalTo(Collections.emptyMap()));
assertThat(ex.getCursor(), is(0));
}
}
@ -325,6 +330,7 @@ public class StringReaderTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_INVALID_DOUBLE));
assertThat(ex.getData(), equalTo(ImmutableMap.of("value", "12.34.56")));
assertThat(ex.getCursor(), is(0));
}
}
@ -335,6 +341,7 @@ public class StringReaderTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_EXPECTED_DOUBLE));
assertThat(ex.getData(), equalTo(Collections.emptyMap()));
assertThat(ex.getCursor(), is(0));
}
}
@ -370,6 +377,7 @@ public class StringReaderTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_EXPECTED_SYMBOL));
assertThat(ex.getData(), equalTo(ImmutableMap.of("symbol", "a")));
assertThat(ex.getCursor(), is(0));
}
}
@ -382,6 +390,40 @@ public class StringReaderTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_EXPECTED_SYMBOL));
assertThat(ex.getData(), equalTo(ImmutableMap.of("symbol", "a")));
assertThat(ex.getCursor(), is(0));
}
}
@Test
public void readBoolean_correct() throws Exception {
final StringReader reader = new StringReader("true");
assertThat(reader.readBoolean(), is(true));
assertThat(reader.getRead(), equalTo("true"));
}
@Test
public void readBoolean_incorrect() throws Exception {
final StringReader reader = new StringReader("tuesday");
try {
reader.readBoolean();
fail();
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_INVALID_BOOL));
assertThat(ex.getData(), equalTo(ImmutableMap.of("value", "tuesday")));
assertThat(ex.getCursor(), is(0));
}
}
@Test
public void readBoolean_none() throws Exception {
final StringReader reader = new StringReader("");
try {
reader.readBoolean();
fail();
} catch (final CommandException ex) {
assertThat(ex.getType(), is(StringReader.ERROR_EXPECTED_BOOL));
assertThat(ex.getData(), equalTo(Collections.emptyMap()));
assertThat(ex.getCursor(), is(0));
}
}
}

View file

@ -57,6 +57,7 @@ public class IntegerArgumentTypeTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(IntegerArgumentType.ERROR_WRONG_SUFFIX));
assertThat(ex.getData(), equalTo(ImmutableMap.<String, Object>of("suffix", "L")));
assertThat(ex.getCursor(), is(0));
}
}
@ -69,6 +70,7 @@ public class IntegerArgumentTypeTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(IntegerArgumentType.ERROR_WRONG_SUFFIX));
assertThat(ex.getData(), equalTo(ImmutableMap.<String, Object>of("suffix", "L")));
assertThat(ex.getCursor(), is(0));
}
}
@ -80,7 +82,8 @@ public class IntegerArgumentTypeTest {
fail();
} catch (final CommandException ex) {
assertThat(ex.getType(), is(IntegerArgumentType.ERROR_TOO_SMALL));
assertThat(ex.getData(), equalTo(ImmutableMap.<String, Object>of("found", -5, "minimum", 0)));
assertThat(ex.getData(), equalTo(ImmutableMap.<String, Object>of("found", "-5", "minimum", "0")));
assertThat(ex.getCursor(), is(0));
}
}
@ -92,7 +95,8 @@ public class IntegerArgumentTypeTest {
fail();
} catch (final CommandException ex) {
assertThat(ex.getType(), is(IntegerArgumentType.ERROR_TOO_BIG));
assertThat(ex.getData(), equalTo(ImmutableMap.<String, Object>of("found", 5, "maximum", 0)));
assertThat(ex.getData(), equalTo(ImmutableMap.<String, Object>of("found", "5", "maximum", "0")));
assertThat(ex.getCursor(), is(0));
}
}

View file

@ -2,10 +2,12 @@ package com.mojang.brigadier.exceptions;
import com.google.common.collect.ImmutableMap;
import com.google.common.testing.EqualsTester;
import com.mojang.brigadier.StringReader;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
@ -18,21 +20,19 @@ public class ParameterizedCommandExceptionTypeTest {
}
@Test(expected = IllegalArgumentException.class)
public void testCreateTooFewArguments() throws Exception {
type.create();
}
@Test(expected = IllegalArgumentException.class)
public void testCreateTooManyArguments() throws Exception {
type.create("World", "Universe");
public void createMap_TooManyArguments() throws Exception {
type.createMap("World", "Universe");
}
@Test
public void testCreate() throws Exception {
final CommandException exception = type.create("World");
public void createWithContext() throws Exception {
final StringReader reader = new StringReader("Foo bar");
reader.setCursor(5);
final CommandException exception = type.createWithContext(reader, "World");
assertThat(exception.getType(), is(type));
assertThat(exception.getData(), is(ImmutableMap.<String, Object>of("name", "World")));
assertThat(exception.getMessage(), is("Hello, World!"));
assertThat(exception.getInput(), is("Foo bar"));
assertThat(exception.getCursor(), is(5));
}
@Test

View file

@ -1,21 +1,29 @@
package com.mojang.brigadier.exceptions;
import com.google.common.testing.EqualsTester;
import com.mojang.brigadier.StringReader;
import org.junit.Test;
import static org.hamcrest.Matchers.empty;
import java.util.Collections;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
public class SimpleCommandExceptionTypeTest {
@Test
public void testCreate() throws Exception {
public void createWithContext() throws Exception {
final SimpleCommandExceptionType type = new SimpleCommandExceptionType("foo", "bar");
final CommandException exception = type.create();
final StringReader reader = new StringReader("Foo bar");
reader.setCursor(5);
final CommandException exception = type.createWithContext(reader);
assertThat(exception.getType(), is(type));
assertThat(exception.getMessage(), is("bar"));
assertThat(exception.getData().values(), empty());
assertThat(exception.getData(), is(Collections.emptyMap()));
assertThat(exception.getInput(), is("Foo bar"));
assertThat(exception.getCursor(), is(5));
}
@Test
@ -25,4 +33,22 @@ public class SimpleCommandExceptionTypeTest {
.addEqualityGroup(new SimpleCommandExceptionType("bar", "Hello, world!"), new SimpleCommandExceptionType("bar", "Hello, universe!"))
.testEquals();
}
@Test
public void getContext_none() throws Exception {
final CommandException exception = new CommandException(mock(CommandExceptionType.class), Collections.emptyMap());
assertThat(exception.getContext(), is(nullValue()));
}
@Test
public void getContext_short() throws Exception {
final CommandException exception = new CommandException(mock(CommandExceptionType.class), Collections.emptyMap(), "Hello world!", 5);
assertThat(exception.getContext(), equalTo("Hello<--[HERE]"));
}
@Test
public void getContext_long() throws Exception {
final CommandException exception = new CommandException(mock(CommandExceptionType.class), Collections.emptyMap(), "Hello world! This has an error in it. Oh dear!", 20);
assertThat(exception.getContext(), equalTo("...d! This ha<--[HERE]"));
}
}

View file

@ -69,6 +69,7 @@ public class LiteralCommandNodeTest extends AbstractCommandNodeTest {
} catch (final CommandException ex) {
assertThat(ex.getType(), is(LiteralCommandNode.ERROR_INCORRECT_LITERAL));
assertThat(ex.getData(), is(ImmutableMap.<String, Object>of("expected", "foo")));
assertThat(ex.getCursor(), is(0));
}
}