Skip to content

Commit

Permalink
[#283] Enhancement and API Change: Provide getMissing method on Mis…
Browse files Browse the repository at this point in the history
…singParameterException to get a reference to the problematic options and positional parameters. Thanks to [jcapsule](https://github.com/jcapsule) for the suggestion.

Closes #283.
  • Loading branch information
remkop committed Apr 6, 2018
1 parent b27d82f commit 5390056
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 8 deletions.
1 change: 1 addition & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ No features have been promoted in this picocli release.

## <a name="3.0.0-alpha-5-fixes"></a> Fixed issues

- [#283] Enhancement and API Change: Provide `getMissing` method on MissingParameterException to get a reference to the problematic options and positional parameters. Thanks to [jcapsule](https://github.com/jcapsule) for the suggestion.
- [#323] Enhancement: Remove dependency on java.sql package: picocli should only require the java.base module when running in Java 9.
- [#325] Enhancement: Allow custom type converter to map empty String to custom default value for empty options. Thanks to [jesselong](https://github.com/jesselong) for the suggestion.
- [#303] Enhancement: Improve validation to prevent common mistakes.
Expand Down
19 changes: 11 additions & 8 deletions src/main/java/picocli/CommandLine.java
Original file line number Diff line number Diff line change
Expand Up @@ -5191,7 +5191,7 @@ private void assertNoMissingParameters(ArgSpec argSpec, int arity, Stack<String>
if (arity > args.size()) {
if (arity == 1) {
if (argSpec.isOption()) {
throw new MissingParameterException(CommandLine.this, "Missing required parameter for " +
throw new MissingParameterException(CommandLine.this, argSpec, "Missing required parameter for " +
optionDescription("", argSpec, 0));
}
Range indexRange = ((PositionalParamSpec) argSpec).index();
Expand All @@ -5213,13 +5213,13 @@ private void assertNoMissingParameters(ArgSpec argSpec, int arity, Stack<String>
} else {
msg += (count > 1 ? "s: " : ": ");
}
throw new MissingParameterException(CommandLine.this, msg + names);
throw new MissingParameterException(CommandLine.this, argSpec, msg + names);
}
if (args.isEmpty()) {
throw new MissingParameterException(CommandLine.this, optionDescription("", argSpec, 0) +
throw new MissingParameterException(CommandLine.this, argSpec, optionDescription("", argSpec, 0) +
" requires at least " + arity + " values, but none were specified.");
}
throw new MissingParameterException(CommandLine.this, optionDescription("", argSpec, 0) +
throw new MissingParameterException(CommandLine.this, argSpec, optionDescription("", argSpec, 0) +
" requires at least " + arity + " values, but only " + args.size() + " were specified: " + reverse(args));
}
}
Expand Down Expand Up @@ -7371,20 +7371,23 @@ private static ParameterException create(CommandLine cmd, Exception ex, String a
*/
public static class MissingParameterException extends ParameterException {
private static final long serialVersionUID = 5075678535706338753L;
public MissingParameterException(CommandLine commandLine, String msg) {
private final List<ArgSpec> missing;
public MissingParameterException(CommandLine commandLine, ArgSpec missing, String msg) { this(commandLine, Arrays.asList(missing), msg); }
public MissingParameterException(CommandLine commandLine, Collection<ArgSpec> missing, String msg) {
super(commandLine, msg);
this.missing = Collections.unmodifiableList(new ArrayList<ArgSpec>(missing));
}

public List<ArgSpec> getMissing() { return missing; }
private static MissingParameterException create(CommandLine cmd, Collection<ArgSpec> missing, String separator) {
if (missing.size() == 1) {
return new MissingParameterException(cmd, "Missing required option '"
return new MissingParameterException(cmd, missing, "Missing required option '"
+ describe(missing.iterator().next(), separator) + "'");
}
List<String> names = new ArrayList<String>(missing.size());
for (ArgSpec argSpec : missing) {
names.add(describe(argSpec, separator));
}
return new MissingParameterException(cmd, "Missing required options " + names.toString());
return new MissingParameterException(cmd, missing, "Missing required options " + names.toString());
}
private static String describe(ArgSpec argSpec, String separator) {
String prefix = (argSpec.isOption())
Expand Down
6 changes: 6 additions & 0 deletions src/test/java/picocli/CommandLineArityTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ class Example {
fail("Should not accept missing mandatory parameter");
} catch (MissingParameterException ex) {
assertEquals("Missing required parameter: <mandatory>", ex.getMessage());
assertEquals(1, ex.getMissing().size());
assertEquals("<mandatory>", ex.getMissing().get(0).paramLabel());
}
}
@Test
Expand Down Expand Up @@ -662,6 +664,8 @@ class OptionsNoArityAndParameters {
fail("expected MissingParameterException");
} catch (MissingParameterException ok) {
assertEquals("Missing required parameter for option '-chars' (<charOptions>)", ok.getMessage());
assertEquals(1, ok.getMissing().size());
assertTrue(ok.getMissing().get(0).toString(), ok.getMissing().get(0) instanceof Model.OptionSpec);
}
}

Expand Down Expand Up @@ -917,6 +921,8 @@ class Arg {
fail("Expected MissingParameterException");
} catch (MissingParameterException ex) {
assertEquals("positional parameter at index 0..* (<parameters>) requires at least 2 values, but only 1 were specified: [p3]", ex.getMessage());
assertEquals(1, ex.getMissing().size());
assertTrue(ex.getMissing().get(0).toString(), ex.getMissing().get(0) instanceof Model.PositionalParamSpec);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/test/java/picocli/CommandLineModelTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ public void testVersionHelp_helpCommand() {
commandLine.parse();
} catch (MissingParameterException ex) {
assertEquals("Missing required option '-x=PARAM'", ex.getMessage());
assertEquals(1, ex.getMissing().size());
assertSame(ex.getMissing().get(0).toString(), parent.posixOptionsMap().get('x'), ex.getMissing().get(0));
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/test/java/picocli/CommandLineTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1681,6 +1681,8 @@ class Args {
fail("MissingParameterException expected");
} catch (MissingParameterException ex) {
assertEquals("positional parameter at index 0..* (<values>) requires at least 2 values, but only 1 were specified: [a,b,c,d,e]", ex.getMessage());
assertEquals(1, ex.getMissing().size());
assertTrue(ex.getMissing().get(0).toString(), ex.getMissing().get(0) instanceof Model.PositionalParamSpec);
}
try {
CommandLine.populateCommand(new Args()); // 0 arg: should fail
Expand Down

0 comments on commit 5390056

Please sign in to comment.