Support explicit arity min max with @Option
- @Option now has arityMin/arityMax which if defined, non-negative, are used instead of arity. - Fixes #731
This commit is contained in:
@@ -74,6 +74,28 @@ public @interface Option {
|
||||
* Define option arity.
|
||||
*
|
||||
* @return option arity
|
||||
* @see #arityMin()
|
||||
* @see #arityMax()
|
||||
*/
|
||||
OptionArity arity() default OptionArity.NONE;
|
||||
|
||||
/**
|
||||
* Define option arity min. If Defined non-negative will be used instead of
|
||||
* {@link #arity()}. If {@code arityMax} is not set non-negative it is set to
|
||||
* same as this.
|
||||
*
|
||||
* @return option arity min
|
||||
* @see #arity()
|
||||
*/
|
||||
int arityMin() default -1;
|
||||
|
||||
/**
|
||||
* Define option arity max. If Defined non-negative will be used instead of
|
||||
* {@link #arity()}. If {@code arityMin} is not set non-negative it is set to
|
||||
* zero.
|
||||
*
|
||||
* @return option arity max
|
||||
* @see #arity()
|
||||
*/
|
||||
int arityMax() default -1;
|
||||
}
|
||||
|
||||
@@ -251,7 +251,22 @@ class CommandRegistrationFactoryBean implements FactoryBean<CommandRegistration>
|
||||
optionSpec.shortNames(shortNames.toArray(new Character[0]));
|
||||
optionSpec.position(mp.getParameterIndex());
|
||||
optionSpec.description(so.description());
|
||||
if (so.arity() != OptionArity.NONE) {
|
||||
int arityMin = so.arityMin();
|
||||
int arityMax = so.arityMax();
|
||||
if (arityMin > -1) {
|
||||
if (arityMax < arityMin) {
|
||||
arityMax = arityMin;
|
||||
}
|
||||
}
|
||||
else if (arityMax > -1) {
|
||||
if (arityMin < 0) {
|
||||
arityMin = 0;
|
||||
}
|
||||
}
|
||||
if (arityMin > -1 && arityMax > -1) {
|
||||
optionSpec.arity(arityMin, arityMax);
|
||||
}
|
||||
else if (so.arity() != OptionArity.NONE) {
|
||||
optionSpec.arity(so.arity());
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.shell.Availability;
|
||||
import org.springframework.shell.AvailabilityProvider;
|
||||
import org.springframework.shell.command.CommandRegistration;
|
||||
import org.springframework.shell.command.CommandRegistration.OptionArity;
|
||||
import org.springframework.shell.command.annotation.Command;
|
||||
import org.springframework.shell.command.annotation.CommandAvailability;
|
||||
import org.springframework.shell.command.annotation.Option;
|
||||
@@ -242,6 +243,78 @@ class CommandRegistrationFactoryBeanTests {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void setsOptionWithArity() {
|
||||
configCommon(OptionWithArity.class, new OptionWithArity(), "command1", new Class[] { String.class })
|
||||
.run((context) -> {
|
||||
CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF,
|
||||
CommandRegistrationFactoryBean.class);
|
||||
assertThat(fb).isNotNull();
|
||||
CommandRegistration registration = fb.getObject();
|
||||
assertThat(registration).isNotNull();
|
||||
assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(1);
|
||||
assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1);
|
||||
});
|
||||
configCommon(OptionWithArity.class, new OptionWithArity(), "command2", new Class[] { String.class })
|
||||
.run((context) -> {
|
||||
CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF,
|
||||
CommandRegistrationFactoryBean.class);
|
||||
assertThat(fb).isNotNull();
|
||||
CommandRegistration registration = fb.getObject();
|
||||
assertThat(registration).isNotNull();
|
||||
assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(1);
|
||||
assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(1);
|
||||
});
|
||||
configCommon(OptionWithArity.class, new OptionWithArity(), "command3", new Class[] { String.class })
|
||||
.run((context) -> {
|
||||
CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF,
|
||||
CommandRegistrationFactoryBean.class);
|
||||
assertThat(fb).isNotNull();
|
||||
CommandRegistration registration = fb.getObject();
|
||||
assertThat(registration).isNotNull();
|
||||
assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0);
|
||||
assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(2);
|
||||
});
|
||||
configCommon(OptionWithArity.class, new OptionWithArity(), "command4", new Class[] { String.class })
|
||||
.run((context) -> {
|
||||
CommandRegistrationFactoryBean fb = context.getBean(FACTORYBEANREF,
|
||||
CommandRegistrationFactoryBean.class);
|
||||
assertThat(fb).isNotNull();
|
||||
CommandRegistration registration = fb.getObject();
|
||||
assertThat(registration).isNotNull();
|
||||
assertThat(registration.getOptions().get(0).getArityMin()).isEqualTo(0);
|
||||
assertThat(registration.getOptions().get(0).getArityMax()).isEqualTo(2);
|
||||
});
|
||||
}
|
||||
|
||||
@Command
|
||||
private static class OptionWithArity {
|
||||
|
||||
@Command
|
||||
void command1(@Option(longNames = "arg", arity = OptionArity.EXACTLY_ONE) String arg) {
|
||||
}
|
||||
|
||||
@Command
|
||||
void command2(@Option(longNames = "arg", arityMin = 1) String arg) {
|
||||
}
|
||||
|
||||
@Command
|
||||
void command3(@Option(longNames = "arg", arityMax = 2) String arg) {
|
||||
}
|
||||
|
||||
@Command
|
||||
void command4(@Option(longNames = "arg", arityMax = 2, arity = OptionArity.EXACTLY_ONE) String arg) {
|
||||
}
|
||||
|
||||
@Bean
|
||||
CompletionProvider completionProvider() {
|
||||
return ctx -> {
|
||||
return Collections.emptyList();
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private <T> ApplicationContextRunner configCommon(Class<T> type, T bean) {
|
||||
return configCommon(type, bean, "command", new Class[0]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user