Handle arg looking options better
- Now lexing better with valid options - Only report unrecognised option with double dash as current parser don't have structure to do deeper analysis. - Fixes #651
This commit is contained in:
@@ -22,6 +22,7 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -213,7 +214,15 @@ public interface CommandParser {
|
||||
.filter(o -> o.isRequired())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Lexer lexer = new Lexer(args);
|
||||
Set<String> splitValidValues = options.stream()
|
||||
.flatMap(o -> {
|
||||
Stream<String> longs = Stream.of(o.getLongNames()).map(l -> "--" + l);
|
||||
Stream<String> shorts = Stream.of(o.getShortNames()).map(s -> "-"+ Character.toString(s));
|
||||
return Stream.concat(longs, shorts);
|
||||
})
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Lexer lexer = new Lexer(args, splitValidValues);
|
||||
List<List<String>> lexerResults = lexer.visit();
|
||||
Parser parser = new Parser();
|
||||
ParserResults parserResults = parser.visit(lexerResults, options);
|
||||
@@ -228,7 +237,7 @@ public interface CommandParser {
|
||||
}
|
||||
else {
|
||||
for (String arg : pr.args) {
|
||||
if (arg.startsWith("-")) {
|
||||
if (arg.startsWith("--")) {
|
||||
errors.add(UnrecognisedOptionException.of(String.format("Unrecognised option '%s'", arg),
|
||||
arg));
|
||||
}
|
||||
@@ -520,11 +529,13 @@ public interface CommandParser {
|
||||
*/
|
||||
private static class Lexer {
|
||||
private final String[] args;
|
||||
Lexer(String[] args) {
|
||||
private final Set<String> splitValidValues;
|
||||
Lexer(String[] args, Set<String> splitValues) {
|
||||
this.args = args;
|
||||
this.splitValidValues = splitValues;
|
||||
}
|
||||
List<List<String>> visit() {
|
||||
return Utils.split(args, t -> t.startsWith("-"));
|
||||
return Utils.split(args, t -> splitValidValues.contains(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,8 +26,10 @@ import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.shell.command.CommandParser.CommandParserResults;
|
||||
import org.springframework.shell.command.CommandParser.MissingOptionException;
|
||||
import org.springframework.shell.command.CommandParser.NotEnoughArgumentsOptionException;
|
||||
import org.springframework.shell.command.CommandParser.TooManyArgumentsOptionException;
|
||||
import org.springframework.shell.command.CommandParser.UnrecognisedOptionException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -496,6 +498,11 @@ public class CommandParserTests extends AbstractCommandTests {
|
||||
CommandParserResults results = parser.parse(options, args);
|
||||
assertThat(results.results()).hasSize(0);
|
||||
assertThat(results.errors()).hasSize(1);
|
||||
assertThat(results.errors()).satisfiesExactly(
|
||||
e -> {
|
||||
assertThat(e).isInstanceOf(UnrecognisedOptionException.class);
|
||||
}
|
||||
);
|
||||
assertThat(results.positional()).hasSize(1);
|
||||
}
|
||||
|
||||
@@ -508,6 +515,11 @@ public class CommandParserTests extends AbstractCommandTests {
|
||||
CommandParserResults results = parser.parse(options, args);
|
||||
assertThat(results.results()).hasSize(1);
|
||||
assertThat(results.errors()).hasSize(1);
|
||||
assertThat(results.errors()).satisfiesExactly(
|
||||
e -> {
|
||||
assertThat(e).isInstanceOf(UnrecognisedOptionException.class);
|
||||
}
|
||||
);
|
||||
assertThat(results.positional()).hasSize(1);
|
||||
}
|
||||
|
||||
@@ -520,9 +532,29 @@ public class CommandParserTests extends AbstractCommandTests {
|
||||
CommandParserResults results = parser.parse(options, args);
|
||||
assertThat(results.results()).hasSize(0);
|
||||
assertThat(results.errors()).hasSize(2);
|
||||
assertThat(results.errors()).satisfiesExactly(
|
||||
e -> {
|
||||
assertThat(e).isInstanceOf(UnrecognisedOptionException.class);
|
||||
},
|
||||
e -> {
|
||||
assertThat(e).isInstanceOf(MissingOptionException.class);
|
||||
}
|
||||
);
|
||||
assertThat(results.positional()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDashOptionValueDoNotError() {
|
||||
// gh-651
|
||||
CommandOption option1 = longOption("arg1");
|
||||
List<CommandOption> options = Arrays.asList(option1);
|
||||
String[] args = new String[]{"--arg1", "-1"};
|
||||
CommandParserResults results = parser.parse(options, args);
|
||||
assertThat(results.results()).hasSize(1);
|
||||
assertThat(results.errors()).hasSize(0);
|
||||
assertThat(results.positional()).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPositionDoesNotAffectRequiredErrorWithOtherErrors() {
|
||||
// gh-601
|
||||
|
||||
Reference in New Issue
Block a user