From d61552a8b8d66bb9f60480b25396ea00259a1ba2 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 18 May 2022 10:07:26 -0500 Subject: [PATCH] refactor(derive): Deconstruct arg matches into enums --- clap_derive/src/derives/args.rs | 20 ++++++++++++----- clap_derive/src/derives/subcommand.rs | 32 ++++++++++++++++++--------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/clap_derive/src/derives/args.rs b/clap_derive/src/derives/args.rs index dddddbef..d80e876b 100644 --- a/clap_derive/src/derives/args.rs +++ b/clap_derive/src/derives/args.rs @@ -132,11 +132,19 @@ pub fn gen_from_arg_matches_for_struct( #[deny(clippy::correctness)] impl #impl_generics clap::FromArgMatches for #struct_name #ty_generics #where_clause { fn from_arg_matches(__clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result { + Self::from_arg_matches_mut(&mut __clap_arg_matches.clone()) + } + + fn from_arg_matches_mut(__clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result { let v = #struct_name #constructor; ::std::result::Result::Ok(v) } fn update_from_arg_matches(&mut self, __clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result<(), clap::Error> { + self.update_from_arg_matches_mut(&mut __clap_arg_matches.clone()) + } + + fn update_from_arg_matches_mut(&mut self, __clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result<(), clap::Error> { #updater ::std::result::Result::Ok(()) } @@ -398,7 +406,7 @@ pub fn gen_constructor(fields: &Punctuated, parent_attribute: &Att quote_spanned! { kind.span()=> #field_name: { if #arg_matches.subcommand_name().map(<#subcmd_type as clap::Subcommand>::has_subcommand).unwrap_or(false) { - Some(<#subcmd_type as clap::FromArgMatches>::from_arg_matches(#arg_matches)?) + Some(<#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut(#arg_matches)?) } else { None } @@ -408,7 +416,7 @@ pub fn gen_constructor(fields: &Punctuated, parent_attribute: &Att _ => { quote_spanned! { kind.span()=> #field_name: { - <#subcmd_type as clap::FromArgMatches>::from_arg_matches(#arg_matches)? + <#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut(#arg_matches)? } } }, @@ -416,7 +424,7 @@ pub fn gen_constructor(fields: &Punctuated, parent_attribute: &Att } Kind::Flatten => quote_spanned! { kind.span()=> - #field_name: clap::FromArgMatches::from_arg_matches(#arg_matches)? + #field_name: clap::FromArgMatches::from_arg_matches_mut(#arg_matches)? }, Kind::Skip(val) => match val { @@ -472,7 +480,7 @@ pub fn gen_updater( }; let updater = quote_spanned! { ty.span()=> - <#subcmd_type as clap::FromArgMatches>::update_from_arg_matches(#field_name, #arg_matches)?; + <#subcmd_type as clap::FromArgMatches>::update_from_arg_matches_mut(#field_name, #arg_matches)?; }; let updater = match **ty { @@ -480,7 +488,7 @@ pub fn gen_updater( if let Some(#field_name) = #field_name.as_mut() { #updater } else { - *#field_name = Some(<#subcmd_type as clap::FromArgMatches>::from_arg_matches( + *#field_name = Some(<#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut( #arg_matches )?); } @@ -500,7 +508,7 @@ pub fn gen_updater( Kind::Flatten => quote_spanned! { kind.span()=> { #access - clap::FromArgMatches::update_from_arg_matches(#field_name, #arg_matches)?; + clap::FromArgMatches::update_from_arg_matches_mut(#field_name, #arg_matches)?; } }, diff --git a/clap_derive/src/derives/subcommand.rs b/clap_derive/src/derives/subcommand.rs index 255e7d5b..f91a821d 100644 --- a/clap_derive/src/derives/subcommand.rs +++ b/clap_derive/src/derives/subcommand.rs @@ -122,7 +122,15 @@ fn gen_from_arg_matches_for_enum( )] #[deny(clippy::correctness)] impl #impl_generics clap::FromArgMatches for #name #ty_generics #where_clause { + fn from_arg_matches(__clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result { + Self::from_arg_matches_mut(&mut __clap_arg_matches.clone()) + } + #from_arg_matches + + fn update_from_arg_matches(&mut self, __clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result<(), clap::Error> { + self.update_from_arg_matches_mut(&mut __clap_arg_matches.clone()) + } #update_from_arg_matches } } @@ -471,7 +479,7 @@ fn gen_from_arg_matches( Unit => quote!(), Unnamed(ref fields) if fields.unnamed.len() == 1 => { let ty = &fields.unnamed[0]; - quote!( ( <#ty as clap::FromArgMatches>::from_arg_matches(__clap_arg_matches)? ) ) + quote!( ( <#ty as clap::FromArgMatches>::from_arg_matches_mut(__clap_arg_matches)? ) ) } Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident), }; @@ -501,7 +509,7 @@ fn gen_from_arg_matches( .map(|__clap_name| <#ty as clap::Subcommand>::has_subcommand(__clap_name)) .unwrap_or_default() { - let __clap_res = <#ty as clap::FromArgMatches>::from_arg_matches(__clap_arg_matches)?; + let __clap_res = <#ty as clap::FromArgMatches>::from_arg_matches_mut(__clap_arg_matches)?; return ::std::result::Result::Ok(#name :: #variant_name (__clap_res)); } } @@ -534,10 +542,11 @@ fn gen_from_arg_matches( }; quote! { - fn from_arg_matches(__clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result { + fn from_arg_matches_mut(__clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result { #( #child_subcommands )else* - if let Some((#subcommand_name_var, #sub_arg_matches_var)) = __clap_arg_matches.subcommand() { + if let Some((#subcommand_name_var, mut __clap_arg_sub_matches)) = __clap_arg_matches.remove_subcommand() { + let #sub_arg_matches_var = &mut __clap_arg_sub_matches; #( #subcommands )* #wildcard @@ -565,7 +574,7 @@ fn gen_update_from_arg_matches( ); match &*attrs.kind() { - // Fallback to `from_arg_matches` + // Fallback to `from_arg_matches_mut` Kind::ExternalSubcommand => None, _ => Some((variant, attrs)), } @@ -603,7 +612,7 @@ fn gen_update_from_arg_matches( if fields.unnamed.len() == 1 { ( quote!((ref mut __clap_arg)), - quote!(clap::FromArgMatches::update_from_arg_matches( + quote!(clap::FromArgMatches::update_from_arg_matches_mut( __clap_arg, __clap_arg_matches )?), @@ -616,7 +625,8 @@ fn gen_update_from_arg_matches( quote! { #name :: #variant_name #pattern if #sub_name == __clap_name => { - let (_, __clap_arg_matches) = __clap_arg_matches.subcommand().unwrap(); + let (_, mut __clap_arg_sub_matches) = __clap_arg_matches.remove_subcommand().unwrap(); + let __clap_arg_matches = &mut __clap_arg_sub_matches; #updater } } @@ -630,7 +640,7 @@ fn gen_update_from_arg_matches( quote! { if <#ty as clap::Subcommand>::has_subcommand(__clap_name) { if let #name :: #variant_name (child) = s { - <#ty as clap::FromArgMatches>::update_from_arg_matches(child, __clap_arg_matches)?; + <#ty as clap::FromArgMatches>::update_from_arg_matches_mut(child, __clap_arg_matches)?; return ::std::result::Result::Ok(()); } } @@ -644,16 +654,16 @@ fn gen_update_from_arg_matches( }); quote! { - fn update_from_arg_matches<'b>( + fn update_from_arg_matches_mut<'b>( &mut self, - __clap_arg_matches: &clap::ArgMatches, + __clap_arg_matches: &mut clap::ArgMatches, ) -> ::std::result::Result<(), clap::Error> { if let Some(__clap_name) = __clap_arg_matches.subcommand_name() { match self { #( #subcommands ),* s => { #( #child_subcommands )* - *s = ::from_arg_matches(__clap_arg_matches)?; + *s = ::from_arg_matches_mut(__clap_arg_matches)?; } } }