@Test public void testParameterCapacity() throws Exception { PositionalParamSpec paramSpec = PositionalParamSpec.builder().index(Range.valueOf("1..2")).arity(Range.valueOf("*")).build(); Method capacity = PositionalParamSpec.class.getDeclaredMethod("capacity"); capacity.setAccessible(true); Range c = (Range) capacity.invoke(paramSpec); assertEquals(Range.valueOf("*"), c); }
@Test public void testParamIndexAnnotatedAndUnAnnotated() { CommandLine git = new CommandLine(new AnnotatedParams()); CommandLine method = git.getSubcommands().get("method"); List<Model.PositionalParamSpec> positionals = method.getCommandSpec().positionalParameters(); for (int i = 0; i < positionals.size(); i++) { assertEquals(CommandLine.Range.valueOf("" + i), positionals.get(i).index()); } }
@Test public void testArgSpecSplitWithEscapedBackslashInsideQuote() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex(";").build(); System.setProperty("picocli.trace", "DEBUG"); String value = "\"abc\\\\\\\";def\""; String[] values = positional.splitValue(value, new CommandLine.Model.ParserSpec().splitQuotedStrings(false), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"\"abc\\\\\\\";def\""}, values); }
/** Ensures all attributes of this {@code PositionalParamSpec} have a valid value; throws an {@link InitializationException} if this cannot be achieved. */ private PositionalParamSpec(Builder builder) { super(builder); index = builder.index == null ? Range.valueOf("*") : builder.index; capacity = builder.capacity == null ? Range.parameterCapacity(arity(), index) : builder.capacity; if (toString == null) { toString = "positional parameter[" + index() + "]"; } } public static Builder builder() { return new Builder(); }
private static Range parameterArity(IAnnotatedElement member) { if (member.isAnnotationPresent(Parameters.class)) { return adjustForType(Range.valueOf(member.getAnnotation(Parameters.class).arity()), member); } else { return member.isMethodParameter() ? adjustForType(Range.valueOf(""), member) : new Range(0, 0, false, true, "0"); } } /** Returns a new {@code Range} based on the {@link Parameters#index()} annotation on the specified field.
private static Range defaultArity(IAnnotatedElement member) { ITypeInfo info = member.getTypeInfo(); if (member.isAnnotationPresent(Option.class)) { boolean zeroArgs = info.isBoolean() || (info.isMultiValue() && info.getAuxiliaryTypeInfos().get(0).isBoolean()); return zeroArgs ? Range.valueOf("0").unspecified(true) : Range.valueOf("1").unspecified(true); } if (info.isMultiValue()) { return Range.valueOf("0..1").unspecified(true); } return Range.valueOf("1").unspecified(true);// for single-valued fields (incl. boolean positional parameters) } /** Returns the default arity {@code Range} for {@link Option options}: booleans have arity 0, other types have arity 1.
private static Range parameterIndex(IAnnotatedElement member) { if (member.isAnnotationPresent(Parameters.class)) { Range result = Range.valueOf(member.getAnnotation(Parameters.class).index()); if (!result.isUnspecified) { return result; } } if (member.isMethodParameter()) { int min = member.getMethodParamPosition(); int max = member.isMultiValue() ? Integer.MAX_VALUE : min; return new Range(min, max, member.isMultiValue(), false, ""); } return Range.valueOf("*"); // the default } static Range adjustForType(Range result, IAnnotatedElement member) {
@Test public void testArityForParameters_arrayFieldImplicitArity0_1() throws Exception { class Args { @Parameters File[] inputFiles; } Range arity = Range.parameterArity(Args.class.getDeclaredField("inputFiles")); assertEquals(Range.valueOf("0..1"), arity); assertEquals("0..1", arity.toString()); } @Test
@Test public void testArityForParameters_intFieldImplicitArity1() throws Exception { class ImplicitSingleField { @Parameters int intSingleValue; } Range arity = Range.parameterArity(ImplicitSingleField.class.getDeclaredField("intSingleValue")); assertEquals(Range.valueOf("1"), arity); assertEquals("1", arity.toString()); } @Test
@SuppressWarnings("deprecation") @Test public void testDefaultArity_Class() { assertEquals(Range.valueOf("0"), Range.defaultArity(Boolean.TYPE)); assertEquals(Range.valueOf("0"), Range.defaultArity(Boolean.class)); assertEquals(Range.valueOf("1"), Range.defaultArity(Integer.TYPE)); assertEquals(Range.valueOf("1"), Range.defaultArity(Integer.class)); assertEquals(Range.valueOf("1"), Range.defaultArity(List.class)); assertEquals(Range.valueOf("1"), Range.defaultArity(String[].class)); assertEquals(Range.valueOf("1"), Range.defaultArity(Map.class)); }
@Test public void testPositionalDefaultArityIsOneIfTypeNonBoolean() { assertEquals(Range.valueOf("1"), CommandLine.Model.PositionalParamSpec.builder().type(int.class).build().arity()); assertEquals(Range.valueOf("1"), CommandLine.Model.PositionalParamSpec.builder().type(Integer.class).build().arity()); assertEquals(Range.valueOf("1"), CommandLine.Model.PositionalParamSpec.builder().type(Byte.class).build().arity()); assertEquals(Range.valueOf("1"), CommandLine.Model.PositionalParamSpec.builder().type(String.class).build().arity()); } @Test
@Test public void testArgSpecSplitBalancedQuotedValueDebug() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex(";").build(); System.setProperty("picocli.trace", "DEBUG"); String value = "\"abc\\\";def\""; String[] values = positional.splitValue(value, new CommandLine.Model.ParserSpec().splitQuotedStrings(false), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"\"abc\\\";def\""}, values); }
@Test public void testArityConstructor_fixedRange() { Range arity = new Range(1, 23, false, false, null); assertEquals("min", 1, arity.min); assertEquals("max", 23, arity.max); assertEquals("1..23", arity.toString()); assertEquals(Range.valueOf("1..23"), arity); } @Test
@Test public void testPositionalDefaultArityIsOneIfTypeBoolean() { assertEquals(Range.valueOf("1"), CommandLine.Model.PositionalParamSpec.builder().type(boolean.class).build().arity()); assertEquals(Range.valueOf("1"), CommandLine.Model.PositionalParamSpec.builder().type(Boolean.class).build().arity()); }
private static Range optionArity(IAnnotatedElement member) { return member.isAnnotationPresent(Option.class) ? adjustForType(Range.valueOf(member.getAnnotation(Option.class).arity()), member) : new Range(0, 0, false, true, "0"); } /** Returns a new {@code Range} based on the {@link Parameters#arity()} annotation on the specified field,
@Test public void testArgSpecSplitValue_MultipleQuotedValues() { ParserSpec parser = new ParserSpec(); ArgSpec spec = PositionalParamSpec.builder().splitRegex(",").build(); String[] actual = spec.splitValue("a,b,\"c,d,e\",f,\"xxx,yyy\"", parser, Range.valueOf("0"), 0); assertArrayEquals(new String[]{"a", "b", "\"c,d,e\"", "f", "\"xxx,yyy\""}, actual); }
@Test public void testArityForOption_listFieldImplicitArity1() throws Exception { class ImplicitList { @Option(names = "-a") List<Integer> listIntegers; } Range arity = Range.optionArity(ImplicitList.class.getDeclaredField("listIntegers")); assertEquals(Range.valueOf("1"), arity); assertEquals("1", arity.toString()); } @Test
@Test public void testArgSpecSplitValue_SplitsQuotedValuesIfConfigured() { ParserSpec parser = new ParserSpec().splitQuotedStrings(true); ArgSpec spec = PositionalParamSpec.builder().splitRegex(",").build(); String[] actual = spec.splitValue("a,b,\"c,d,e\",f", parser, Range.valueOf("0"), 0); assertArrayEquals(new String[]{"a", "b", "\"c", "d" , "e\"", "f"}, actual); }