From d05622d015bb8a678b691699df30b8f2529fcfa6 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 25 Oct 2021 16:28:23 -0500 Subject: [PATCH] fix(derive): Don't duplicate subcommand aliases When an anonymous struct is inside of an enum, we end up applying the App methods twice, once for the `augment_args` and once for variant. This consolidates those calls. Fixes #2898 --- clap_derive/src/derives/subcommand.rs | 29 +++++++++++++++++++-------- clap_derive/tests/issues.rs | 26 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/clap_derive/src/derives/subcommand.rs b/clap_derive/src/derives/subcommand.rs index 6edb0c13..e64d764e 100644 --- a/clap_derive/src/derives/subcommand.rs +++ b/clap_derive/src/derives/subcommand.rs @@ -240,14 +240,24 @@ fn gen_augment( _ => { let subcommand_var = Ident::new("__clap_subcommand", Span::call_site()); - let arg_block = match variant.fields { + let sub_augment = match variant.fields { Named(ref fields) => { + // Defer to `gen_augment` for adding app methods args::gen_augment(&fields.named, &subcommand_var, &attrs, override_required) } - Unit => quote!( #subcommand_var ), + Unit => { + let arg_block = quote!( #subcommand_var ); + let initial_app_methods = attrs.initial_top_level_methods(); + let final_from_attrs = attrs.final_top_level_methods(); + quote! { + let #subcommand_var = #subcommand_var #initial_app_methods; + let #subcommand_var = #arg_block; + #subcommand_var #final_from_attrs + } + }, Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { let ty = &unnamed[0]; - if override_required { + let arg_block = if override_required { quote_spanned! { ty.span()=> { <#ty as clap::Args>::augment_args_for_update(#subcommand_var) @@ -259,6 +269,13 @@ fn gen_augment( <#ty as clap::Args>::augment_args(#subcommand_var) } } + }; + let initial_app_methods = attrs.initial_top_level_methods(); + let final_from_attrs = attrs.final_top_level_methods(); + quote! { + let #subcommand_var = #subcommand_var #initial_app_methods; + let #subcommand_var = #arg_block; + #subcommand_var #final_from_attrs } } Unnamed(..) => { @@ -267,14 +284,10 @@ fn gen_augment( }; let name = attrs.cased_name(); - let initial_app_methods = attrs.initial_top_level_methods(); - let final_from_attrs = attrs.final_top_level_methods(); let subcommand = quote! { let #app_var = #app_var.subcommand({ let #subcommand_var = clap::App::new(#name); - let #subcommand_var = #subcommand_var #initial_app_methods; - let #subcommand_var = #arg_block; - #subcommand_var #final_from_attrs + #sub_augment }); }; Some(subcommand) diff --git a/clap_derive/tests/issues.rs b/clap_derive/tests/issues.rs index bdf797cc..1e4730c4 100644 --- a/clap_derive/tests/issues.rs +++ b/clap_derive/tests/issues.rs @@ -75,6 +75,32 @@ fn issue_324() { assert!(help.contains("MY_VERSION")); } +#[test] +fn issue_418() { + #[derive(Debug, Parser)] + struct Opts { + #[clap(subcommand)] + /// The command to run + command: Command, + } + + #[derive(Debug, Subcommand)] + enum Command { + /// Reticulate the splines + #[clap(visible_alias = "ret")] + Reticulate { + /// How many splines + num_splines: u8, + }, + /// Frobnicate the rest + #[clap(visible_alias = "frob")] + Frobnicate, + } + + let help = get_long_help::(); + assert!(help.contains("Reticulate the splines [aliases: ret]")); +} + #[test] fn issue_490() { use clap::Parser;