Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setter method annotated by @Option with default value not been invoked when reusing it #2149

Closed
JBWKZsf opened this issue Nov 13, 2023 · 3 comments
Labels
theme: parser An issue or change related to the parser type: bug 🐛
Milestone

Comments

@JBWKZsf
Copy link

JBWKZsf commented Nov 13, 2023

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:

  1. Running A B -e XX C, setEnv in InputOptions of A is not called at all, but C's InputOptions setEnv in called.
  2. Running A B C -e XX, setEnv of InputOptions 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.

@remkop
Copy link
Owner

remkop commented Nov 25, 2023

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?

@remkop
Copy link
Owner

remkop commented Feb 21, 2024

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.

@remkop remkop added this to the 4.7.6 milestone Feb 21, 2024
@remkop remkop added type: bug 🐛 theme: parser An issue or change related to the parser labels Feb 21, 2024
@remkop
Copy link
Owner

remkop commented May 6, 2024

Fixed in main. Thank you for raising this!

@remkop remkop closed this as completed May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
theme: parser An issue or change related to the parser type: bug 🐛
Projects
None yet
Development

No branches or pull requests

2 participants