diff --git a/src/main/java/picocli/CommandLine.java b/src/main/java/picocli/CommandLine.java index feb32e8b2..2a84f2ad0 100644 --- a/src/main/java/picocli/CommandLine.java +++ b/src/main/java/picocli/CommandLine.java @@ -14326,10 +14326,10 @@ private void consumeMapArguments(ArgSpec argSpec, alreadyUnquoted = false; } // now process the varargs if any - String fallback = consumed == 0 && argSpec.isOption() && !OptionSpec.DEFAULT_FALLBACK_VALUE.equals(((OptionSpec) argSpec).fallbackValue()) + String fallback = argSpec.isOption() && !OptionSpec.DEFAULT_FALLBACK_VALUE.equals(((OptionSpec) argSpec).fallbackValue()) ? ((OptionSpec) argSpec).fallbackValue() : null; - if (fallback != null && (args.isEmpty() || !varargCanConsumeNextValue(argSpec, args.peek()) + if (fallback != null && consumed == 0 && (args.isEmpty() || !varargCanConsumeNextValue(argSpec, args.peek()) || !canConsumeOneMapArgument(argSpec, lookBehind, alreadyUnquoted, arity, consumed, args.peek(), classes, keyConverter, valueConverter, argDescription))) { args.push(fallback); } @@ -14548,11 +14548,11 @@ private List consumeArguments(ArgSpec argSpec, consumed = addUserInputToList(argSpec, result, consumed, argDescription); } // now process the varargs if any - String fallback = consumed == 0 && argSpec.isOption() && !OptionSpec.DEFAULT_FALLBACK_VALUE.equals(((OptionSpec) argSpec).fallbackValue()) + String fallback = argSpec.isOption() && !OptionSpec.DEFAULT_FALLBACK_VALUE.equals(((OptionSpec) argSpec).fallbackValue()) ? ((OptionSpec) argSpec).fallbackValue() : null; boolean hasFallback = fallback != null || (argSpec.isOption() && Option.NULL_VALUE.equals(((OptionSpec) argSpec).originalFallbackValue)); - if (hasFallback && (args.isEmpty() || !varargCanConsumeNextValue(argSpec, args.peek()) + if (hasFallback && consumed == 0 && (args.isEmpty() || !varargCanConsumeNextValue(argSpec, args.peek()) || (!canConsumeOneArgument(argSpec, lookBehind, alreadyUnquoted, arity, consumed, args.peek(), argDescription)))) { args.push(fallback); } diff --git a/src/test/java/picocli/FallbackTest.java b/src/test/java/picocli/FallbackTest.java index e0f4df48c..750582d3b 100644 --- a/src/test/java/picocli/FallbackTest.java +++ b/src/test/java/picocli/FallbackTest.java @@ -227,4 +227,60 @@ public void testIssue1993Map() { Map expected = TestUtil.mapOf("KEY", CommandLine.Option.NULL_VALUE, "FOO", "123"); assertEquals(expected, main.map); } + + + static class Issue1998NPE { + static final String MY_NULL_VALUE = "_MY_" + CommandLine.Option.NULL_VALUE; + + @CommandLine.Option(names = {"--item"}, arity = "0..1", fallbackValue = CommandLine.Option.NULL_VALUE) + List item; + @CommandLine.Option(names = {"--item2"}, arity = "0..1", fallbackValue = MY_NULL_VALUE, converter = ItemNullValueConverter.class) + List item2; + } + + static class ItemNullValueConverter implements CommandLine.ITypeConverter { + public String convert(String value) throws Exception { + if (value.equals(Issue1998NPE.MY_NULL_VALUE)) { + return null; + } + return value; + } + } + + @Test // PASS + public void testIssue1998_item__null() { + Issue1998NPE main = new Issue1998NPE(); + CommandLine commandLine = new CommandLine(main); + commandLine.parseArgs("--item", "--item", "pepa"); + + assertEquals(Arrays.asList(null, "pepa"), main.item); + } + + @Test // FAIL + public void testIssue1998_item__empty_equals() { + Issue1998NPE main = new Issue1998NPE(); + CommandLine commandLine = new CommandLine(main); + commandLine.parseArgs("--item=", "--item", "pepa"); + + assertEquals(Arrays.asList("", "pepa"), main.item); + } + + @Test // PASS + public void testIssue1998_item2__null() { + Issue1998NPE main = new Issue1998NPE(); + CommandLine commandLine = new CommandLine(main); + commandLine.parseArgs("--item2", "--item2", "pepa"); + + assertEquals(Arrays.asList(null, "pepa"), main.item2); + } + + @Test // PASS + public void testIssue1998_item2__empty_equals() { + Issue1998NPE main = new Issue1998NPE(); + CommandLine commandLine = new CommandLine(main); + commandLine.parseArgs("--item2=", "--item2", "pepa"); + + assertEquals(Arrays.asList("", "pepa"), main.item2); + } + }