Changed return value of ParameterResolver::resolve to use a ValueResult that contains metadata about the value that was resolved
Added new ValueResultAsserts to facilitate testing of ParameterResolvers
This commit is contained in:
6
pom.xml
6
pom.xml
@@ -21,6 +21,7 @@
|
||||
|
||||
<modules>
|
||||
<module>spring-shell2-core</module>
|
||||
<module>spring-shell2-core-tests</module>
|
||||
<module>spring-shell2-standard</module>
|
||||
<module>spring-shell2-standard-commands</module>
|
||||
<module>spring-shell2-jcommander-adapter</module>
|
||||
@@ -36,6 +37,11 @@
|
||||
<artifactId>spring-shell2-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.shell</groupId>
|
||||
<artifactId>spring-shell2-core-tests</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.shell</groupId>
|
||||
<artifactId>spring-shell2-standard</artifactId>
|
||||
|
||||
27
spring-shell2-core-tests/pom.xml
Normal file
27
spring-shell2-core-tests/pom.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>spring-shell2-core-tests</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.shell</groupId>
|
||||
<artifactId>spring-shell2-parent</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<description>Core API test classes for Spring Shell 2</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.shell</groupId>
|
||||
<artifactId>spring-shell2-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.shell2;
|
||||
|
||||
import org.assertj.core.api.AbstractAssert;
|
||||
import org.assertj.core.api.Assertions;
|
||||
|
||||
/**
|
||||
* Assertions for {@link ValueResult}.
|
||||
*
|
||||
* @author Camilo Gonzalez
|
||||
*/
|
||||
public class ValueResultAsserts extends AbstractAssert<ValueResultAsserts, ValueResult> {
|
||||
|
||||
public ValueResultAsserts(ValueResult actual) {
|
||||
super(actual, ValueResultAsserts.class);
|
||||
}
|
||||
|
||||
public ValueResultAsserts hasValue(Object expectedValue) {
|
||||
isNotNull();
|
||||
Assertions.assertThat(actual.resolvedValue()).isEqualTo(expectedValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueResultAsserts usesWords(int... expectedWordsUsed) {
|
||||
isNotNull();
|
||||
|
||||
Assertions.assertThat(actual.wordsUsed().stream().toArray()).containsExactly(expectedWordsUsed);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueResultAsserts notUsesWords() {
|
||||
isNotNull();
|
||||
Assertions.assertThat(actual.wordsUsed().isEmpty());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueResultAsserts usesWordsForValue(int... expectedWordsUsedForValue) {
|
||||
isNotNull();
|
||||
|
||||
Assertions.assertThat(actual.wordsUsedForValue().stream().toArray()).containsExactly(expectedWordsUsedForValue);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public ValueResultAsserts notUsesWordsForValue() {
|
||||
isNotNull();
|
||||
Assertions.assertThat(actual.wordsUsedForValue().isEmpty());
|
||||
return this;
|
||||
}
|
||||
|
||||
public static ValueResultAsserts assertThat(ValueResult valueResult) {
|
||||
return new ValueResultAsserts(valueResult);
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ public interface ParameterResolver {
|
||||
/**
|
||||
* Turn the given textual input into an actual object, maybe using some conversion or lookup mechanism.
|
||||
*/
|
||||
Object resolve(MethodParameter methodParameter, List<String> words);
|
||||
ValueResult resolve(MethodParameter methodParameter, List<String> words);
|
||||
|
||||
/**
|
||||
* Describe a supported parameter, so that integrated help can be generated.
|
||||
|
||||
@@ -222,7 +222,7 @@ public class Shell implements CommandRegistry {
|
||||
Arrays.fill(args, UNRESOLVED);
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(method, i);
|
||||
args[i] = findResolver(methodParameter).resolve(methodParameter, wordsForArgs);
|
||||
args[i] = findResolver(methodParameter).resolve(methodParameter, wordsForArgs).resolvedValue();
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.shell2;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.naming.spi.ResolveResult;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
|
||||
/**
|
||||
* A {@link ResolveResult} for a successful {@link ParameterResolver#resolve} operation.
|
||||
*
|
||||
* @author Camilo Gonzalez
|
||||
*/
|
||||
public class ValueResult {
|
||||
|
||||
private final MethodParameter methodParameter;
|
||||
|
||||
private final Object resolvedValue;
|
||||
|
||||
private final BitSet wordsUsed;
|
||||
|
||||
private final BitSet wordsUsedForValue;
|
||||
|
||||
public ValueResult(MethodParameter methodParameter, Object resolvedValue) {
|
||||
this(methodParameter, resolvedValue, new BitSet(), new BitSet());
|
||||
}
|
||||
|
||||
public ValueResult(MethodParameter methodParameter, Object resolvedValue, BitSet wordsUsed,
|
||||
BitSet wordsUsedForValue) {
|
||||
|
||||
this.methodParameter = methodParameter;
|
||||
this.resolvedValue = resolvedValue;
|
||||
this.wordsUsed = wordsUsed == null ? new BitSet() : wordsUsed;
|
||||
this.wordsUsedForValue = wordsUsedForValue == null ? new BitSet() : wordsUsedForValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link MethodParameter} that was the target of the {@link ParameterResolver#resolve}
|
||||
* operation.
|
||||
*/
|
||||
public MethodParameter methodParameter() {
|
||||
return methodParameter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the resolved value for the {@link MethodParameter} associated with this result.
|
||||
*/
|
||||
public Object resolvedValue() {
|
||||
return resolvedValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the full set of words used to resolve the {@link MethodParameter}. This includes
|
||||
* any tags/keys consumed from the input.
|
||||
*/
|
||||
public BitSet wordsUsed() {
|
||||
return wordsUsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the full set of words used to resolve the value of this {@link MethodParameter}.
|
||||
*/
|
||||
public BitSet wordsUsedForValue() {
|
||||
return wordsUsedForValue;
|
||||
}
|
||||
|
||||
public List<String> wordsUsed(List<String> words) {
|
||||
return wordsUsed.stream().mapToObj(index -> words.get(index)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<String> wordsUsedForValue(List<String> words) {
|
||||
return wordsUsedForValue.stream().mapToObj(index -> words.get(index)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -52,6 +52,8 @@ public class ShellTest {
|
||||
|
||||
@Mock
|
||||
private ParameterResolver parameterResolver;
|
||||
|
||||
private ValueResult valueResult;
|
||||
|
||||
@InjectMocks
|
||||
private Shell shell;
|
||||
@@ -67,6 +69,8 @@ public class ShellTest {
|
||||
public void commandMatch() throws IOException {
|
||||
when(parameterResolver.supports(any())).thenReturn(true);
|
||||
when(inputProvider.readInput()).thenReturn(() -> "hello world how are you doing ?");
|
||||
valueResult = new ValueResult(null, "test");
|
||||
when(parameterResolver.resolve(any(), any())).thenReturn(valueResult);
|
||||
doThrow(new Exit()).when(resultHandler).handleResult(any());
|
||||
|
||||
shell.methodTargets = Collections.singletonMap("hello world", MethodTarget.of("helloWorld", this, "Say hello"));
|
||||
@@ -102,6 +106,8 @@ public class ShellTest {
|
||||
public void noCommand() throws IOException {
|
||||
when(parameterResolver.supports(any())).thenReturn(true);
|
||||
when(inputProvider.readInput()).thenReturn(() -> "", () -> "hello world how are you doing ?");
|
||||
valueResult = new ValueResult(null, "test");
|
||||
when(parameterResolver.resolve(any(), any())).thenReturn(valueResult);
|
||||
doThrow(new Exit()).when(resultHandler).handleResult(any());
|
||||
|
||||
shell.methodTargets = Collections.singletonMap("hello world", MethodTarget.of("helloWorld", this, "Say hello"));
|
||||
|
||||
@@ -19,7 +19,6 @@ package org.springframework.shell2.jcommander;
|
||||
import static org.springframework.shell2.Utils.unCamelify;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -28,22 +27,22 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.beust.jcommander.DynamicParameter;
|
||||
import com.beust.jcommander.JCommander;
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.beust.jcommander.ParametersDelegate;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.shell2.CompletionContext;
|
||||
import org.springframework.shell2.CompletionProposal;
|
||||
import org.springframework.shell2.ParameterDescription;
|
||||
import org.springframework.shell2.ParameterResolver;
|
||||
import org.springframework.shell2.Utils;
|
||||
import org.springframework.shell2.ValueResult;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import com.beust.jcommander.DynamicParameter;
|
||||
import com.beust.jcommander.JCommander;
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.ParameterException;
|
||||
import com.beust.jcommander.ParametersDelegate;
|
||||
|
||||
/**
|
||||
* Provides integration with JCommander.
|
||||
*
|
||||
@@ -80,10 +79,10 @@ public class JCommanderParameterResolver implements ParameterResolver {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolve(MethodParameter methodParameter, List<String> words) {
|
||||
public ValueResult resolve(MethodParameter methodParameter, List<String> words) {
|
||||
JCommander jCommander = createJCommander(methodParameter);
|
||||
jCommander.parse(words.toArray(new String[words.size()]));
|
||||
return jCommander.getObjects().get(0);
|
||||
return new ValueResult(methodParameter, jCommander.getObjects().get(0));
|
||||
}
|
||||
|
||||
private JCommander createJCommander(MethodParameter methodParameter) {
|
||||
|
||||
@@ -63,7 +63,9 @@ public class JCommanderParameterResolverTest {
|
||||
public void testPojoValuesAreCorrectlySet() {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(COMMAND_METHOD, 0);
|
||||
|
||||
FieldCollins resolved = (FieldCollins) resolver.resolve(methodParameter, asList("--name foo -level 2 something-else yet-something-else".split(" ")));
|
||||
FieldCollins resolved = (FieldCollins) resolver
|
||||
.resolve(methodParameter, asList("--name foo -level 2 something-else yet-something-else".split(" ")))
|
||||
.resolvedValue();
|
||||
|
||||
assertThat(resolved.getName()).isEqualTo("foo");
|
||||
assertThat(resolved.getLevel()).isEqualTo(2);
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.shell</groupId>
|
||||
<artifactId>spring-shell2-core-tests</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.shell2.legacy;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -36,6 +37,7 @@ import org.springframework.shell2.CompletionContext;
|
||||
import org.springframework.shell2.CompletionProposal;
|
||||
import org.springframework.shell2.ParameterDescription;
|
||||
import org.springframework.shell2.ParameterResolver;
|
||||
import org.springframework.shell2.ValueResult;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -64,21 +66,23 @@ public class LegacyParameterResolver implements ParameterResolver {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolve(MethodParameter methodParameter, List<String> words) {
|
||||
public ValueResult resolve(MethodParameter methodParameter, List<String> words) {
|
||||
CliOption cliOption = methodParameter.getParameterAnnotation(CliOption.class);
|
||||
Optional<Converter<?>> converter = converters.stream()
|
||||
.filter(c -> c.supports(methodParameter.getParameterType(), cliOption.optionContext()))
|
||||
.findFirst();
|
||||
|
||||
Map<String, String> values = parseOptions(words);
|
||||
Map<String, Object> seenValues = convertValues(values, methodParameter, converter);
|
||||
Map<String, ParseResult> values = parseOptions(words);
|
||||
Map<String, ValueResult> seenValues = convertValues(values, methodParameter, converter);
|
||||
switch (seenValues.size()) {
|
||||
case 0:
|
||||
if (!cliOption.mandatory()) {
|
||||
String value = cliOption.unspecifiedDefaultValue();
|
||||
return converter
|
||||
Object resolvedValue = converter
|
||||
.orElseThrow(noConverterFound(cliOption.key()[0], value, methodParameter.getParameterType()))
|
||||
.convertFromText(value, methodParameter.getParameterType(), cliOption.optionContext());
|
||||
|
||||
return new ValueResult(methodParameter, resolvedValue);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Could not find parameter values for " + prettifyKeys(Arrays.asList(cliOption.key())) + " in " + words);
|
||||
@@ -117,38 +121,49 @@ public class LegacyParameterResolver implements ParameterResolver {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<String, String> parseOptions(List<String> words) {
|
||||
Map<String, String> values = new HashMap<>();
|
||||
private Map<String, ParseResult> parseOptions(List<String> words) {
|
||||
Map<String, ParseResult> values = new HashMap<>();
|
||||
for (int i = 0; i < words.size(); i++) {
|
||||
int from = i;
|
||||
String word = words.get(i);
|
||||
if (word.startsWith("--")) {
|
||||
String key = word.substring("--".length());
|
||||
if (word.startsWith(CLI_PREFIX)) {
|
||||
String key = word.substring(CLI_PREFIX.length());
|
||||
// If next word doesn't exist or starts with '--', this is an unary option. Store null
|
||||
String value = i < words.size() - 1 && !words.get(i + 1).startsWith("--") ? words.get(++i) : null;
|
||||
Assert.isTrue(!values.containsKey(key), String.format("Option --%s has already been set", key));
|
||||
values.put(key, value);
|
||||
String value = i < words.size() - 1 && !words.get(i + 1).startsWith(CLI_PREFIX) ? words.get(++i) : null;
|
||||
Assert.isTrue(!values.containsKey(key), String.format("Option %s%s has already been set", CLI_PREFIX, key));
|
||||
values.put(key, new ParseResult(value, from));
|
||||
} // Must be the 'anonymous' option
|
||||
else {
|
||||
Assert.isTrue(!values.containsKey(""), "Anonymous option has already been set");
|
||||
values.put("", word);
|
||||
values.put("", new ParseResult(word, from));
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
private Map<String, Object> convertValues(Map<String, String> values, MethodParameter methodParameter, Optional<Converter<?>> converter) {
|
||||
Map<String, Object> seenValues = new HashMap<>();
|
||||
private Map<String, ValueResult> convertValues(Map<String, ParseResult> values, MethodParameter methodParameter, Optional<Converter<?>> converter) {
|
||||
Map<String, ValueResult> seenValues = new HashMap<>();
|
||||
CliOption option = methodParameter.getParameterAnnotation(CliOption.class);
|
||||
for (String key : option.key()) {
|
||||
if (values.containsKey(key)) {
|
||||
String value = values.get(key);
|
||||
ParseResult parseResult = values.get(key);
|
||||
String value = parseResult.value;
|
||||
if (value == null && !CLI_OPTION_NULL.equals(option.specifiedDefaultValue())) {
|
||||
value = option.specifiedDefaultValue();
|
||||
}
|
||||
Class<?> parameterType = methodParameter.getParameterType();
|
||||
seenValues.put(key, converter
|
||||
Object resolvedValue = converter
|
||||
.orElseThrow(noConverterFound(key, value, parameterType))
|
||||
.convertFromText(value, parameterType, option.optionContext()));
|
||||
.convertFromText(value, parameterType, option.optionContext());
|
||||
int from = parseResult.from;
|
||||
int to = key.isEmpty() || parseResult.value == null ? from : from + 1;
|
||||
BitSet wordsUsed = new BitSet();
|
||||
wordsUsed.set(from, to + 1);
|
||||
BitSet wordsUsedForValues = new BitSet();
|
||||
if (parseResult.value != null) {
|
||||
wordsUsedForValues.set(to);
|
||||
}
|
||||
seenValues.put(key, new ValueResult(methodParameter, resolvedValue, wordsUsed, wordsUsedForValues));
|
||||
}
|
||||
}
|
||||
return seenValues;
|
||||
@@ -158,11 +173,23 @@ public class LegacyParameterResolver implements ParameterResolver {
|
||||
* Return the list of possible keys for an option, suitable for displaying in an error message.
|
||||
*/
|
||||
private String prettifyKeys(Collection<String> keys) {
|
||||
return keys.stream().map(s -> "".equals(s) ? "<anonymous>" : "--" + s).collect(Collectors.joining(", ", "[", "]"));
|
||||
return keys.stream().map(s -> "".equals(s) ? "<anonymous>" : CLI_PREFIX + s).collect(Collectors.joining(", ", "[", "]"));
|
||||
}
|
||||
|
||||
private Supplier<IllegalStateException> noConverterFound(String key, String value, Class<?> parameterType) {
|
||||
return () -> new IllegalStateException("No converter found for --" + key + " from '" + value + "' to type " + parameterType);
|
||||
return () -> new IllegalStateException("No converter found for " + CLI_PREFIX + key + " from '" + value + "' to type " + parameterType);
|
||||
}
|
||||
|
||||
private static class ParseResult {
|
||||
private final String value;
|
||||
|
||||
private final Integer from;
|
||||
|
||||
public ParseResult(String value, Integer from) {
|
||||
this.value = value;
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@ package org.springframework.shell2.legacy;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.shell2.ValueResultAsserts.assertThat;
|
||||
import static org.springframework.shell2.legacy.LegacyCommands.REGISTER_METHOD;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -37,6 +37,7 @@ import org.springframework.shell.core.annotation.CliOption;
|
||||
import org.springframework.shell2.ParameterDescription;
|
||||
import org.springframework.shell2.ParameterResolver;
|
||||
import org.springframework.shell2.Utils;
|
||||
import org.springframework.shell2.ValueResult;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -68,47 +69,46 @@ public class LegacyParameterResolverTest {
|
||||
public void resolvesParameterAnnotatedWithCliOption() throws Exception {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(REGISTER_METHOD, NAME_OR_ANONYMOUS);
|
||||
|
||||
Object result = resolve(methodParameter, "--foo bar --name baz --qix bux");
|
||||
|
||||
assertThat(result).isEqualTo("baz");
|
||||
assertThat(resolve(methodParameter, "--foo bar --name baz --qix bux")).hasValue("baz").usesWords(2, 3)
|
||||
.usesWordsForValue(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvesAnonymousParameterAnnotatedWithCliOption() throws Exception {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(REGISTER_METHOD, NAME_OR_ANONYMOUS);
|
||||
|
||||
Object result = resolve(methodParameter, "--foo bar baz --qix bux");
|
||||
assertThat(result).isEqualTo("baz");
|
||||
assertThat(resolve(methodParameter, "--foo bar baz --qix bux")).hasValue("baz").usesWords(2)
|
||||
.usesWordsForValue(2);
|
||||
|
||||
// As first param
|
||||
result = resolve(methodParameter, "baz --foo bar --qix bux");
|
||||
assertThat(result).isEqualTo("baz");
|
||||
assertThat(resolve(methodParameter, "baz --foo bar --qix bux")).hasValue("baz").usesWords(0)
|
||||
.usesWordsForValue(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usesLegacyConverters() throws Exception {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(REGISTER_METHOD, TYPE);
|
||||
|
||||
Object result = resolve(methodParameter, "--foo bar --name baz --qix bux --type processor");
|
||||
|
||||
assertThat(result).isSameAs(ArtifactType.processor);
|
||||
assertThat(resolve(methodParameter, "--foo bar --name baz --qix bux --type processor"))
|
||||
.hasValue(ArtifactType.processor).usesWords(6, 7).usesWordsForValue(7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnspecifiedDefaultValue() throws Exception {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(REGISTER_METHOD, FORCE);
|
||||
|
||||
Object result = resolve(methodParameter, "--foo bar --name baz --qix bux");
|
||||
|
||||
assertThat(result).isEqualTo(false);
|
||||
assertThat(resolve(methodParameter, "--foo bar --name baz --qix bux"))
|
||||
.hasValue(false).notUsesWords().notUsesWordsForValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpecifiedDefaultValue() throws Exception {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(REGISTER_METHOD, FORCE);
|
||||
|
||||
assertThat(resolve(methodParameter, "--force --foo bar --name baz --qix bux")).isEqualTo(true);
|
||||
assertThat(resolve(methodParameter, "--foo bar --name baz --qix bux --force")).isEqualTo(true);
|
||||
assertThat(resolve(methodParameter, "--force --foo bar --name baz --qix bux"))
|
||||
.hasValue(true).usesWords(0).notUsesWordsForValue();
|
||||
|
||||
assertThat(resolve(methodParameter, "--foo bar --name baz --qix bux --force"))
|
||||
.hasValue(true).usesWords(6).notUsesWordsForValue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -116,7 +116,8 @@ public class LegacyParameterResolverTest {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(REGISTER_METHOD, COORDINATES);
|
||||
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.expectMessage("Could not find parameter values for [--coordinates, --coords] in [--force, --foo, bar, --name, baz, --qix, bux]");
|
||||
thrown.expectMessage(
|
||||
"Could not find parameter values for [--coordinates, --coords] in [--force, --foo, bar, --name, baz, --qix, bux]");
|
||||
resolve(methodParameter, "--force --foo bar --name baz --qix bux");
|
||||
}
|
||||
|
||||
@@ -155,101 +156,102 @@ public class LegacyParameterResolverTest {
|
||||
thrown.expectMessage("No converter found for --v2 from '42' to type int");
|
||||
resolve(methodParameter, "--v1 1 --v2");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDescribeBothDefaultsNotDeclared() {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(LegacyCommands.REGISTER_METHOD, 1);
|
||||
|
||||
|
||||
ParameterDescription description = parameterResolver.describe(methodParameter).findFirst().get();
|
||||
|
||||
|
||||
assertThat(description.keys()).containsExactly("--type");
|
||||
assertThat(description.formal()).isEqualTo(Utils.unCamelify(ArtifactType.class.getSimpleName()));
|
||||
assertThat(description.defaultValue().isPresent()).isFalse();
|
||||
assertThat(description.mandatoryKey()).isTrue();
|
||||
|
||||
|
||||
String expectedHelp = methodParameter.getParameterAnnotation(CliOption.class).help();
|
||||
assertThat(description.help()).isEqualTo(expectedHelp);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDescribeBothDefaultsDeclared() {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(LegacyCommands.SOME_METHOD, 1);
|
||||
|
||||
|
||||
ParameterDescription description = parameterResolver.describe(methodParameter).findFirst().get();
|
||||
|
||||
|
||||
assertThat(description.keys()).containsExactly("--option");
|
||||
assertThat(description.formal()).isEqualTo(boolean.class.getName());
|
||||
assertThat(description.defaultValue().get()).isEqualTo("false");
|
||||
assertThat(description.defaultValueWhenFlag().get()).isEqualTo("true");
|
||||
assertThat(description.mandatoryKey()).isTrue();
|
||||
|
||||
|
||||
String expectedHelp = methodParameter.getParameterAnnotation(CliOption.class).help();
|
||||
assertThat(description.help()).isEqualTo(expectedHelp);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDescribeOnlySpecifiedDefaultDeclared() {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(LegacyCommands.SUM_METHOD, 1);
|
||||
|
||||
|
||||
ParameterDescription description = parameterResolver.describe(methodParameter).findFirst().get();
|
||||
|
||||
|
||||
assertThat(description.keys()).containsExactly("--v2");
|
||||
assertThat(description.formal()).isEqualTo(int.class.getName());
|
||||
assertThat(description.defaultValue().get()).isEqualTo("null");
|
||||
assertThat(description.defaultValueWhenFlag().get()).isEqualTo("42");
|
||||
assertThat(description.mandatoryKey()).isTrue();
|
||||
|
||||
String expectedHelp = methodParameter.getParameterAnnotation(CliOption.class).help();
|
||||
assertThat(description.help()).isEqualTo(expectedHelp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDescribeOnlyUnspecifiedDefaultDeclared() {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(LegacyCommands.SUM_METHOD, 0);
|
||||
|
||||
ParameterDescription description = parameterResolver.describe(methodParameter).findFirst().get();
|
||||
|
||||
assertThat(description.keys()).containsExactly("--v1");
|
||||
assertThat(description.formal()).isEqualTo(int.class.getName());
|
||||
assertThat(description.defaultValue().get()).isEqualTo("38");
|
||||
assertThat(description.mandatoryKey()).isTrue();
|
||||
|
||||
String expectedHelp = methodParameter.getParameterAnnotation(CliOption.class).help();
|
||||
assertThat(description.help()).isEqualTo(expectedHelp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDescribeDefaultKey() {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(LegacyCommands.LEGACY_ECHO_METHOD, 0);
|
||||
|
||||
ParameterDescription description = parameterResolver.describe(methodParameter).findFirst().get();
|
||||
|
||||
assertThat(description.keys()).isEmpty();
|
||||
assertThat(description.formal()).isEqualTo(Utils.unCamelify(String.class.getSimpleName()));
|
||||
assertThat(description.defaultValue().isPresent()).isFalse();
|
||||
assertThat(description.mandatoryKey()).isFalse();
|
||||
|
||||
String expectedHelp = methodParameter.getParameterAnnotation(CliOption.class).help();
|
||||
assertThat(description.help()).isEqualTo(expectedHelp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDescribeNonMandatoryNoDefaults() {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(LegacyCommands.SOME_METHOD, 0);
|
||||
|
||||
ParameterDescription description = parameterResolver.describe(methodParameter).findFirst().get();
|
||||
|
||||
assertThat(description.keys()).containsExactly("--key");
|
||||
assertThat(description.formal()).isEqualTo(Utils.unCamelify(String.class.getSimpleName()));
|
||||
assertThat(description.defaultValue().get()).isEqualTo("null");
|
||||
assertThat(description.mandatoryKey()).isTrue();
|
||||
|
||||
|
||||
String expectedHelp = methodParameter.getParameterAnnotation(CliOption.class).help();
|
||||
assertThat(description.help()).isEqualTo(expectedHelp);
|
||||
}
|
||||
|
||||
private Object resolve(MethodParameter methodParameter, String command) {
|
||||
return parameterResolver.resolve(methodParameter, asList(command.split(" ")));
|
||||
@Test
|
||||
public void testDescribeOnlyUnspecifiedDefaultDeclared() {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(LegacyCommands.SUM_METHOD, 0);
|
||||
|
||||
ParameterDescription description = parameterResolver.describe(methodParameter).findFirst().get();
|
||||
|
||||
assertThat(description.keys()).containsExactly("--v1");
|
||||
assertThat(description.formal()).isEqualTo(int.class.getName());
|
||||
assertThat(description.defaultValue().get()).isEqualTo("38");
|
||||
assertThat(description.mandatoryKey()).isTrue();
|
||||
|
||||
String expectedHelp = methodParameter.getParameterAnnotation(CliOption.class).help();
|
||||
assertThat(description.help()).isEqualTo(expectedHelp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDescribeDefaultKey() {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(LegacyCommands.LEGACY_ECHO_METHOD, 0);
|
||||
|
||||
ParameterDescription description = parameterResolver.describe(methodParameter).findFirst().get();
|
||||
|
||||
assertThat(description.keys()).isEmpty();
|
||||
assertThat(description.formal()).isEqualTo(Utils.unCamelify(String.class.getSimpleName()));
|
||||
assertThat(description.defaultValue().isPresent()).isFalse();
|
||||
assertThat(description.mandatoryKey()).isFalse();
|
||||
|
||||
String expectedHelp = methodParameter.getParameterAnnotation(CliOption.class).help();
|
||||
assertThat(description.help()).isEqualTo(expectedHelp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDescribeNonMandatoryNoDefaults() {
|
||||
MethodParameter methodParameter = Utils.createMethodParameter(LegacyCommands.SOME_METHOD, 0);
|
||||
|
||||
ParameterDescription description = parameterResolver.describe(methodParameter).findFirst().get();
|
||||
|
||||
assertThat(description.keys()).containsExactly("--key");
|
||||
assertThat(description.formal()).isEqualTo(Utils.unCamelify(String.class.getSimpleName()));
|
||||
assertThat(description.defaultValue().get()).isEqualTo("null");
|
||||
assertThat(description.mandatoryKey()).isTrue();
|
||||
|
||||
String expectedHelp = methodParameter.getParameterAnnotation(CliOption.class).help();
|
||||
assertThat(description.help()).isEqualTo(expectedHelp);
|
||||
}
|
||||
|
||||
private ValueResult resolve(MethodParameter methodParameter, String command) {
|
||||
ValueResult result = parameterResolver.resolve(methodParameter, asList(command.split(" ")));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -17,16 +17,19 @@
|
||||
<groupId>org.springframework.shell</groupId>
|
||||
<artifactId>spring-shell2-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.shell</groupId>
|
||||
<artifactId>spring-shell2-core-tests</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,11 +16,14 @@
|
||||
|
||||
package org.springframework.shell2.standard;
|
||||
|
||||
import static org.springframework.shell2.Utils.unCamelify;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -44,13 +47,12 @@ import org.springframework.shell2.ParameterMissingResolutionException;
|
||||
import org.springframework.shell2.ParameterResolver;
|
||||
import org.springframework.shell2.UnfinishedParameterResolutionException;
|
||||
import org.springframework.shell2.Utils;
|
||||
import org.springframework.shell2.ValueResult;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import static org.springframework.shell2.Utils.unCamelify;
|
||||
|
||||
/**
|
||||
* Default ParameterResolver implementation that supports the following features:<ul>
|
||||
* <li>named parameters (recognized because they start with some {@link ShellMethod#prefix()})</li>
|
||||
@@ -73,6 +75,7 @@ import static org.springframework.shell2.Utils.unCamelify;
|
||||
* if needed.</p>
|
||||
* @author Eric Bottard
|
||||
* @author Florent Biville
|
||||
* @author Camilo Gonzalez
|
||||
*/
|
||||
@Component
|
||||
public class StandardParameterResolver implements ParameterResolver {
|
||||
@@ -105,7 +108,7 @@ public class StandardParameterResolver implements ParameterResolver {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolve(MethodParameter methodParameter, List<String> words) {
|
||||
public ValueResult resolve(MethodParameter methodParameter, List<String> words) {
|
||||
String prefix = prefixForMethod(methodParameter.getMethod());
|
||||
|
||||
CacheKey cacheKey = new CacheKey(methodParameter.getMethod(), words);
|
||||
@@ -113,12 +116,15 @@ public class StandardParameterResolver implements ParameterResolver {
|
||||
|
||||
Map<Parameter, ParameterRawValue> result = new HashMap<>();
|
||||
Map<String, String> namedParameters = new HashMap<>();
|
||||
List<String> positionalValues = new ArrayList<>();
|
||||
|
||||
// index of words that haven't yet been used to resolve parameter values
|
||||
List<Integer> unusedWords = new ArrayList<>();
|
||||
|
||||
Set<String> possibleKeys = gatherAllPossibleKeys(methodParameter.getMethod());
|
||||
|
||||
// First, resolve all parameters passed by-name
|
||||
for (int i = 0; i < words.size(); i++) {
|
||||
int from = i;
|
||||
String word = words.get(i);
|
||||
if (possibleKeys.contains(word)) {
|
||||
String key = word;
|
||||
@@ -133,16 +139,17 @@ public class StandardParameterResolver implements ParameterResolver {
|
||||
String raw = words.subList(i + 1, i + 1 + arity).stream().collect(Collectors.joining(","));
|
||||
Assert.isTrue(!namedParameters.containsKey(key), String.format("Parameter for '%s' has already been specified", word));
|
||||
namedParameters.put(key, raw);
|
||||
result.put(parameter, ParameterRawValue.explicit(raw, key));
|
||||
i += arity;
|
||||
if (arity == 0) {
|
||||
boolean defaultValue = booleanDefaultValue(parameter);
|
||||
// Boolean parameter has been specified. Use the opposite of the default value
|
||||
result.put(parameter, ParameterRawValue.explicit(String.valueOf(!defaultValue), key));
|
||||
result.put(parameter, ParameterRawValue.explicit(String.valueOf(!defaultValue), key, from, from));
|
||||
} else {
|
||||
i += arity;
|
||||
result.put(parameter, ParameterRawValue.explicit(raw, key, from, i));
|
||||
}
|
||||
} // store for later processing of positional params
|
||||
else {
|
||||
positionalValues.add(word);
|
||||
unusedWords.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,14 +164,18 @@ public class StandardParameterResolver implements ParameterResolver {
|
||||
copy.retainAll(namedParameters.keySet());
|
||||
if (copy.isEmpty()) { // Was not set via a key (including aliases), must be positional
|
||||
int arity = getArity(parameter);
|
||||
if (arity > 0 && (offset + arity) <= positionalValues.size()) {
|
||||
String raw = positionalValues.subList(offset, offset + arity).stream().collect(Collectors.joining(","));
|
||||
result.put(parameter, ParameterRawValue.explicit(raw, null));
|
||||
if (arity > 0 && (offset + arity) <= unusedWords.size()) {
|
||||
String raw = unusedWords.subList(offset, offset + arity).stream()
|
||||
.map(index -> words.get(index))
|
||||
.collect(Collectors.joining(","));
|
||||
int from = unusedWords.get(offset);
|
||||
int to = from + arity - 1;
|
||||
result.put(parameter, ParameterRawValue.explicit(raw, null, from, to));
|
||||
offset += arity;
|
||||
} // No more input. Try defaultValues
|
||||
else {
|
||||
Optional<String> defaultValue = defaultValueFor(parameter);
|
||||
defaultValue.ifPresent(value -> result.put(parameter, ParameterRawValue.implicit(value, null)));
|
||||
defaultValue.ifPresent(value -> result.put(parameter, ParameterRawValue.implicit(value, null, null, null)));
|
||||
}
|
||||
}
|
||||
else if (copy.size() > 1) {
|
||||
@@ -172,8 +183,10 @@ public class StandardParameterResolver implements ParameterResolver {
|
||||
}
|
||||
}
|
||||
|
||||
Assert.isTrue(offset == positionalValues.size(), "Too many arguments: the following could not be mapped to parameters: "
|
||||
+ positionalValues.subList(offset, positionalValues.size()).stream().collect(Collectors.joining(" ", "'", "'")));
|
||||
Assert.isTrue(offset == unusedWords.size(),
|
||||
"Too many arguments: the following could not be mapped to parameters: "
|
||||
+ unusedWords.subList(offset, unusedWords.size()).stream()
|
||||
.map(index -> words.get(index)).collect(Collectors.joining(" ", "'", "'")));
|
||||
return result;
|
||||
});
|
||||
|
||||
@@ -182,7 +195,31 @@ public class StandardParameterResolver implements ParameterResolver {
|
||||
throw new ParameterMissingResolutionException(describe(methodParameter).findFirst().get());
|
||||
}
|
||||
ParameterRawValue parameterRawValue = resolved.get(param);
|
||||
return convertRawValue(parameterRawValue, methodParameter);
|
||||
Object value = convertRawValue(parameterRawValue, methodParameter);
|
||||
BitSet wordsUsed = getWordsUsed(parameterRawValue);
|
||||
BitSet wordsUsedForValue = getWordsUsedForValue(parameterRawValue);
|
||||
return new ValueResult(methodParameter, value, wordsUsed, wordsUsedForValue);
|
||||
}
|
||||
|
||||
private BitSet getWordsUsed(ParameterRawValue parameterRawValue) {
|
||||
if (parameterRawValue.from != null) {
|
||||
BitSet wordsUsed = new BitSet();
|
||||
wordsUsed.set(parameterRawValue.from, parameterRawValue.to + 1);
|
||||
return wordsUsed;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private BitSet getWordsUsedForValue(ParameterRawValue parameterRawValue) {
|
||||
if (parameterRawValue.from != null) {
|
||||
BitSet wordsUsedForValue = new BitSet();
|
||||
wordsUsedForValue.set(parameterRawValue.from, parameterRawValue.to + 1);
|
||||
if (parameterRawValue.key != null) {
|
||||
wordsUsedForValue.clear(parameterRawValue.from);
|
||||
}
|
||||
return wordsUsedForValue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object convertRawValue(ParameterRawValue parameterRawValue, MethodParameter methodParameter) {
|
||||
@@ -438,9 +475,9 @@ public class StandardParameterResolver implements ParameterResolver {
|
||||
|
||||
private CompletionContext context;
|
||||
|
||||
private int from;
|
||||
private Integer from;
|
||||
|
||||
private int to;
|
||||
private Integer to;
|
||||
|
||||
private Integer keyIndex;
|
||||
|
||||
@@ -459,18 +496,20 @@ public class StandardParameterResolver implements ParameterResolver {
|
||||
*/
|
||||
private final String key;
|
||||
|
||||
private ParameterRawValue(String value, boolean explicit, String key) {
|
||||
private ParameterRawValue(String value, boolean explicit, String key, Integer from, Integer to) {
|
||||
this.value = value;
|
||||
this.explicit = explicit;
|
||||
this.key = key;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public static ParameterRawValue explicit(String value, String key) {
|
||||
return new ParameterRawValue(value, true, key);
|
||||
public static ParameterRawValue explicit(String value, String key, Integer from, Integer to) {
|
||||
return new ParameterRawValue(value, true, key, from, to);
|
||||
}
|
||||
|
||||
public static ParameterRawValue implicit(String value, String key) {
|
||||
return new ParameterRawValue(value, false, key);
|
||||
public static ParameterRawValue implicit(String value, String key, Integer from, Integer to) {
|
||||
return new ParameterRawValue(value, false, key, from, to);
|
||||
}
|
||||
|
||||
public boolean positional() {
|
||||
@@ -480,10 +519,12 @@ public class StandardParameterResolver implements ParameterResolver {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ParameterRawValue{" +
|
||||
"value='" + value + '\'' +
|
||||
", explicit=" + explicit +
|
||||
", key='" + key + '\'' +
|
||||
'}';
|
||||
"value='" + value + '\'' +
|
||||
", explicit=" + explicit +
|
||||
", key='" + key + '\'' +
|
||||
", from=" + from +
|
||||
", to=" + to +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
|
||||
package org.springframework.shell2.standard;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.shell2.ValueResultAsserts.assertThat;
|
||||
import static org.springframework.util.ReflectionUtils.findMethod;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -25,18 +31,13 @@ import org.jline.reader.impl.DefaultParser;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.shell2.CompletionContext;
|
||||
import org.springframework.shell2.CompletionProposal;
|
||||
import org.springframework.shell2.ParameterMissingResolutionException;
|
||||
import org.springframework.shell2.UnfinishedParameterResolutionException;
|
||||
import org.springframework.shell2.Utils;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.util.ReflectionUtils.findMethod;
|
||||
import org.springframework.shell2.ValueResult;
|
||||
|
||||
/**
|
||||
* Unit tests for DefaultParameterResolver.
|
||||
@@ -56,33 +57,31 @@ public class StandardParameterResolverTest {
|
||||
public void testParses() throws Exception {
|
||||
Method method = findMethod(Remote.class, "zap", boolean.class, String.class, String.class, String.class);
|
||||
|
||||
assertThat(resolver.resolve(
|
||||
Utils.createMethodParameter(method, 0),
|
||||
asList("--force --name --foo y".split(" "))
|
||||
)).isEqualTo(true);
|
||||
assertThat(resolver.resolve(
|
||||
Utils.createMethodParameter(method, 1),
|
||||
asList("--force --name --foo y".split(" "))
|
||||
)).isEqualTo("--foo");
|
||||
assertThat(resolver.resolve(
|
||||
Utils.createMethodParameter(method, 2),
|
||||
asList("--force --name --foo y".split(" "))
|
||||
)).isEqualTo("y");
|
||||
assertThat(resolver.resolve(
|
||||
Utils.createMethodParameter(method, 3),
|
||||
asList("--force --name --foo y".split(" "))
|
||||
)).isEqualTo("last");
|
||||
|
||||
List<String> words = asList("--force --name --foo y".split(" "));
|
||||
ValueResult result0 = resolver.resolve(Utils.createMethodParameter(method, 0), words);
|
||||
assertThat(result0).hasValue(true).usesWords(0).notUsesWordsForValue();
|
||||
assertThat(result0.wordsUsed(words)).containsExactly("--force");
|
||||
|
||||
ValueResult result1 = resolver.resolve(Utils.createMethodParameter(method, 1), words);
|
||||
assertThat(result1).hasValue("--foo").usesWords(1, 2).usesWordsForValue(2);
|
||||
assertThat(result1.wordsUsed(words)).containsExactly("--name", "--foo");
|
||||
assertThat(result1.wordsUsedForValue(words)).containsExactly("--foo");
|
||||
|
||||
ValueResult result2 = resolver.resolve(Utils.createMethodParameter(method, 2), words);
|
||||
assertThat(result2).hasValue("y").usesWords(3).usesWordsForValue(3);
|
||||
assertThat(result2.wordsUsed(words)).containsExactly("y");
|
||||
|
||||
ValueResult result3 = resolver.resolve(Utils.createMethodParameter(method, 3), words);
|
||||
assertThat(result3).hasValue("last").notUsesWords().notUsesWordsForValue();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParsesWithMethodPrefix() throws Exception {
|
||||
Method method = findMethod(Remote.class, "prefixTest", String.class);
|
||||
|
||||
assertThat(resolver.resolve(
|
||||
Utils.createMethodParameter(method, 0),
|
||||
asList("-message abc".split(" "))
|
||||
)).isEqualTo("abc");
|
||||
ValueResult result = resolver.resolve(Utils.createMethodParameter(method, 0),
|
||||
asList("-message abc".split(" ")));
|
||||
assertThat(result).hasValue("abc").usesWords(0, 1).usesWordsForValue(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -244,8 +243,6 @@ public class StandardParameterResolverTest {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private CompletionContext contextFor(String input) {
|
||||
DefaultParser defaultParser = new DefaultParser();
|
||||
ParsedLine parsed = defaultParser.parse(input, input.length());
|
||||
|
||||
Reference in New Issue
Block a user