Skip to content

Bug: Default value provider is not called for required inherited options of subcommands. #2443

@garretwilson

Description

@garretwilson

I'm seeing some behavior I don't understand.

I have an application class Foo like this:

@Command(name = "foo", subcommands = {Bar.class})
public class FooCli {

  private String widget = nll;

  @Option(names = "--widget", scope = ScopeType.INHERIT)
  protected setWidget(String widget) {
    this.widget = widget.
  }


}

Then I have a Bar subcommand class:

@Command(name = "bar")
public class Bar {

  @Command(name = "baz");
  public void baz() {
  }

}

In the main Foo class I set up a default value provider:

  commandLine.setDefaultValueProvider(new CommandLine.IDefaultValueProvider() {
    @Override
    public String defaultValue(final ArgSpec argSpec) throws Exception {
      return findDefaultCliArg(argSpec).orElse(null);
    }
  });

That winds its way down to this method:

  protected Optional<String> findDefaultCliOption(final OptionSpec optionSpec) {
    System.out.println("looking for default for command `%s` option `%s`: ".formatted(optionSpec.command().qualifiedName(), optionSpec.longestName()));
    return Optional.empty(); //TODO implement
  }

This is just to see what is going on.

If I run foo bar baz with no --widget option, I see something like this in the output:

looking for default for command `foo` option `--widget`

That makes sense, because --widget is defined at the foo application command level, and it's trying to find the value, since I didn't supply one.

And this is exactly what I want, because if I'm doing a default lookup of an inherited option, I don't want to check for a thousand different commands—I just want to look for the option on the command it was defined.

But what if I make --widget required?

  @Option(names = "--widget", required = true, scope = ScopeType.INHERIT)

Suddenly the output changes!

looking for default for command `foo bar baz` option `--widget`

So the default lookup passes me a fully defined command foo bar baz CommandSpec if the --widget option is required, but only the top-level foo CommandSpec if --widget is not required!

Why the difference? Shouldn't the default lookup pass the provider exactly the same information regardless of whether the option is required?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions