private static void validatePositionalParameters(List<PositionalParamSpec> positionalParametersFields) { int min = 0; for (PositionalParamSpec positional : positionalParametersFields) { Range index = positional.index(); if (index.min > min) { throw new ParameterIndexGapException("Command definition should have a positional parameter with index=" + min + ". Nearest positional parameter '" + positional.paramLabel() + "' has index=" + index.min); } min = Math.max(min, index.max); min = min == Integer.MAX_VALUE ? min : min + 1; } } @SuppressWarnings("unchecked") private static Stack<String> copy(Stack<String> stack) { return (Stack<String>) stack.clone(); }
for (int i = indexRange.min; i < positionalParameters.size(); i++) { if (positionalParameters.get(i).arity().min > 0) { names += sep + positionalParameters.get(i).paramLabel(); sep = ", "; count++;
@Test public void testAnnotateMethod_unannotatedPositional_indexByParameterOrder() throws Exception { Method m = CommandLine.getCommandMethods(UnannotatedPositional.class, "x").get(0); CommandLine cmd = new CommandLine(m); CommandSpec spec = cmd.getCommandSpec(); List<Model.PositionalParamSpec> positionals = spec.positionalParameters(); String[] labels = { "<arg0>", "<arg1>", "<arg2>", "<arg3>", "<arg4>"}; assertEquals(positionals.size(), labels.length); String[] ranges = { "0", "1", "2", "3..*", "4..*" }; for (int i = 0; i < positionals.size(); i++) { Model.PositionalParamSpec positional = positionals.get(i); assertEquals(positional.paramLabel() + " at index " + i, CommandLine.Range.valueOf(ranges[i]), positional.index()); assertEquals(labels[i], positional.paramLabel()); } }
for (int i = indexRange.min; i < positionalParameters.size(); i++) { if (positionalParameters.get(i).arity().min > 0) { names += sep + positionalParameters.get(i).paramLabel(); sep = ", "; count++;
@Test public void testMixinAnnotationInjectsOptionsAndParametersInDeclarationOrder() throws Exception { @Command(sortOptions = false) class Receiver { @Mixin InjectsOptionsAndParameters.MixMeIn mixMeIn; @Option(names = {"-b", "--beta"}, description = "Receiver option") private int beta; @Parameters(description = "parameters from receiver") File[] receiverFiles; } CommandLine commandLine = new CommandLine(new Receiver()); CommandSpec commandSpec = commandLine.getCommandSpec(); assertEquals(2, commandSpec.options().size()); assertArrayEquals(new String[]{"-a", "--alpha"}, commandSpec.options().get(0).names()); assertArrayEquals(new String[]{"-b", "--beta"}, commandSpec.options().get(1).names()); assertEquals(2, commandSpec.positionalParameters().size()); assertEquals("<files>", commandSpec.positionalParameters().get(0).paramLabel()); assertEquals("<receiverFiles>", commandSpec.positionalParameters().get(1).paramLabel()); String expects = String.format("" + "Usage: <main class> [-a=<alpha>] [-b=<beta>] [<files>...] [<receiverFiles>...]%n" + " [<files>...] parameters from mixin%n" + " [<receiverFiles>...] parameters from receiver%n" + " -a, --alpha=<alpha> option from mixin%n" + " -b, --beta=<beta> Receiver option%n"); assertEquals(expects, usageString(commandLine, Help.Ansi.OFF)); }
private void verifyMixinInjectsOptionsAndParameters(CommandLine commandLine) throws UnsupportedEncodingException { CommandSpec commandSpec = commandLine.getCommandSpec(); assertEquals(2, commandSpec.options().size()); assertArrayEquals(new String[]{"-b", "--beta"}, commandSpec.options().get(0).names()); assertArrayEquals(new String[]{"-a", "--alpha"}, commandSpec.options().get(1).names()); assertTrue(commandSpec.optionsMap().containsKey("--alpha")); assertTrue(commandSpec.optionsMap().containsKey("--beta")); assertTrue(commandSpec.optionsMap().containsKey("-a")); assertTrue(commandSpec.optionsMap().containsKey("-b")); assertTrue(commandSpec.posixOptionsMap().containsKey('a')); assertTrue(commandSpec.posixOptionsMap().containsKey('b')); assertEquals(2, commandSpec.positionalParameters().size()); assertEquals("<receiverFiles>", commandSpec.positionalParameters().get(0).paramLabel()); assertEquals("<files>", commandSpec.positionalParameters().get(1).paramLabel()); String expects = String.format("" + "Usage: <main class> [-a=<alpha>] [-b=<beta>] [<receiverFiles>...] [<files>...]%n" + " [<receiverFiles>...] parameters from receiver%n" + " [<files>...] parameters from mixin%n" + " -b, --beta=<beta> Receiver option%n" + " -a, --alpha=<alpha> option from mixin%n"); assertEquals(expects, usageString(commandLine, Help.Ansi.OFF)); } @Test
@Test public void testAnnotateMethod_unannotatedPositionalMixedWithOptions_indexByParameterOrder() throws Exception { Method m = CommandLine.getCommandMethods(PositionalsMixedWithOptions.class, "mixed").get(0); CommandLine cmd = new CommandLine(m); CommandSpec spec = cmd.getCommandSpec(); List<Model.PositionalParamSpec> positionals = spec.positionalParameters(); String[] labels = { "<arg0>", "<arg3>", "<arg4>"}; assertEquals(positionals.size(), labels.length); String[] ranges = { "0", "1..*", "2..*" }; for (int i = 0; i < positionals.size(); i++) { Model.PositionalParamSpec positional = positionals.get(i); assertEquals(positional.paramLabel() + " at index " + i, CommandLine.Range.valueOf(ranges[i]), positional.index()); assertEquals(labels[i], positional.paramLabel()); } assertEquals(2, spec.options().size()); assertEquals(int.class, spec.findOption("-b").type()); assertEquals(String.class, spec.findOption("-c").type()); }
/** Returns the description template of this positional parameter, before variables are {@linkplain Parameters#description() rendered}. * If a resource bundle has been {@linkplain ArgSpec#messages(Messages) set}, this method will first try to find a value in the resource bundle: * If the resource bundle has no entry for the {@code fully qualified commandName + "." + descriptionKey} or for the unqualified {@code descriptionKey}, * an attempt is made to find the positional parameter description using {@code paramLabel() + "[" + index() + "]"} as key, * first with the {@code fully qualified commandName + "."} prefix, then without. * @see Parameters#description() * @see CommandSpec#qualifiedName(String) * @since 3.6 */ @Override public String[] description() { if (messages() == null) { return super.description(); } String[] newValue = messages().getStringArray(descriptionKey(), null); if (newValue != null) { return newValue; } newValue = messages().getStringArray(paramLabel() + "[" + index() + "]", null); if (newValue != null) { return newValue; } return super.description(); }
@Test public void testAnnotateMethod_unannotatedPositional_indexByParameterOrder() throws Exception { Method m = CommandLine.getCommandMethods(UnannotatedPositional.class, "x").get(0); CommandLine cmd = new CommandLine(m); CommandSpec spec = cmd.getCommandSpec(); List<Model.PositionalParamSpec> positionals = spec.positionalParameters(); String[] labels = { "<arg0>", "<arg1>", "<arg2>", "<arg3>", "<arg4>"}; assertEquals(positionals.size(), labels.length); String[] ranges = { "0", "1", "2", "3..*", "4..*" }; for (int i = 0; i < positionals.size(); i++) { Model.PositionalParamSpec positional = positionals.get(i); assertEquals(positional.paramLabel() + " at index " + i, CommandLine.Range.valueOf(ranges[i]), positional.index()); assertEquals(labels[i], positional.paramLabel()); } }
private static void validatePositionalParameters(List<PositionalParamSpec> positionalParametersFields) { int min = 0; for (PositionalParamSpec positional : positionalParametersFields) { Range index = positional.index(); if (index.min > min) { throw new ParameterIndexGapException("Command definition should have a positional parameter with index=" + min + ". Nearest positional parameter '" + positional.paramLabel() + "' has index=" + index.min); } min = Math.max(min, index.max); min = min == Integer.MAX_VALUE ? min : min + 1; } } @SuppressWarnings("unchecked") private static Stack<String> copy(Stack<String> stack) { return (Stack<String>) stack.clone(); }
@Test public void testPositionalDefaultParamLabel() { assertEquals("PARAM", PositionalParamSpec.builder().build().paramLabel()); }
@Test public void testInferTypes() { class App { @CommandLine.Parameters List<Class<? extends Class<? extends String>[]>> list; } assertEquals("<list>", CommandLine.Model.CommandSpec.forAnnotatedObject(new App()).positionalParameters().get(0).paramLabel()); } }
@Test public void testMixinAnnotationInjectsOptionsAndParametersInDeclarationOrder() throws Exception { @Command(sortOptions = false) class Receiver { @Mixin InjectsOptionsAndParameters.MixMeIn mixMeIn; @Option(names = {"-b", "--beta"}, description = "Receiver option") private int beta; @Parameters(description = "parameters from receiver") File[] receiverFiles; } CommandLine commandLine = new CommandLine(new Receiver()); CommandSpec commandSpec = commandLine.getCommandSpec(); assertEquals(2, commandSpec.options().size()); assertArrayEquals(new String[]{"-a", "--alpha"}, commandSpec.options().get(0).names()); assertArrayEquals(new String[]{"-b", "--beta"}, commandSpec.options().get(1).names()); assertEquals(2, commandSpec.positionalParameters().size()); assertEquals("<files>", commandSpec.positionalParameters().get(0).paramLabel()); assertEquals("<receiverFiles>", commandSpec.positionalParameters().get(1).paramLabel()); String expects = String.format("" + "Usage: <main class> [-a=<alpha>] [-b=<beta>] [<files>...] [<receiverFiles>...]%n" + " [<files>...] parameters from mixin%n" + " [<receiverFiles>...] parameters from receiver%n" + " -a, --alpha=<alpha> option from mixin%n" + " -b, --beta=<beta> Receiver option%n"); assertEquals(expects, usageString(commandLine, Help.Ansi.OFF)); }
private void verifyMixinInjectsOptionsAndParameters(CommandLine commandLine) throws UnsupportedEncodingException { CommandSpec commandSpec = commandLine.getCommandSpec(); assertEquals(2, commandSpec.options().size()); assertArrayEquals(new String[]{"-b", "--beta"}, commandSpec.options().get(0).names()); assertArrayEquals(new String[]{"-a", "--alpha"}, commandSpec.options().get(1).names()); assertTrue(commandSpec.optionsMap().containsKey("--alpha")); assertTrue(commandSpec.optionsMap().containsKey("--beta")); assertTrue(commandSpec.optionsMap().containsKey("-a")); assertTrue(commandSpec.optionsMap().containsKey("-b")); assertTrue(commandSpec.posixOptionsMap().containsKey('a')); assertTrue(commandSpec.posixOptionsMap().containsKey('b')); assertEquals(2, commandSpec.positionalParameters().size()); assertEquals("<receiverFiles>", commandSpec.positionalParameters().get(0).paramLabel()); assertEquals("<files>", commandSpec.positionalParameters().get(1).paramLabel()); String expects = String.format("" + "Usage: <main class> [-a=<alpha>] [-b=<beta>] [<receiverFiles>...] [<files>...]%n" + " [<receiverFiles>...] parameters from receiver%n" + " [<files>...] parameters from mixin%n" + " -b, --beta=<beta> Receiver option%n" + " -a, --alpha=<alpha> option from mixin%n"); assertEquals(expects, usageString(commandLine, Help.Ansi.OFF)); } @Test
private void printParametersAnnotation(PrintWriter pw, PositionalParamSpec spec, String indent) { pw.printf("%s@%s", indent, importer.getImportedName(Parameters.class.getCanonicalName())); indent = String.format(",%n%s ", indent); String sep = "("; sep = append(pw, sep, indent, "index = \"%s\"", spec.index().toString(), spec.index().isUnspecified()); sep = appendStringArray(pw, sep, indent, "description = %s", spec.description(), EMPTY_ARRAY); sep = append(pw, sep, indent, "arity = \"%s\"", spec.arity().toString(), spec.arity().isUnspecified() ? spec.arity().toString() : ""); sep = append(pw, sep, indent, "paramLabel = \"%s\"", spec.paramLabel(), "<" + argElementName(spec) + ">"); sep = append(pw, sep, indent, "hideParamSyntax = %s", spec.hideParamSyntax(), false); sep = appendTypeInfo(pw, sep, indent, spec.typeInfo()); sep = appendTypeConverter(pw, sep, indent, spec.converters()); sep = append(pw, sep, indent, "split = \"%s\"", spec.splitRegex(), ""); sep = append(pw, sep, indent, "hidden = %s", spec.hidden(), false); sep = append(pw, sep, indent, "defaultValue = \"%s\"", spec.defaultValue() == null ? "__no_default_value__" : spec.defaultValue(), "__no_default_value__"); sep = append(pw, sep, indent, "showDefaultValue = %s", spec.showDefaultValue(), CommandLine.Help.Visibility.ON_DEMAND); sep = appendCompletionCandidates(pw, sep, indent, spec); sep = append(pw, sep, indent, "interactive = %s", spec.interactive(), false); sep = append(pw, sep, indent, "descriptionKey = \"%s\"", spec.descriptionKey(), ""); if (!"(".equals(sep)) { pw.print(")"); } }
@Test public void testAnnotateMethod_unannotatedPositionalMixedWithOptions_indexByParameterOrder() throws Exception { Method m = CommandLine.getCommandMethods(PositionalsMixedWithOptions.class, "mixed").get(0); CommandLine cmd = new CommandLine(m); CommandSpec spec = cmd.getCommandSpec(); List<Model.PositionalParamSpec> positionals = spec.positionalParameters(); String[] labels = { "<arg0>", "<arg3>", "<arg4>"}; assertEquals(positionals.size(), labels.length); String[] ranges = { "0", "1..*", "2..*" }; for (int i = 0; i < positionals.size(); i++) { Model.PositionalParamSpec positional = positionals.get(i); assertEquals(positional.paramLabel() + " at index " + i, CommandLine.Range.valueOf(ranges[i]), positional.index()); assertEquals(labels[i], positional.paramLabel()); } assertEquals(2, spec.options().size()); assertEquals(int.class, spec.findOption("-b").type()); assertEquals(String.class, spec.findOption("-c").type()); }
/** Returns the description template of this positional parameter, before variables are {@linkplain Parameters#description() rendered}. * If a resource bundle has been {@linkplain ArgSpec#messages(Messages) set}, this method will first try to find a value in the resource bundle: * If the resource bundle has no entry for the {@code fully qualified commandName + "." + descriptionKey} or for the unqualified {@code descriptionKey}, * an attempt is made to find the positional parameter description using {@code paramLabel() + "[" + index() + "]"} as key, * first with the {@code fully qualified commandName + "."} prefix, then without. * @see Parameters#description() * @see CommandSpec#qualifiedName(String) * @since 3.6 */ @Override public String[] description() { if (messages() == null) { return super.description(); } String[] newValue = messages().getStringArray(descriptionKey(), null); if (newValue != null) { return newValue; } newValue = messages().getStringArray(paramLabel() + "[" + index() + "]", null); if (newValue != null) { return newValue; } return super.description(); }
@Test public void testPositionalDefaultParamLabel() { assertEquals("PARAM", PositionalParamSpec.builder().build().paramLabel()); }
@Test public void testInferTypes() { class App { @CommandLine.Parameters List<Class<? extends Class<? extends String>[]>> list; } assertEquals("<list>", CommandLine.Model.CommandSpec.forAnnotatedObject(new App()).positionalParameters().get(0).paramLabel()); } }