• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
2 // Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
3 // Ana Hobden (@hoverbear) <operator@hoverbear.org>
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 //
11 // This work was derived from Structopt (https://github.com/TeXitoi/structopt)
12 // commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
13 // MIT/Apache 2.0 license.
14 
15 use proc_macro2::{Ident, Span, TokenStream};
16 use quote::{format_ident, quote, quote_spanned};
17 use syn::{spanned::Spanned, Data, DeriveInput, FieldsUnnamed, Generics, Variant};
18 
19 use crate::derives::args;
20 use crate::item::{Item, Kind, Name};
21 use crate::utils::{is_simple_ty, subty_if_name};
22 
derive_subcommand(input: &DeriveInput) -> Result<TokenStream, syn::Error>23 pub fn derive_subcommand(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
24     let ident = &input.ident;
25 
26     match input.data {
27         Data::Enum(ref e) => {
28             let name = Name::Derived(ident.clone());
29             let item = Item::from_subcommand_enum(input, name)?;
30             let variants = e
31                 .variants
32                 .iter()
33                 .map(|variant| {
34                     let item =
35                         Item::from_subcommand_variant(variant, item.casing(), item.env_casing())?;
36                     Ok((variant, item))
37                 })
38                 .collect::<Result<Vec<_>, syn::Error>>()?;
39             gen_for_enum(&item, ident, &input.generics, &variants)
40         }
41         _ => abort_call_site!("`#[derive(Subcommand)]` only supports enums"),
42     }
43 }
44 
gen_for_enum( item: &Item, item_name: &Ident, generics: &Generics, variants: &[(&Variant, Item)], ) -> Result<TokenStream, syn::Error>45 pub fn gen_for_enum(
46     item: &Item,
47     item_name: &Ident,
48     generics: &Generics,
49     variants: &[(&Variant, Item)],
50 ) -> Result<TokenStream, syn::Error> {
51     if !matches!(&*item.kind(), Kind::Command(_)) {
52         abort! { item.kind().span(),
53             "`{}` cannot be used with `command`",
54             item.kind().name(),
55         }
56     }
57 
58     let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
59 
60     let from_arg_matches = gen_from_arg_matches(variants)?;
61     let update_from_arg_matches = gen_update_from_arg_matches(variants)?;
62 
63     let augmentation = gen_augment(variants, item, false)?;
64     let augmentation_update = gen_augment(variants, item, true)?;
65     let has_subcommand = gen_has_subcommand(variants)?;
66 
67     Ok(quote! {
68         #[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
69         #[allow(
70             clippy::style,
71             clippy::complexity,
72             clippy::pedantic,
73             clippy::restriction,
74             clippy::perf,
75             clippy::deprecated,
76             clippy::nursery,
77             clippy::cargo,
78             clippy::suspicious_else_formatting,
79             clippy::almost_swapped,
80         )]
81         impl #impl_generics clap::FromArgMatches for #item_name #ty_generics #where_clause {
82             fn from_arg_matches(__clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result<Self, clap::Error> {
83                 Self::from_arg_matches_mut(&mut __clap_arg_matches.clone())
84             }
85 
86             #from_arg_matches
87 
88             fn update_from_arg_matches(&mut self, __clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result<(), clap::Error> {
89                 self.update_from_arg_matches_mut(&mut __clap_arg_matches.clone())
90             }
91             #update_from_arg_matches
92         }
93 
94         #[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
95         #[allow(
96             clippy::style,
97             clippy::complexity,
98             clippy::pedantic,
99             clippy::restriction,
100             clippy::perf,
101             clippy::deprecated,
102             clippy::nursery,
103             clippy::cargo,
104             clippy::suspicious_else_formatting,
105             clippy::almost_swapped,
106         )]
107         impl #impl_generics clap::Subcommand for #item_name #ty_generics #where_clause {
108             fn augment_subcommands <'b>(__clap_app: clap::Command) -> clap::Command {
109                 #augmentation
110             }
111             fn augment_subcommands_for_update <'b>(__clap_app: clap::Command) -> clap::Command {
112                 #augmentation_update
113             }
114             fn has_subcommand(__clap_name: &str) -> bool {
115                 #has_subcommand
116             }
117         }
118     })
119 }
120 
gen_augment( variants: &[(&Variant, Item)], parent_item: &Item, override_required: bool, ) -> Result<TokenStream, syn::Error>121 fn gen_augment(
122     variants: &[(&Variant, Item)],
123     parent_item: &Item,
124     override_required: bool,
125 ) -> Result<TokenStream, syn::Error> {
126     use syn::Fields::*;
127 
128     let app_var = Ident::new("__clap_app", Span::call_site());
129 
130     let mut subcommands = Vec::new();
131     for (variant, item) in variants {
132         let kind = item.kind();
133 
134         let genned = match &*kind {
135             Kind::Skip(_, _) | Kind::Arg(_) | Kind::FromGlobal(_) | Kind::Value => None,
136 
137             Kind::ExternalSubcommand => {
138                 let ty = match variant.fields {
139                     Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
140 
141                     _ => abort!(
142                         variant,
143                         "The enum variant marked with `external_subcommand` must be \
144                              a single-typed tuple, and the type must be either `Vec<String>` \
145                              or `Vec<OsString>`."
146                     ),
147                 };
148                 let deprecations = if !override_required {
149                     item.deprecations()
150                 } else {
151                     quote!()
152                 };
153                 let subty = subty_if_name(ty, "Vec").ok_or_else(|| {
154                     format_err!(
155                         ty.span(),
156                         "The type must be `Vec<_>` \
157                              to be used with `external_subcommand`."
158                     )
159                 })?;
160                 let subcommand = quote_spanned! { kind.span()=>
161                     #deprecations
162                     let #app_var = #app_var
163                         .external_subcommand_value_parser(clap::value_parser!(#subty));
164                 };
165                 Some(subcommand)
166             }
167 
168             Kind::Flatten(_) => match variant.fields {
169                 Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
170                     let ty = &unnamed[0];
171                     let deprecations = if !override_required {
172                         item.deprecations()
173                     } else {
174                         quote!()
175                     };
176                     let next_help_heading = item.next_help_heading();
177                     let next_display_order = item.next_display_order();
178                     let subcommand = if override_required {
179                         quote! {
180                             #deprecations
181                             let #app_var = #app_var
182                                 #next_help_heading
183                                 #next_display_order;
184                             let #app_var = <#ty as clap::Subcommand>::augment_subcommands_for_update(#app_var);
185                         }
186                     } else {
187                         quote! {
188                             #deprecations
189                             let #app_var = #app_var
190                                 #next_help_heading
191                                 #next_display_order;
192                             let #app_var = <#ty as clap::Subcommand>::augment_subcommands(#app_var);
193                         }
194                     };
195                     Some(subcommand)
196                 }
197                 _ => abort!(
198                     variant,
199                     "`flatten` is usable only with single-typed tuple variants"
200                 ),
201             },
202 
203             Kind::Subcommand(_) => {
204                 let subcommand_var = Ident::new("__clap_subcommand", Span::call_site());
205                 let arg_block = match variant.fields {
206                     Named(_) => {
207                         abort!(variant, "non single-typed tuple enums are not supported")
208                     }
209                     Unit => quote!( #subcommand_var ),
210                     Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
211                         let ty = &unnamed[0];
212                         if override_required {
213                             quote_spanned! { ty.span()=>
214                                 {
215                                     <#ty as clap::Subcommand>::augment_subcommands_for_update(#subcommand_var)
216                                 }
217                             }
218                         } else {
219                             quote_spanned! { ty.span()=>
220                                 {
221                                     <#ty as clap::Subcommand>::augment_subcommands(#subcommand_var)
222                                 }
223                             }
224                         }
225                     }
226                     Unnamed(..) => {
227                         abort!(variant, "non single-typed tuple enums are not supported")
228                     }
229                 };
230 
231                 let name = item.cased_name();
232                 let deprecations = if !override_required {
233                     item.deprecations()
234                 } else {
235                     quote!()
236                 };
237                 let initial_app_methods = item.initial_top_level_methods();
238                 let final_from_attrs = item.final_top_level_methods();
239                 let override_methods = if override_required {
240                     quote_spanned! { kind.span()=>
241                         .subcommand_required(false)
242                         .arg_required_else_help(false)
243                     }
244                 } else {
245                     quote!()
246                 };
247                 let subcommand = quote! {
248                     let #app_var = #app_var.subcommand({
249                         #deprecations;
250                         let #subcommand_var = clap::Command::new(#name);
251                         let #subcommand_var = #subcommand_var
252                             .subcommand_required(true)
253                             .arg_required_else_help(true);
254                         let #subcommand_var = #subcommand_var #initial_app_methods;
255                         let #subcommand_var = #arg_block;
256                         #subcommand_var #final_from_attrs #override_methods
257                     });
258                 };
259                 Some(subcommand)
260             }
261 
262             Kind::Command(_) => {
263                 let subcommand_var = Ident::new("__clap_subcommand", Span::call_site());
264                 let sub_augment = match variant.fields {
265                     Named(ref fields) => {
266                         // Defer to `gen_augment` for adding cmd methods
267                         let fields = fields
268                             .named
269                             .iter()
270                             .map(|field| {
271                                 let item =
272                                     Item::from_args_field(field, item.casing(), item.env_casing())?;
273                                 Ok((field, item))
274                             })
275                             .collect::<Result<Vec<_>, syn::Error>>()?;
276                         args::gen_augment(&fields, &subcommand_var, item, override_required)?
277                     }
278                     Unit => {
279                         let arg_block = quote!( #subcommand_var );
280                         let initial_app_methods = item.initial_top_level_methods();
281                         let final_from_attrs = item.final_top_level_methods();
282                         quote! {
283                             let #subcommand_var = #subcommand_var #initial_app_methods;
284                             let #subcommand_var = #arg_block;
285                             #subcommand_var #final_from_attrs
286                         }
287                     }
288                     Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
289                         let ty = &unnamed[0];
290                         let arg_block = if override_required {
291                             quote_spanned! { ty.span()=>
292                                 {
293                                     <#ty as clap::Args>::augment_args_for_update(#subcommand_var)
294                                 }
295                             }
296                         } else {
297                             quote_spanned! { ty.span()=>
298                                 {
299                                     <#ty as clap::Args>::augment_args(#subcommand_var)
300                                 }
301                             }
302                         };
303                         let initial_app_methods = item.initial_top_level_methods();
304                         let final_from_attrs = item.final_top_level_methods();
305                         quote! {
306                             let #subcommand_var = #subcommand_var #initial_app_methods;
307                             let #subcommand_var = #arg_block;
308                             #subcommand_var #final_from_attrs
309                         }
310                     }
311                     Unnamed(..) => {
312                         abort!(variant, "non single-typed tuple enums are not supported")
313                     }
314                 };
315 
316                 let deprecations = if !override_required {
317                     item.deprecations()
318                 } else {
319                     quote!()
320                 };
321                 let name = item.cased_name();
322                 let subcommand = quote! {
323                     let #app_var = #app_var.subcommand({
324                         #deprecations
325                         let #subcommand_var = clap::Command::new(#name);
326                         #sub_augment
327                     });
328                 };
329                 Some(subcommand)
330             }
331         };
332         subcommands.push(genned);
333     }
334 
335     let deprecations = if !override_required {
336         parent_item.deprecations()
337     } else {
338         quote!()
339     };
340     let initial_app_methods = parent_item.initial_top_level_methods();
341     let final_app_methods = parent_item.final_top_level_methods();
342     Ok(quote! {
343         #deprecations;
344         let #app_var = #app_var #initial_app_methods;
345         #( #subcommands )*;
346         #app_var #final_app_methods
347     })
348 }
349 
gen_has_subcommand(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error>350 fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error> {
351     use syn::Fields::*;
352 
353     let mut ext_subcmd = false;
354 
355     let (flatten_variants, variants): (Vec<_>, Vec<_>) = variants
356         .iter()
357         .filter_map(|(variant, item)| {
358             let kind = item.kind();
359             match &*kind {
360                 Kind::Skip(_, _) | Kind::Arg(_) | Kind::FromGlobal(_) | Kind::Value => None,
361 
362                 Kind::ExternalSubcommand => {
363                     ext_subcmd = true;
364                     None
365                 }
366                 Kind::Flatten(_) | Kind::Subcommand(_) | Kind::Command(_) => Some((variant, item)),
367             }
368         })
369         .partition(|(_, item)| {
370             let kind = item.kind();
371             matches!(&*kind, Kind::Flatten(_))
372         });
373 
374     let subcommands = variants.iter().map(|(_variant, item)| {
375         let sub_name = item.cased_name();
376         quote! {
377             if #sub_name == __clap_name {
378                 return true
379             }
380         }
381     });
382     let child_subcommands = flatten_variants
383         .iter()
384         .map(|(variant, _attrs)| match variant.fields {
385             Unnamed(ref fields) if fields.unnamed.len() == 1 => {
386                 let ty = &fields.unnamed[0];
387                 Ok(quote! {
388                     if <#ty as clap::Subcommand>::has_subcommand(__clap_name) {
389                         return true;
390                     }
391                 })
392             }
393             _ => abort!(
394                 variant,
395                 "`flatten` is usable only with single-typed tuple variants"
396             ),
397         })
398         .collect::<Result<Vec<_>, syn::Error>>()?;
399 
400     let genned = if ext_subcmd {
401         quote! { true }
402     } else {
403         quote! {
404             #( #subcommands )*
405 
406             #( #child_subcommands )else*
407 
408             false
409         }
410     };
411     Ok(genned)
412 }
413 
gen_from_arg_matches(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error>414 fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error> {
415     use syn::Fields::*;
416 
417     let subcommand_name_var = format_ident!("__clap_name");
418     let sub_arg_matches_var = format_ident!("__clap_arg_matches");
419 
420     let mut ext_subcmd = None;
421     let mut flatten_variants = Vec::new();
422     let mut unflatten_variants = Vec::new();
423     for (variant, item) in variants {
424         let kind = item.kind();
425         match &*kind {
426             Kind::Skip(_, _) | Kind::Arg(_) | Kind::FromGlobal(_) | Kind::Value => {}
427 
428             Kind::ExternalSubcommand => {
429                 if ext_subcmd.is_some() {
430                     abort!(
431                         item.kind().span(),
432                         "Only one variant can be marked with `external_subcommand`, \
433                          this is the second"
434                     );
435                 }
436 
437                 let ty = match variant.fields {
438                     Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
439 
440                     _ => abort!(
441                         variant,
442                         "The enum variant marked with `external_subcommand` must be \
443                          a single-typed tuple, and the type must be either `Vec<String>` \
444                          or `Vec<OsString>`."
445                     ),
446                 };
447 
448                 let (span, str_ty) = match subty_if_name(ty, "Vec") {
449                     Some(subty) => {
450                         if is_simple_ty(subty, "String") {
451                             (subty.span(), quote!(::std::string::String))
452                         } else if is_simple_ty(subty, "OsString") {
453                             (subty.span(), quote!(::std::ffi::OsString))
454                         } else {
455                             abort!(
456                                 ty.span(),
457                                 "The type must be either `Vec<String>` or `Vec<OsString>` \
458                                  to be used with `external_subcommand`."
459                             );
460                         }
461                     }
462 
463                     None => abort!(
464                         ty.span(),
465                         "The type must be either `Vec<String>` or `Vec<OsString>` \
466                          to be used with `external_subcommand`."
467                     ),
468                 };
469 
470                 ext_subcmd = Some((span, &variant.ident, str_ty));
471             }
472             Kind::Flatten(_) | Kind::Subcommand(_) | Kind::Command(_) => {
473                 if matches!(&*item.kind(), Kind::Flatten(_)) {
474                     flatten_variants.push((variant, item));
475                 } else {
476                     unflatten_variants.push((variant, item));
477                 }
478             }
479         }
480     }
481 
482     let subcommands = unflatten_variants.iter().map(|(variant, item)| {
483         let sub_name = item.cased_name();
484         let variant_name = &variant.ident;
485         let constructor_block = match variant.fields {
486             Named(ref fields) => {
487                 let fields = fields
488                     .named
489                     .iter()
490                     .map(|field| {
491                         let item = Item::from_args_field(field, item.casing(), item.env_casing())?;
492                         Ok((field, item))
493                     })
494                     .collect::<Result<Vec<_>, syn::Error>>()?;
495                 args::gen_constructor(&fields)?
496             },
497             Unit => quote!(),
498             Unnamed(ref fields) if fields.unnamed.len() == 1 => {
499                 let ty = &fields.unnamed[0];
500                 quote!( ( <#ty as clap::FromArgMatches>::from_arg_matches_mut(__clap_arg_matches)? ) )
501             }
502             Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident),
503         };
504 
505         Ok(quote! {
506             if #subcommand_name_var == #sub_name && !#sub_arg_matches_var.contains_id("") {
507                 return ::std::result::Result::Ok(Self :: #variant_name #constructor_block)
508             }
509         })
510     }).collect::<Result<Vec<_>, syn::Error>>()?;
511     let child_subcommands = flatten_variants.iter().map(|(variant, _attrs)| {
512         let variant_name = &variant.ident;
513         match variant.fields {
514             Unnamed(ref fields) if fields.unnamed.len() == 1 => {
515                 let ty = &fields.unnamed[0];
516                 Ok(quote! {
517                     if __clap_arg_matches
518                         .subcommand_name()
519                         .map(|__clap_name| <#ty as clap::Subcommand>::has_subcommand(__clap_name))
520                         .unwrap_or_default()
521                     {
522                         let __clap_res = <#ty as clap::FromArgMatches>::from_arg_matches_mut(__clap_arg_matches)?;
523                         return ::std::result::Result::Ok(Self :: #variant_name (__clap_res));
524                     }
525                 })
526             }
527             _ => abort!(
528                 variant,
529                 "`flatten` is usable only with single-typed tuple variants"
530             ),
531         }
532     }).collect::<Result<Vec<_>, syn::Error>>()?;
533 
534     let wildcard = match ext_subcmd {
535         Some((span, var_name, str_ty)) => quote_spanned! { span=>
536                 ::std::result::Result::Ok(Self::#var_name(
537                     ::std::iter::once(#str_ty::from(#subcommand_name_var))
538                     .chain(
539                         #sub_arg_matches_var
540                             .remove_many::<#str_ty>("")
541                             .unwrap()
542                             .map(#str_ty::from)
543                     )
544                     .collect::<::std::vec::Vec<_>>()
545                 ))
546         },
547 
548         None => quote! {
549             ::std::result::Result::Err(clap::Error::raw(clap::error::ErrorKind::InvalidSubcommand, format!("The subcommand '{}' wasn't recognized", #subcommand_name_var)))
550         },
551     };
552 
553     let raw_deprecated = args::raw_deprecated();
554     Ok(quote! {
555         fn from_arg_matches_mut(__clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result<Self, clap::Error> {
556             #raw_deprecated
557 
558             #( #child_subcommands )else*
559 
560             if let Some((#subcommand_name_var, mut __clap_arg_sub_matches)) = __clap_arg_matches.remove_subcommand() {
561                 let #sub_arg_matches_var = &mut __clap_arg_sub_matches;
562                 #( #subcommands )*
563 
564                 #wildcard
565             } else {
566                 ::std::result::Result::Err(clap::Error::raw(clap::error::ErrorKind::MissingSubcommand, "A subcommand is required but one was not provided."))
567             }
568         }
569     })
570 }
571 
gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error>572 fn gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error> {
573     use syn::Fields::*;
574 
575     let (flatten, variants): (Vec<_>, Vec<_>) = variants
576         .iter()
577         .filter_map(|(variant, item)| {
578             let kind = item.kind();
579             match &*kind {
580                 // Fallback to `from_arg_matches_mut`
581                 Kind::Skip(_, _)
582                 | Kind::Arg(_)
583                 | Kind::FromGlobal(_)
584                 | Kind::Value
585                 | Kind::ExternalSubcommand => None,
586                 Kind::Flatten(_) | Kind::Subcommand(_) | Kind::Command(_) => Some((variant, item)),
587             }
588         })
589         .partition(|(_, item)| {
590             let kind = item.kind();
591             matches!(&*kind, Kind::Flatten(_))
592         });
593 
594     let subcommands = variants.iter().map(|(variant, item)| {
595         let sub_name = item.cased_name();
596         let variant_name = &variant.ident;
597         let (pattern, updater) = match variant.fields {
598             Named(ref fields) => {
599                 let field_names = fields.named.iter().map(|field| {
600                     field.ident.as_ref().unwrap()
601                 }).collect::<Vec<_>>();
602                 let fields = fields
603                     .named
604                     .iter()
605                     .map(|field| {
606                         let item = Item::from_args_field(field, item.casing(), item.env_casing())?;
607                         Ok((field, item))
608                     })
609                     .collect::<Result<Vec<_>, syn::Error>>()?;
610                 let update = args::gen_updater(&fields, false)?;
611                 (quote!( { #( #field_names, )* }), quote!( { #update } ))
612             }
613             Unit => (quote!(), quote!({})),
614             Unnamed(ref fields) => {
615                 if fields.unnamed.len() == 1 {
616                     (
617                         quote!((ref mut __clap_arg)),
618                         quote!(clap::FromArgMatches::update_from_arg_matches_mut(
619                             __clap_arg,
620                             __clap_arg_matches
621                         )?),
622                     )
623                 } else {
624                     abort_call_site!("{}: tuple enums are not supported", variant.ident)
625                 }
626             }
627         };
628 
629         Ok(quote! {
630             Self :: #variant_name #pattern if #sub_name == __clap_name => {
631                 let (_, mut __clap_arg_sub_matches) = __clap_arg_matches.remove_subcommand().unwrap();
632                 let __clap_arg_matches = &mut __clap_arg_sub_matches;
633                 #updater
634             }
635         })
636     }).collect::<Result<Vec<_>, _>>()?;
637 
638     let child_subcommands = flatten.iter().map(|(variant, _attrs)| {
639         let variant_name = &variant.ident;
640         match variant.fields {
641             Unnamed(ref fields) if fields.unnamed.len() == 1 => {
642                 let ty = &fields.unnamed[0];
643                 Ok(quote! {
644                     if <#ty as clap::Subcommand>::has_subcommand(__clap_name) {
645                         if let Self :: #variant_name (child) = s {
646                             <#ty as clap::FromArgMatches>::update_from_arg_matches_mut(child, __clap_arg_matches)?;
647                             return ::std::result::Result::Ok(());
648                         }
649                     }
650                 })
651             }
652             _ => abort!(
653                 variant,
654                 "`flatten` is usable only with single-typed tuple variants"
655             ),
656         }
657     }).collect::<Result<Vec<_>, _>>()?;
658 
659     let raw_deprecated = args::raw_deprecated();
660     Ok(quote! {
661         fn update_from_arg_matches_mut<'b>(
662             &mut self,
663             __clap_arg_matches: &mut clap::ArgMatches,
664         ) -> ::std::result::Result<(), clap::Error> {
665             #raw_deprecated
666 
667             if let Some(__clap_name) = __clap_arg_matches.subcommand_name() {
668                 match self {
669                     #( #subcommands ),*
670                     s => {
671                         #( #child_subcommands )*
672                         *s = <Self as clap::FromArgMatches>::from_arg_matches_mut(__clap_arg_matches)?;
673                     }
674                 }
675             }
676             ::std::result::Result::Ok(())
677         }
678     })
679 }
680