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:
Janne Valkealahti
2023-02-01 09:29:20 +00:00
parent 3ce7afac6b
commit 809e296e55
2 changed files with 47 additions and 4 deletions

View File

@@ -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));
}
}
}

View File

@@ -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