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

fix(builder): Fully recurse when building #3670

Merged
merged 2 commits into from May 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion clap_complete/tests/snapshots/sub_subcommands.bash
Expand Up @@ -73,7 +73,7 @@ _my-app() {
return 0
;;
my__app__some_cmd__help)
opts="-h -V --help --version <SUBCOMMAND>..."
opts="<SUBCOMMAND>..."
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
Expand Down
4 changes: 0 additions & 4 deletions clap_complete/tests/snapshots/sub_subcommands.elvish
Expand Up @@ -53,10 +53,6 @@ set edit:completion:arg-completer[my-app] = {|@words|
cand --version 'Print version information'
}
&'my-app;some_cmd;help'= {
cand -h 'Print help information'
cand --help 'Print help information'
cand -V 'Print version information'
cand --version 'Print version information'
}
&'my-app;help'= {
}
Expand Down
2 changes: 0 additions & 2 deletions clap_complete/tests/snapshots/sub_subcommands.fish
Expand Up @@ -14,5 +14,3 @@ complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and not __fish_seen
complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -l config -d 'the other case to test' -r -f -a "{Lest quotes aren/'t escaped. }"
complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -s h -l help -d 'Print help information'
complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from sub_cmd" -s V -l version -d 'Print version information'
complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from help" -s h -l help -d 'Print help information'
complete -c my-app -n "__fish_seen_subcommand_from some_cmd; and __fish_seen_subcommand_from help" -s V -l version -d 'Print version information'
4 changes: 0 additions & 4 deletions clap_complete/tests/snapshots/sub_subcommands.ps1
Expand Up @@ -60,10 +60,6 @@ Register-ArgumentCompleter -Native -CommandName 'my-app' -ScriptBlock {
break
}
'my-app;some_cmd;help' {
[CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help information')
[CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help information')
[CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version information')
[CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version information')
break
}
'my-app;help' {
Expand Down
4 changes: 0 additions & 4 deletions clap_complete/tests/snapshots/sub_subcommands.zsh
Expand Up @@ -70,10 +70,6 @@ _arguments "${_arguments_options[@]}" /
;;
(help)
_arguments "${_arguments_options[@]}" /
'-h[Print help information]' /
'--help[Print help information]' /
'-V[Print version information]' /
'--version[Print version information]' /
'*::subcommand -- The subcommand whose help message to display:' /
&& ret=0
;;
Expand Down
10 changes: 0 additions & 10 deletions clap_complete_fig/tests/snapshots/sub_subcommands.fig.js
Expand Up @@ -56,16 +56,6 @@ const completion: Fig.Spec = {
{
name: "help",
description: "Print this message or the help of the given subcommand(s)",
options: [
{
name: ["-h", "--help"],
description: "Print help information",
},
{
name: ["-V", "--version"],
description: "Print version information",
},
],
args: {
name: "subcommand",
isOptional: true,
Expand Down
10 changes: 7 additions & 3 deletions src/build/command.rs
Expand Up @@ -4008,15 +4008,19 @@ impl<'help> App<'help> {
/// Call this on the top-level [`Command`] when done building and before reading state for
/// cases like completions, custom help output, etc.
pub fn build(&mut self) {
self._build_recursive();
self._build_bin_names_internal();
}

pub(crate) fn _build_recursive(&mut self) {
self._build_self();
for subcmd in self.get_subcommands_mut() {
subcmd._build_self();
subcmd._build_recursive();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK The reason for not building everything was performance concerns. We only built the subcommands people were using.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two build paths. The incremental build path used by parsing and the "build all" build path used by completions, etc. They share _build_self but how they walk and how they generate bin names is separate.

}
self._build_bin_names_internal();
}

pub(crate) fn _build_self(&mut self) {
debug!("Command::_build");
debug!("Command::_build: name={:?}", self.get_name());
if !self.settings.is_set(AppSettings::Built) {
// Make sure all the globally set flags apply to us as well
self.settings = self.settings | self.g_settings;
Expand Down
16 changes: 16 additions & 0 deletions tests/builder/tests.rs
Expand Up @@ -408,3 +408,19 @@ fn mut_arg_all() {
cmd = cmd.mut_arg(arg_name, |arg| arg.hide_possible_values(true));
}
}

#[test]
fn issue_3669_command_build_recurses() {
let mut cmd = Command::new("ctest").subcommand(
Command::new("subcmd").subcommand(
Command::new("multi")
.about("tests subcommands")
.author("Kevin K. <kbknapp@gmail.com>")
.version("0.1")
.arg(clap::arg!(
<FLAG> "tests flags"
)),
),
);
cmd.build();
}