diff --git a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java index 2abfa295..099559ce 100644 --- a/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java +++ b/spring-shell-core/src/main/java/org/springframework/shell/command/CommandParser.java @@ -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 splitValidValues = options.stream() + .flatMap(o -> { + Stream longs = Stream.of(o.getLongNames()).map(l -> "--" + l); + Stream 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> 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 splitValidValues; + Lexer(String[] args, Set splitValues) { this.args = args; + this.splitValidValues = splitValues; } List> visit() { - return Utils.split(args, t -> t.startsWith("-")); + return Utils.split(args, t -> splitValidValues.contains(t)); } } } diff --git a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserTests.java b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserTests.java index 01614a8b..732a439d 100644 --- a/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserTests.java +++ b/spring-shell-core/src/test/java/org/springframework/shell/command/CommandParserTests.java @@ -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 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