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

Shell completions include --version on subcommands despite no version set #2860

Closed
2 tasks done
epage opened this issue Oct 12, 2021 · 2 comments · Fixed by #2863
Closed
2 tasks done

Shell completions include --version on subcommands despite no version set #2860

epage opened this issue Oct 12, 2021 · 2 comments · Fixed by #2863
Assignees
Labels
A-completion Area: completion generator C-bug Category: Updating dependencies
Milestone

Comments

@epage
Copy link
Member

epage commented Oct 12, 2021

Please complete the following tasks

  • I have searched the discussions
  • I have searched the existing issues

Rust Version

rustc 1.55.0 (c8dfcfe04 2021-09-06)

Clap Version

master

Minimal reproducible code

This snippet is using the API the generators used, so it can demonstrate the problem

fn main() {
    use clap::*;
    let mut app = App::new("fig")
        .about("Tests completions")
        .arg(
            Arg::new("file")
                .value_hint(ValueHint::FilePath)
                .about("some input file"),
        )
        .subcommand(
            App::new("test").about("tests things").arg(
                Arg::new("case")
                    .long("case")
                    .takes_value(true)
                    .about("the case to test"),
            ),
        );

    app.get_matches_mut();
    for flag in clap_generate::utils::flags(&app) {
        if flag.get_name() == "version" {
            dbg!(flag);
        }
    }

    for subcommand in app.get_subcommands() {
        for flag in clap_generate::utils::flags(&subcommand) {
            if flag.get_name() == "version" {
                dbg!(subcommand.get_name());
                dbg!(flag);
            }
        }
    }
}

Steps to reproduce the bug with the above code

Run it

Actual Behaviour

See a version flag included for each subcommand

Expected Behaviour

No output should happen

Additional Context

This was found as part of #2858.

If I'm reading this correctly, #2831 relied on fn _build to remove --version in the call to _check_help_and_version but we don't recursively call _build on subcommands, leaving the auto-generated flag behind.

if this is the case, then probably a lot of subcommand behavior is broken because we'd never call _build on their args.

Debug Output

[            clap::build::app]  App::_do_parse
[            clap::build::app]  App::_build
[            clap::build::app]  App::_propagate:fig
[            clap::build::app]  App::_check_help_and_version
[            clap::build::app]  App::_check_help_and_version: Removing generated version
[            clap::build::app]  App::_check_help_and_version: Building help subcommand
[            clap::build::app]  App::_propagate_global_args:fig
[            clap::build::app]  App::_derive_display_order:fig
[            clap::build::app]  App::_derive_display_order:test
[            clap::build::app]  App::_derive_display_order:help
[clap::build::app::debug_asserts]       App::_debug_asserts
[clap::build::arg::debug_asserts]       Arg::_debug_asserts:help
[clap::build::arg::debug_asserts]       Arg::_debug_asserts:file
[         clap::parse::parser]  Parser::get_matches_with
[         clap::parse::parser]  Parser::_build
[         clap::parse::parser]  Parser::_verify_positionals
[         clap::parse::parser]  Parser::remove_overrides
[      clap::parse::validator]  Validator::validate
[         clap::parse::parser]  Parser::add_env: Checking arg `--help`
[         clap::parse::parser]  Parser::add_env: Checking arg `<file>`
[         clap::parse::parser]  Parser::add_defaults
[         clap::parse::parser]  Parser::add_defaults:iter:file:
[         clap::parse::parser]  Parser::add_value: doesn't have conditional defaults
[         clap::parse::parser]  Parser::add_value:iter:file: doesn't have default vals
[         clap::parse::parser]  Parser::add_value:iter:file: doesn't have default missing vals
[      clap::parse::validator]  Validator::validate_conflicts
[      clap::parse::validator]  Validator::validate_exclusive
[      clap::parse::validator]  Validator::gather_conflicts
[      clap::parse::validator]  Validator::validate_required: required=ChildGraph([])
[      clap::parse::validator]  Validator::gather_requirements
[      clap::parse::validator]  Validator::validate_required_unless
[      clap::parse::validator]  Validator::validate_matched_args
[    clap::parse::arg_matcher]  ArgMatcher::get_global_values: global_arg_vec=[help]

Note the single logged App::_build, rather than one-per-subcommand.

@epage epage added C-bug Category: Updating dependencies A-completion Area: completion generator labels Oct 12, 2021
@epage epage added this to the 3.0 milestone Oct 12, 2021
@pksunkara
Copy link
Member

Oof, I forgot about tracking this issue. The context is:

We do lazy building of the subcommand to improve performance in our parser once we match a subcommand. But generators need all the subcommands to be built. I have a TODO marked here about this.

@epage
Copy link
Member Author

epage commented Oct 12, 2021

Thanks for the pointer!

@epage epage self-assigned this Oct 12, 2021
epage added a commit to epage/clap that referenced this issue Oct 12, 2021
`App::get_matches` lazily post-processes `App`s and `Arg`s so we don't
do it to subcommands that are never run (downside being people have to
exercise their full app to get debug_asserts).

`clap_generate` was only post-processing the top-level `App` and `Arg`s,
ignoring the sub-commands.  In clap-rs#2858, we noticed that `--version` was
being left in the completions instead of being removed during the
`_build` step.  We would also have an incorrect `num_vals` and a host of
other problems.

This change adds a `App::_build_all` function for `clap_generate` to use
to eagerly build everything.  By having it there, we make sure
everywhere that needs eager building, gets it (like some tests).

In `clap_generate::utils`, we add a unit test to ensure the subcommand's
`--version` was removed.

For some other tests specifying `.version()`, I added
`AppSettings::PropagateVersion` to make it behave more consistently.
The places I didn't were generally where the version was conditionally
set.

For `clap_generate/tests/generate_completions.rs`, I had to adjust the
`conflicts_with` because the subcommand was inheriting the argument with
it defined *but* the subcommand did not have the argument, tripping up a
debug assert.

Fixes clap-rs#2860
epage added a commit to epage/clap that referenced this issue Oct 12, 2021
`App::get_matches` lazily post-processes `App`s and `Arg`s so we don't
do it to subcommands that are never run (downside being people have to
exercise their full app to get debug_asserts).

`clap_generate` was only post-processing the top-level `App` and `Arg`s,
ignoring the sub-commands.  In clap-rs#2858, we noticed that `--version` was
being left in the completions instead of being removed during the
`_build` step.  We would also have an incorrect `num_vals` and a host of
other problems.

This change adds a `App::_build_all` function for `clap_generate` to use
to eagerly build everything.  By having it there, we make sure
everywhere that needs eager building, gets it (like some tests).

In `clap_generate::utils`, we add a unit test to ensure the subcommand's
`--version` was removed.

For some other tests specifying `.version()`, I added
`AppSettings::PropagateVersion` to make it behave more consistently.
The places I didn't were generally where the version was conditionally
set.

For `clap_generate/tests/generate_completions.rs`, I had to adjust the
`conflicts_with` because the subcommand was inheriting the argument with
it defined *but* the subcommand did not have the argument, tripping up a
debug assert.

Fixes clap-rs#2860
@bors bors bot closed this as completed in a61b608 Oct 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-completion Area: completion generator C-bug Category: Updating dependencies
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants