Setter method annotated by @Option with default value not been invoked when reusing it
JBWKZsf opened this issue · comments
Behavior: Setter method annotated by @option with default value not been invoked when reusing it(By saving reusing, I leveraged @Mixin
).
For example:
I have a @Mixin
class has bunch options
public class InputOptions {
private final static String DEFAULT_ENV = "env";
private final static String DEFAULT_REGION = "region";
private String env;
private String region;
@CommandLine.Spec(MIXEE)
private CommandSpec mixee;
@CommandLine.Option(
names = {"-e", "--env"},
defaultValue = DEFAULT_ENV)
public void setEnv(String env) {
this.env = env;
if (!DEFAULT_ENV.equals(env) && !this.equals(getRoot().inputOptions)) {
getRoot().inputOptions.setEnv(env);
}
}
@CommandLine.Option(
names = {"-r", "--region"},
defaultValue = DEFAULT_REGION)
public void setRegion(String region) {
this.region = region;
if (!DEFAULT_REGION.equals(region) && !this.equals(getRoot().inputOptions)) {
getRoot().inputOptions.setRegion(region);
}
}
public String getEnv() {
if (this.equals(getRoot().inputOptions)) return env;
return getRoot().inputOptions.getEnv();
}
public String getRegion() {
if (this.equals(getRoot().inputOptions)) return region;
return getRoot().inputOptions.getRegion();
}
private T getRoot() {
return (T) mixee.root().userObject();
}
}
I reused this options in other commands(in parents and subcommands as global options, I referred example: https://picocli.info/#_use_case_configure_log_level_with_a_global_option)
But found the behavior that when I define the options, the parent command(parent/child
are relevant to the mixee command level) 's @Mixin
instance's option will not be invoked at all.
For example, I have command A(toplevel
), B(subCommand
), C(subsubCommand
), all of them has declare d@Mixin InputOptions inputOptions
.
Cases:
- Running
A B -e XX C
,setEnv
inInputOptions
of A is not called at all, but C'sInputOptions
setEnv
in called. - Running
A B C -e XX
,setEnv
ofInputOptions
in both A and B is not called at all.
Worth to notice, setRegion
has been called in all InputOptions
instances in both 2 cases above.
Is this some misbehaving in picocli? I was expecting in any cases, the setters method should be called in all InputOptions
options. Thus the default value can be set for the options.
Hi, sorry for the late response.
Can you run your program with tracing set to DEBUG (e.g. use system property -Dpicocli.trace=DEBUG
)
and post the output here please?
Thank you for raising this. It looks like you have found a bug.
For the input A B C -e XX
, the default value should be applied to setEnv
for the A
and the B
commands, but as you say, this method is only called for C
with the command line value "XX".
It looks like the bug is due to the implementation of equals
on OptionSpec
. As a result, the OptionSpec
instance for the --env
option in the mixin for A is considered equal to the instance in the B command and in the C command.
Since the --env
option was assigned a value "XX" for the C
command, it won't assign the default value any more.
The bug means that picocli thinks that the --env
option instance in C
is the same instance as in the A
and B
commands, so those are not assigned the default value either, which is incorrect.
Fixed in main. Thank you for raising this!