Pass in source to evaluations of arguments

This commit is contained in:
Nathan Adams 2017-07-04 15:12:31 +02:00
parent 4af7274892
commit c1a159f75a
15 changed files with 96 additions and 83 deletions

View file

@ -6,7 +6,7 @@ import com.mojang.brigadier.exceptions.CommandException;
import java.util.Set;
public interface CommandArgumentType<T> {
ParsedArgument<T> parse(String command) throws CommandException;
<S> ParsedArgument<S, T> parse(String command) throws CommandException;
void listSuggestions(String command, Set<String> output);
}

View file

@ -42,7 +42,7 @@ public class IntegerArgumentType implements CommandArgumentType<Integer> {
}
@Override
public ParsedArgument<Integer> parse(String command) throws CommandException {
public <S> ParsedArgument<S, Integer> parse(String command) throws CommandException {
String raw = SPLITTER.split(command).iterator().next();
try {

View file

@ -39,7 +39,7 @@ public class StringArgumentType implements CommandArgumentType<String> {
}
@Override
public ParsedArgument<String> parse(String command) throws CommandException {
public <S> ParsedArgument<S, String> parse(String command) throws CommandException {
if (type == StringType.GREEDY_PHRASE) {
return new FixedParsedArgument<>(command, command);
} else if (type == StringType.SINGLE_WORLD) {

View file

@ -5,17 +5,18 @@ import com.google.common.collect.Maps;
import com.google.common.primitives.Primitives;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.tree.CommandNode;
import sun.security.x509.OIDMap;
import java.util.Map;
public class CommandContext<S> {
private final S source;
private final Map<String, ParsedArgument<?>> arguments;
private final Map<String, ParsedArgument<S, ?>> arguments;
private final Command<S> command;
private final Map<CommandNode<S>, String> nodes;
private final String input;
public CommandContext(S source, Map<String, ParsedArgument<?>> arguments, Command<S> command, Map<CommandNode<S>, String> nodes, String input) {
public CommandContext(S source, Map<String, ParsedArgument<S, ?>> arguments, Command<S> command, Map<CommandNode<S>, String> nodes, String input) {
this.source = source;
this.arguments = arguments;
this.command = command;
@ -33,16 +34,17 @@ public class CommandContext<S> {
@SuppressWarnings("unchecked")
public <V> V getArgument(String name, Class<V> clazz) {
ParsedArgument<?> argument = arguments.get(name);
ParsedArgument<S, ?> argument = arguments.get(name);
if (argument == null) {
throw new IllegalArgumentException("No such argument '" + name + "' exists on this command");
}
if (Primitives.wrap(clazz).isAssignableFrom(argument.getResult().getClass())) {
return ((ParsedArgument<V>) argument).getResult();
final Object result = argument.getResult(source);
if (Primitives.wrap(clazz).isAssignableFrom(result.getClass())) {
return (V) result;
} else {
throw new IllegalArgumentException("Argument '" + name + "' is defined as " + argument.getResult().getClass().getSimpleName() + ", not " + clazz);
throw new IllegalArgumentException("Argument '" + name + "' is defined as " + result.getClass().getSimpleName() + ", not " + clazz);
}
}
@ -79,7 +81,7 @@ public class CommandContext<S> {
}
public CommandContext<S> copy() {
Map<String, ParsedArgument<?>> arguments = Maps.newLinkedHashMap();
Map<String, ParsedArgument<S, ?>> arguments = Maps.newLinkedHashMap();
this.arguments.forEach((k, v) -> arguments.put(k, v.copy()));
return new CommandContext<>(source, arguments, command, nodes, input);
}

View file

@ -8,7 +8,7 @@ import com.mojang.brigadier.tree.CommandNode;
import java.util.Map;
public class CommandContextBuilder<S> {
private final Map<String, ParsedArgument<?>> arguments = Maps.newHashMap();
private final Map<String, ParsedArgument<S, ?>> arguments = Maps.newHashMap();
private final Map<CommandNode<S>, String> nodes = Maps.newLinkedHashMap();
private final StringBuilder input = new StringBuilder();
private S source;
@ -27,12 +27,12 @@ public class CommandContextBuilder<S> {
return source;
}
public CommandContextBuilder<S> withArgument(String name, ParsedArgument<?> argument) {
public CommandContextBuilder<S> withArgument(String name, ParsedArgument<S, ?> argument) {
this.arguments.put(name, argument);
return this;
}
public Map<String, ParsedArgument<?>> getArguments() {
public Map<String, ParsedArgument<S, ?>> getArguments() {
return arguments;
}

View file

@ -1,14 +1,14 @@
package com.mojang.brigadier.context;
import java.util.function.Supplier;
import java.util.function.Function;
public class DynamicParsedArgument<T> implements ParsedArgument<T> {
public class DynamicParsedArgument<S, T> implements ParsedArgument<S, T> {
private final String raw;
private Supplier<T> supplier;
private Function<S, T> supplier;
private boolean evaluated;
private T result;
public DynamicParsedArgument(String raw, Supplier<T> supplier) {
public DynamicParsedArgument(String raw, Function<S, T> supplier) {
this.raw = raw;
this.supplier = supplier;
}
@ -19,9 +19,9 @@ public class DynamicParsedArgument<T> implements ParsedArgument<T> {
}
@Override
public T getResult() {
public T getResult(S source) {
if (!evaluated) {
result = supplier.get();
result = supplier.apply(source);
evaluated = true;
}
return result;
@ -48,7 +48,7 @@ public class DynamicParsedArgument<T> implements ParsedArgument<T> {
}
@Override
public ParsedArgument<T> copy() {
public ParsedArgument<S, T> copy() {
return new DynamicParsedArgument<>(raw, supplier);
}
}

View file

@ -1,6 +1,6 @@
package com.mojang.brigadier.context;
public class FixedParsedArgument<T> implements ParsedArgument<T> {
public class FixedParsedArgument<S, T> implements ParsedArgument<S, T> {
private final String raw;
private final T result;
@ -15,7 +15,7 @@ public class FixedParsedArgument<T> implements ParsedArgument<T> {
}
@Override
public T getResult() {
public T getResult(S source) {
return result;
}
@ -40,7 +40,7 @@ public class FixedParsedArgument<T> implements ParsedArgument<T> {
}
@Override
public ParsedArgument<T> copy() {
public ParsedArgument<S, T> copy() {
return new FixedParsedArgument<>(raw, result);
}
}

View file

@ -1,9 +1,9 @@
package com.mojang.brigadier.context;
public interface ParsedArgument<T> {
public interface ParsedArgument<S, T> {
String getRaw();
T getResult();
T getResult(S source);
ParsedArgument<T> copy();
ParsedArgument<S, T> copy();
}

View file

@ -2,7 +2,6 @@ package com.mojang.brigadier.tree;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.CommandArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.context.ParsedArgument;
@ -44,7 +43,7 @@ public class ArgumentCommandNode<S, T> extends CommandNode<S> {
@Override
public String parse(String command, CommandContextBuilder<S> contextBuilder) throws CommandException {
ParsedArgument<T> parsed = type.parse(command);
ParsedArgument<S, T> parsed = type.parse(command);
int start = parsed.getRaw().length();
contextBuilder.withArgument(name, parsed);

View file

@ -7,11 +7,12 @@ import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.context.CommandContextBuilder;
import com.mojang.brigadier.context.ParsedArgument;
import com.mojang.brigadier.exceptions.CommandException;
import com.mojang.brigadier.exceptions.CommandExceptionType;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.Map;
import java.util.Set;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
@ -21,8 +22,11 @@ import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
@RunWith(MockitoJUnitRunner.class)
public class IntegerArgumentTypeTest {
private IntegerArgumentType type;
@Mock
private Object source;
@Before
public void setUp() throws Exception {
@ -31,10 +35,10 @@ public class IntegerArgumentTypeTest {
@Test
public void testParse() throws Exception {
ParsedArgument<Integer> result = type.parse("50");
ParsedArgument<Object, Integer> result = type.parse("50");
assertThat(result.getRaw(), is("50"));
assertThat(result.getResult(), is(50));
assertThat(result.getResult(source), is(50));
}
@Test
@ -61,10 +65,10 @@ public class IntegerArgumentTypeTest {
@Test
public void testParseLowerLimit() throws Exception {
ParsedArgument<Integer> result = type.parse("-100");
ParsedArgument<Object, Integer> result = type.parse("-100");
assertThat(result.getRaw(), is("-100"));
assertThat(result.getResult(), is(-100));
assertThat(result.getResult(source), is(-100));
}
@Test
@ -80,10 +84,10 @@ public class IntegerArgumentTypeTest {
@Test
public void testParseHigherLimit() throws Exception {
ParsedArgument<Integer> result = type.parse("100");
ParsedArgument<Object, Integer> result = type.parse("100");
assertThat(result.getRaw(), is("100"));
assertThat(result.getResult(), is(100));
assertThat(result.getResult(source), is(100));
}
@Test

View file

@ -3,8 +3,10 @@ package com.mojang.brigadier.arguments;
import com.google.common.collect.Sets;
import com.mojang.brigadier.context.ParsedArgument;
import com.mojang.brigadier.exceptions.CommandException;
import com.sun.xml.internal.ws.api.ComponentEx;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.Collections;
import java.util.Set;
@ -25,97 +27,100 @@ import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
@RunWith(MockitoJUnitRunner.class)
public class StringArgumentTypeTest {
private StringArgumentType type;
@Mock
private Object source;
@Test
public void testParseWord() throws Exception {
type = word();
ParsedArgument<String> result = type.parse("hello world");
ParsedArgument<Object, String> result = type.parse("hello world");
assertThat(result.getRaw(), is("hello"));
assertThat(result.getResult(), is("hello"));
assertThat(result.getResult(source), is("hello"));
}
@Test
public void testParseWord_empty() throws Exception {
type = word();
ParsedArgument<String> result = type.parse("");
ParsedArgument<Object, String> result = type.parse("");
assertThat(result.getRaw(), is(""));
assertThat(result.getResult(), is(""));
assertThat(result.getResult(source), is(""));
}
@Test
public void testParseWord_simple() throws Exception {
type = word();
ParsedArgument<String> result = type.parse("hello");
ParsedArgument<Object, String> result = type.parse("hello");
assertThat(result.getRaw(), is("hello"));
assertThat(result.getResult(), is("hello"));
assertThat(result.getResult(source), is("hello"));
}
@Test
public void testParseString() throws Exception {
type = string();
ParsedArgument<String> result = type.parse("hello world");
ParsedArgument<Object, String> result = type.parse("hello world");
assertThat(result.getRaw(), is("hello"));
assertThat(result.getResult(), is("hello"));
assertThat(result.getResult(source), is("hello"));
}
@Test
public void testParseGreedyString() throws Exception {
type = greedyString();
ParsedArgument<String> result = type.parse("hello world");
ParsedArgument<Object, String> result = type.parse("hello world");
assertThat(result.getRaw(), is("hello world"));
assertThat(result.getResult(), is("hello world"));
assertThat(result.getResult(source), is("hello world"));
}
@Test
public void testParse() throws Exception {
type = string();
ParsedArgument<String> result = type.parse("hello");
ParsedArgument<Object, String> result = type.parse("hello");
assertThat(result.getRaw(), is("hello"));
assertThat(result.getResult(), is("hello"));
assertThat(result.getResult(source), is("hello"));
}
@Test
public void testParseWordQuoted() throws Exception {
type = word();
ParsedArgument<String> result = type.parse("\"hello \\\" world\"");
ParsedArgument<Object, String> result = type.parse("\"hello \\\" world\"");
assertThat(result.getRaw(), is("\"hello"));
assertThat(result.getResult(), is("\"hello"));
assertThat(result.getResult(source), is("\"hello"));
}
@Test
public void testParseQuoted() throws Exception {
type = string();
ParsedArgument<String> result = type.parse("\"hello \\\" world\"");
ParsedArgument<Object, String> result = type.parse("\"hello \\\" world\"");
assertThat(result.getRaw(), is("\"hello \\\" world\""));
assertThat(result.getResult(), is("hello \" world"));
assertThat(result.getResult(source), is("hello \" world"));
}
@Test
public void testParseQuotedWithRemaining() throws Exception {
type = string();
ParsedArgument<String> result = type.parse("\"hello \\\" world\" with remaining");
ParsedArgument<Object, String> result = type.parse("\"hello \\\" world\" with remaining");
assertThat(result.getRaw(), is("\"hello \\\" world\""));
assertThat(result.getResult(), is("hello \" world"));
assertThat(result.getResult(source), is("hello \" world"));
}
@Test
public void testParseNotQuoted() throws Exception {
type = string();
ParsedArgument<String> result = type.parse("hello world");
ParsedArgument<Object, String> result = type.parse("hello world");
assertThat(result.getRaw(), is("hello"));
assertThat(result.getResult(), is("hello"));
assertThat(result.getResult(source), is("hello"));
}
@Test
@ -133,10 +138,10 @@ public class StringArgumentTypeTest {
@Test
public void testParseQuote_earlyUnquoteWithRemaining() throws Exception {
type = string();
ParsedArgument<String> result = type.parse("\"hello\" world");
ParsedArgument<Object, String> result = type.parse("\"hello\" world");
assertThat(result.getRaw(), is("\"hello\""));
assertThat(result.getResult(), is("hello"));
assertThat(result.getResult(source), is("hello"));
}
@Test
@ -154,10 +159,10 @@ public class StringArgumentTypeTest {
@Test
public void testParseQuote_lateQuoteWithRemaining() throws Exception {
type = string();
ParsedArgument<String> result = type.parse("hello \"world\"");
ParsedArgument<Object, String> result = type.parse("hello \"world\"");
assertThat(result.getRaw(), is("hello"));
assertThat(result.getResult(), is("hello"));
assertThat(result.getResult(source), is("hello"));
}
@Test
@ -187,10 +192,10 @@ public class StringArgumentTypeTest {
@Test
public void testParseEmpty() throws Exception {
type = string();
ParsedArgument<String> result = type.parse("");
ParsedArgument<Object, String> result = type.parse("");
assertThat(result.getRaw(), is(""));
assertThat(result.getResult(), is(""));
assertThat(result.getResult(source), is(""));
}
@Test

View file

@ -9,6 +9,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.function.Function;
import java.util.function.Supplier;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
@ -84,13 +85,13 @@ public class CommandContextTest {
public void testCopy() throws Exception {
Object first = new Object();
Object second = new Object();
@SuppressWarnings("unchecked") Supplier<Object> supplier = (Supplier<Object>) mock(Supplier.class);
@SuppressWarnings("unchecked") Function<Object, Object> supplier = (Function<Object, Object>) mock(Function.class);
when(supplier.get()).thenReturn(first);
when(supplier.apply(source)).thenReturn(first);
CommandContext<Object> context = builder.withNode(literal("test").build(), "test").withArgument("test", new DynamicParsedArgument<>("test", supplier)).build();
assertThat(context.getArgument("test", Object.class), is(first));
when(supplier.get()).thenReturn(second);
when(supplier.apply(source)).thenReturn(second);
CommandContext<Object> copy = context.copy();
assertThat(context, is(equalTo(copy)));
assertThat(copy.getArgument("test", Object.class), is(second));

View file

@ -1,14 +1,13 @@
package com.mojang.brigadier.context;
import com.google.common.testing.EqualsTester;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.util.function.Function;
import java.util.function.Supplier;
import static org.hamcrest.Matchers.equalTo;
@ -20,9 +19,11 @@ import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class DynamicParsedArgumentTest {
private DynamicParsedArgument<Object> subject;
private DynamicParsedArgument<Object, Object> subject;
@Mock
private Supplier<Object> supplier;
private Function<Object, Object> supplier;
@Mock
private Object source;
@Before
public void setUp() throws Exception {
@ -32,28 +33,28 @@ public class DynamicParsedArgumentTest {
@Test
public void suppliedOnce() throws Exception {
Object result = new Object();
when(supplier.get()).thenReturn(result);
when(supplier.apply(source)).thenReturn(result);
assertThat("first evaluation", subject.getResult(), is(result));
assertThat("already evaluated", subject.getResult(), is(result));
assertThat("first evaluation", subject.getResult(source), is(result));
assertThat("already evaluated", subject.getResult(source), is(result));
verify(supplier, times(1)).get();
verify(supplier, times(1)).apply(source);
}
@Test
public void copy() throws Exception {
Object result = new Object();
when(supplier.get()).thenReturn(result);
assertThat(subject.getResult(), is(result));
when(supplier.apply(source)).thenReturn(result);
assertThat(subject.getResult(source), is(result));
Object newResult = new Object();
when(supplier.get()).thenReturn(newResult);
ParsedArgument<Object> copy = subject.copy();
assertThat(copy.getResult(), is(newResult));
when(supplier.apply(source)).thenReturn(newResult);
ParsedArgument<Object, Object> copy = subject.copy();
assertThat(copy.getResult(source), is(newResult));
assertThat(copy, is(equalTo(subject)));
verify(supplier, times(2)).get();
verify(supplier, times(2)).apply(source);
}
@Test

View file

@ -21,7 +21,7 @@ public class FixedParsedArgumentTest {
@Test
public void copy() throws Exception {
final FixedParsedArgument<String> argument = new FixedParsedArgument<>("foo", "bar");
final FixedParsedArgument<Object, String> argument = new FixedParsedArgument<>("foo", "bar");
assertThat(argument.copy(), is(equalTo(argument)));
}
}

View file

@ -24,6 +24,7 @@ import static org.mockito.Mockito.mock;
public class ArgumentCommandNodeTest extends AbstractCommandNodeTest {
private ArgumentCommandNode<Object, Integer> node;
private CommandContextBuilder<Object> contextBuilder;
private Object source = new Object();
@Override
protected CommandNode<Object> getCommandNode() {
@ -41,7 +42,7 @@ public class ArgumentCommandNodeTest extends AbstractCommandNodeTest {
assertThat(node.parse("123 456", contextBuilder), is(" 456"));
assertThat(contextBuilder.getArguments().containsKey("foo"), is(true));
assertThat(contextBuilder.getArguments().get("foo").getResult(), is(123));
assertThat(contextBuilder.getArguments().get("foo").getResult(source), is(123));
}
@Test
@ -49,7 +50,7 @@ public class ArgumentCommandNodeTest extends AbstractCommandNodeTest {
assertThat(node.parse("123", contextBuilder), is(""));
assertThat(contextBuilder.getArguments().containsKey("foo"), is(true));
assertThat(contextBuilder.getArguments().get("foo").getResult(), is(123));
assertThat(contextBuilder.getArguments().get("foo").getResult(source), is(123));
}
@Test