]> git.proxmox.com Git - rustc.git/blob - vendor/clap_derive-3.2.18/src/derives/args.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / vendor / clap_derive-3.2.18 / src / derives / args.rs
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 crate::{
16 attrs::{Attrs, Kind, Name, ParserKind, DEFAULT_CASING, DEFAULT_ENV_CASING},
17 dummies,
18 utils::{inner_type, is_simple_ty, sub_type, Sp, Ty},
19 };
20
21 use proc_macro2::{Ident, Span, TokenStream};
22 use proc_macro_error::{abort, abort_call_site};
23 use quote::{format_ident, quote, quote_spanned};
24 use syn::{
25 punctuated::Punctuated, spanned::Spanned, token::Comma, Attribute, Data, DataStruct,
26 DeriveInput, Field, Fields, Generics, Type,
27 };
28
29 pub fn derive_args(input: &DeriveInput) -> TokenStream {
30 let ident = &input.ident;
31
32 dummies::args(ident);
33
34 match input.data {
35 Data::Struct(DataStruct {
36 fields: Fields::Named(ref fields),
37 ..
38 }) => gen_for_struct(ident, &input.generics, &fields.named, &input.attrs),
39 Data::Struct(DataStruct {
40 fields: Fields::Unit,
41 ..
42 }) => gen_for_struct(
43 ident,
44 &input.generics,
45 &Punctuated::<Field, Comma>::new(),
46 &input.attrs,
47 ),
48 _ => abort_call_site!("`#[derive(Args)]` only supports non-tuple structs"),
49 }
50 }
51
52 pub fn gen_for_struct(
53 struct_name: &Ident,
54 generics: &Generics,
55 fields: &Punctuated<Field, Comma>,
56 attrs: &[Attribute],
57 ) -> TokenStream {
58 let from_arg_matches = gen_from_arg_matches_for_struct(struct_name, generics, fields, attrs);
59
60 let attrs = Attrs::from_struct(
61 Span::call_site(),
62 attrs,
63 Name::Derived(struct_name.clone()),
64 Sp::call_site(DEFAULT_CASING),
65 Sp::call_site(DEFAULT_ENV_CASING),
66 );
67 let app_var = Ident::new("__clap_app", Span::call_site());
68 let augmentation = gen_augment(fields, &app_var, &attrs, false);
69 let augmentation_update = gen_augment(fields, &app_var, &attrs, true);
70
71 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
72
73 quote! {
74 #from_arg_matches
75
76 #[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
77 #[allow(
78 clippy::style,
79 clippy::complexity,
80 clippy::pedantic,
81 clippy::restriction,
82 clippy::perf,
83 clippy::deprecated,
84 clippy::nursery,
85 clippy::cargo,
86 clippy::suspicious_else_formatting,
87 )]
88 #[deny(clippy::correctness)]
89 impl #impl_generics clap::Args for #struct_name #ty_generics #where_clause {
90 fn augment_args<'b>(#app_var: clap::Command<'b>) -> clap::Command<'b> {
91 #augmentation
92 }
93 fn augment_args_for_update<'b>(#app_var: clap::Command<'b>) -> clap::Command<'b> {
94 #augmentation_update
95 }
96 }
97 }
98 }
99
100 pub fn gen_from_arg_matches_for_struct(
101 struct_name: &Ident,
102 generics: &Generics,
103 fields: &Punctuated<Field, Comma>,
104 attrs: &[Attribute],
105 ) -> TokenStream {
106 let attrs = Attrs::from_struct(
107 Span::call_site(),
108 attrs,
109 Name::Derived(struct_name.clone()),
110 Sp::call_site(DEFAULT_CASING),
111 Sp::call_site(DEFAULT_ENV_CASING),
112 );
113
114 let constructor = gen_constructor(fields, &attrs);
115 let updater = gen_updater(fields, &attrs, true);
116 let raw_deprecated = raw_deprecated();
117
118 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
119
120 quote! {
121 #[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
122 #[allow(
123 clippy::style,
124 clippy::complexity,
125 clippy::pedantic,
126 clippy::restriction,
127 clippy::perf,
128 clippy::deprecated,
129 clippy::nursery,
130 clippy::cargo,
131 clippy::suspicious_else_formatting,
132 )]
133 #[deny(clippy::correctness)]
134 impl #impl_generics clap::FromArgMatches for #struct_name #ty_generics #where_clause {
135 fn from_arg_matches(__clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result<Self, clap::Error> {
136 Self::from_arg_matches_mut(&mut __clap_arg_matches.clone())
137 }
138
139 fn from_arg_matches_mut(__clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result<Self, clap::Error> {
140 #raw_deprecated
141 let v = #struct_name #constructor;
142 ::std::result::Result::Ok(v)
143 }
144
145 fn update_from_arg_matches(&mut self, __clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result<(), clap::Error> {
146 self.update_from_arg_matches_mut(&mut __clap_arg_matches.clone())
147 }
148
149 fn update_from_arg_matches_mut(&mut self, __clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result<(), clap::Error> {
150 #raw_deprecated
151 #updater
152 ::std::result::Result::Ok(())
153 }
154 }
155 }
156 }
157
158 /// Generate a block of code to add arguments/subcommands corresponding to
159 /// the `fields` to an cmd.
160 pub fn gen_augment(
161 fields: &Punctuated<Field, Comma>,
162 app_var: &Ident,
163 parent_attribute: &Attrs,
164 override_required: bool,
165 ) -> TokenStream {
166 let mut subcmds = fields.iter().filter_map(|field| {
167 let attrs = Attrs::from_field(
168 field,
169 parent_attribute.casing(),
170 parent_attribute.env_casing(),
171 );
172 let kind = attrs.kind();
173 if let Kind::Subcommand(ty) = &*kind {
174 let subcmd_type = match (**ty, sub_type(&field.ty)) {
175 (Ty::Option, Some(sub_type)) => sub_type,
176 _ => &field.ty,
177 };
178 let required = if **ty == Ty::Option {
179 quote!()
180 } else {
181 quote_spanned! { kind.span()=>
182 #[allow(deprecated)]
183 let #app_var = #app_var.setting(
184 clap::AppSettings::SubcommandRequiredElseHelp
185 );
186 }
187 };
188
189 let span = field.span();
190 let ts = if override_required {
191 quote! {
192 let #app_var = <#subcmd_type as clap::Subcommand>::augment_subcommands_for_update( #app_var );
193 }
194 } else{
195 quote! {
196 let #app_var = <#subcmd_type as clap::Subcommand>::augment_subcommands( #app_var );
197 #required
198 }
199 };
200 Some((span, ts))
201 } else {
202 None
203 }
204 });
205 let subcmd = subcmds.next().map(|(_, ts)| ts);
206 if let Some((span, _)) = subcmds.next() {
207 abort!(
208 span,
209 "multiple subcommand sets are not allowed, that's the second"
210 );
211 }
212
213 let args = fields.iter().filter_map(|field| {
214 let attrs = Attrs::from_field(
215 field,
216 parent_attribute.casing(),
217 parent_attribute.env_casing(),
218 );
219 let kind = attrs.kind();
220 match &*kind {
221 Kind::Subcommand(_)
222 | Kind::Skip(_)
223 | Kind::FromGlobal(_)
224 | Kind::ExternalSubcommand => None,
225 Kind::Flatten => {
226 let ty = &field.ty;
227 let old_heading_var = format_ident!("__clap_old_heading");
228 let next_help_heading = attrs.next_help_heading();
229 let next_display_order = attrs.next_display_order();
230 if override_required {
231 Some(quote_spanned! { kind.span()=>
232 let #old_heading_var = #app_var.get_next_help_heading();
233 let #app_var = #app_var #next_help_heading #next_display_order;
234 let #app_var = <#ty as clap::Args>::augment_args_for_update(#app_var);
235 let #app_var = #app_var.next_help_heading(#old_heading_var);
236 })
237 } else {
238 Some(quote_spanned! { kind.span()=>
239 let #old_heading_var = #app_var.get_next_help_heading();
240 let #app_var = #app_var #next_help_heading #next_display_order;
241 let #app_var = <#ty as clap::Args>::augment_args(#app_var);
242 let #app_var = #app_var.next_help_heading(#old_heading_var);
243 })
244 }
245 }
246 Kind::Arg(ty) => {
247 let convert_type = inner_type(&field.ty);
248
249 let parser = attrs.parser(&field.ty);
250
251 let value_parser = attrs.value_parser(&field.ty);
252 let action = attrs.action(&field.ty);
253 let func = &parser.func;
254
255 let mut occurrences = false;
256 let mut flag = false;
257 let validator = match *parser.kind {
258 _ if attrs.ignore_parser() || attrs.is_enum() => quote!(),
259 ParserKind::TryFromStr => quote_spanned! { func.span()=>
260 .validator(|s| {
261 #func(s)
262 .map(|_: #convert_type| ())
263 })
264 },
265 ParserKind::TryFromOsStr => quote_spanned! { func.span()=>
266 .validator_os(|s| #func(s).map(|_: #convert_type| ()))
267 },
268 ParserKind::FromStr | ParserKind::FromOsStr => quote!(),
269 ParserKind::FromFlag => {
270 flag = true;
271 quote!()
272 }
273 ParserKind::FromOccurrences => {
274 occurrences = true;
275 quote!()
276 }
277 };
278 let parse_deprecation = match *parser.kind {
279 _ if !attrs.explicit_parser() || cfg!(not(feature = "deprecated")) => quote!(),
280 ParserKind::FromStr => quote_spanned! { func.span()=>
281 #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]`")]
282 fn parse_from_str() {
283 }
284 parse_from_str();
285 },
286 ParserKind::TryFromStr => quote_spanned! { func.span()=>
287 #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]`")]
288 fn parse_try_from_str() {
289 }
290 parse_try_from_str();
291 },
292 ParserKind::FromOsStr => quote_spanned! { func.span()=>
293 #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser)]` for `PathBuf` or `#[clap(value_parser = ...)]` with a custom `TypedValueParser`")]
294 fn parse_from_os_str() {
295 }
296 parse_from_os_str();
297 },
298 ParserKind::TryFromOsStr => quote_spanned! { func.span()=>
299 #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]` with a custom `TypedValueParser`")]
300 fn parse_try_from_os_str() {
301 }
302 parse_try_from_os_str();
303 },
304 ParserKind::FromFlag => quote_spanned! { func.span()=>
305 #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(action = ArgAction::SetTrue)]`")]
306 fn parse_from_flag() {
307 }
308 parse_from_flag();
309 },
310 ParserKind::FromOccurrences => quote_spanned! { func.span()=>
311 #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(action = ArgAction::Count)]` with a field type of `u8`")]
312 fn parse_from_occurrences() {
313 }
314 parse_from_occurrences();
315 },
316 };
317
318 let value_name = attrs.value_name();
319 let possible_values = if attrs.is_enum() && !attrs.ignore_parser() {
320 gen_value_enum_possible_values(convert_type)
321 } else {
322 quote!()
323 };
324
325 let implicit_methods = match **ty {
326 Ty::Option => {
327 quote_spanned! { ty.span()=>
328 .takes_value(true)
329 .value_name(#value_name)
330 #possible_values
331 #validator
332 #value_parser
333 #action
334 }
335 }
336
337 Ty::OptionOption => quote_spanned! { ty.span()=>
338 .takes_value(true)
339 .value_name(#value_name)
340 .min_values(0)
341 .max_values(1)
342 .multiple_values(false)
343 #possible_values
344 #validator
345 #value_parser
346 #action
347 },
348
349 Ty::OptionVec => {
350 if attrs.ignore_parser() {
351 if attrs.is_positional() {
352 quote_spanned! { ty.span()=>
353 .takes_value(true)
354 .value_name(#value_name)
355 .multiple_values(true) // action won't be sufficient for getting multiple
356 #possible_values
357 #validator
358 #value_parser
359 #action
360 }
361 } else {
362 quote_spanned! { ty.span()=>
363 .takes_value(true)
364 .value_name(#value_name)
365 #possible_values
366 #validator
367 #value_parser
368 #action
369 }
370 }
371 } else {
372 quote_spanned! { ty.span()=>
373 .takes_value(true)
374 .value_name(#value_name)
375 .multiple_occurrences(true)
376 #possible_values
377 #validator
378 #value_parser
379 #action
380 }
381 }
382 }
383
384 Ty::Vec => {
385 if attrs.ignore_parser() {
386 if attrs.is_positional() {
387 quote_spanned! { ty.span()=>
388 .takes_value(true)
389 .value_name(#value_name)
390 .multiple_values(true) // action won't be sufficient for getting multiple
391 #possible_values
392 #validator
393 #value_parser
394 #action
395 }
396 } else {
397 quote_spanned! { ty.span()=>
398 .takes_value(true)
399 .value_name(#value_name)
400 #possible_values
401 #validator
402 #value_parser
403 #action
404 }
405 }
406 } else {
407 quote_spanned! { ty.span()=>
408 .takes_value(true)
409 .value_name(#value_name)
410 .multiple_occurrences(true)
411 #possible_values
412 #validator
413 #value_parser
414 #action
415 }
416 }
417 }
418
419 Ty::Other if occurrences => quote_spanned! { ty.span()=>
420 .multiple_occurrences(true)
421 },
422
423 Ty::Other if flag => quote_spanned! { ty.span()=>
424 .takes_value(false)
425 },
426
427 Ty::Other => {
428 let required = attrs.find_default_method().is_none() && !override_required;
429 // `ArgAction::takes_values` is assuming `ArgAction::default_value` will be
430 // set though that won't always be true but this should be good enough,
431 // otherwise we'll report an "arg required" error when unwrapping.
432 let action_value = action.args();
433 quote_spanned! { ty.span()=>
434 .takes_value(true)
435 .value_name(#value_name)
436 .required(#required && #action_value.takes_values())
437 #possible_values
438 #validator
439 #value_parser
440 #action
441 }
442 }
443 };
444
445 let id = attrs.id();
446 let explicit_methods = attrs.field_methods(true);
447
448 Some(quote_spanned! { field.span()=>
449 let #app_var = #app_var.arg({
450 #parse_deprecation
451
452 #[allow(deprecated)]
453 let arg = clap::Arg::new(#id)
454 #implicit_methods;
455
456 let arg = arg
457 #explicit_methods;
458 arg
459 });
460 })
461 }
462 }
463 });
464
465 let initial_app_methods = parent_attribute.initial_top_level_methods();
466 let final_app_methods = parent_attribute.final_top_level_methods();
467 quote! {{
468 let #app_var = #app_var #initial_app_methods;
469 #( #args )*
470 #subcmd
471 #app_var #final_app_methods
472 }}
473 }
474
475 fn gen_value_enum_possible_values(ty: &Type) -> TokenStream {
476 quote_spanned! { ty.span()=>
477 .possible_values(<#ty as clap::ValueEnum>::value_variants().iter().filter_map(clap::ValueEnum::to_possible_value))
478 }
479 }
480
481 pub fn gen_constructor(fields: &Punctuated<Field, Comma>, parent_attribute: &Attrs) -> TokenStream {
482 let fields = fields.iter().map(|field| {
483 let attrs = Attrs::from_field(
484 field,
485 parent_attribute.casing(),
486 parent_attribute.env_casing(),
487 );
488 let field_name = field.ident.as_ref().unwrap();
489 let kind = attrs.kind();
490 let arg_matches = format_ident!("__clap_arg_matches");
491 match &*kind {
492 Kind::ExternalSubcommand => {
493 abort! { kind.span(),
494 "`external_subcommand` can be used only on enum variants"
495 }
496 }
497 Kind::Subcommand(ty) => {
498 let subcmd_type = match (**ty, sub_type(&field.ty)) {
499 (Ty::Option, Some(sub_type)) => sub_type,
500 _ => &field.ty,
501 };
502 match **ty {
503 Ty::Option => {
504 quote_spanned! { kind.span()=>
505 #field_name: {
506 if #arg_matches.subcommand_name().map(<#subcmd_type as clap::Subcommand>::has_subcommand).unwrap_or(false) {
507 Some(<#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut(#arg_matches)?)
508 } else {
509 None
510 }
511 }
512 }
513 },
514 _ => {
515 quote_spanned! { kind.span()=>
516 #field_name: {
517 <#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut(#arg_matches)?
518 }
519 }
520 },
521 }
522 }
523
524 Kind::Flatten => quote_spanned! { kind.span()=>
525 #field_name: clap::FromArgMatches::from_arg_matches_mut(#arg_matches)?
526 },
527
528 Kind::Skip(val) => match val {
529 None => quote_spanned!(kind.span()=> #field_name: Default::default()),
530 Some(val) => quote_spanned!(kind.span()=> #field_name: (#val).into()),
531 },
532
533 Kind::Arg(ty) | Kind::FromGlobal(ty) => {
534 gen_parsers(&attrs, ty, field_name, field, None)
535 }
536 }
537 });
538
539 quote! {{
540 #( #fields ),*
541 }}
542 }
543
544 pub fn gen_updater(
545 fields: &Punctuated<Field, Comma>,
546 parent_attribute: &Attrs,
547 use_self: bool,
548 ) -> TokenStream {
549 let fields = fields.iter().map(|field| {
550 let attrs = Attrs::from_field(
551 field,
552 parent_attribute.casing(),
553 parent_attribute.env_casing(),
554 );
555 let field_name = field.ident.as_ref().unwrap();
556 let kind = attrs.kind();
557
558 let access = if use_self {
559 quote! {
560 #[allow(non_snake_case)]
561 let #field_name = &mut self.#field_name;
562 }
563 } else {
564 quote!()
565 };
566 let arg_matches = format_ident!("__clap_arg_matches");
567
568 match &*kind {
569 Kind::ExternalSubcommand => {
570 abort! { kind.span(),
571 "`external_subcommand` can be used only on enum variants"
572 }
573 }
574 Kind::Subcommand(ty) => {
575 let subcmd_type = match (**ty, sub_type(&field.ty)) {
576 (Ty::Option, Some(sub_type)) => sub_type,
577 _ => &field.ty,
578 };
579
580 let updater = quote_spanned! { ty.span()=>
581 <#subcmd_type as clap::FromArgMatches>::update_from_arg_matches_mut(#field_name, #arg_matches)?;
582 };
583
584 let updater = match **ty {
585 Ty::Option => quote_spanned! { kind.span()=>
586 if let Some(#field_name) = #field_name.as_mut() {
587 #updater
588 } else {
589 *#field_name = Some(<#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut(
590 #arg_matches
591 )?);
592 }
593 },
594 _ => quote_spanned! { kind.span()=>
595 #updater
596 },
597 };
598
599 quote_spanned! { kind.span()=>
600 {
601 #access
602 #updater
603 }
604 }
605 }
606
607 Kind::Flatten => quote_spanned! { kind.span()=> {
608 #access
609 clap::FromArgMatches::update_from_arg_matches_mut(#field_name, #arg_matches)?;
610 }
611 },
612
613 Kind::Skip(_) => quote!(),
614
615 Kind::Arg(ty) | Kind::FromGlobal(ty) => gen_parsers(&attrs, ty, field_name, field, Some(&access)),
616 }
617 });
618
619 quote! {
620 #( #fields )*
621 }
622 }
623
624 fn gen_parsers(
625 attrs: &Attrs,
626 ty: &Sp<Ty>,
627 field_name: &Ident,
628 field: &Field,
629 update: Option<&TokenStream>,
630 ) -> TokenStream {
631 use self::ParserKind::*;
632
633 let parser = attrs.parser(&field.ty);
634 let func = &parser.func;
635 let span = parser.kind.span();
636 let convert_type = inner_type(&field.ty);
637 let id = attrs.id();
638 let mut flag = false;
639 let mut occurrences = false;
640 let (get_one, get_many, deref, mut parse) = match *parser.kind {
641 _ if attrs.ignore_parser() => (
642 quote_spanned!(span=> remove_one::<#convert_type>),
643 quote_spanned!(span=> remove_many::<#convert_type>),
644 quote!(|s| s),
645 quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(s)),
646 ),
647 FromOccurrences => {
648 occurrences = true;
649 (
650 quote_spanned!(span=> occurrences_of),
651 quote!(),
652 quote!(|s| ::std::ops::Deref::deref(s)),
653 func.clone(),
654 )
655 }
656 FromFlag => {
657 flag = true;
658 (
659 quote!(),
660 quote!(),
661 quote!(|s| ::std::ops::Deref::deref(s)),
662 func.clone(),
663 )
664 }
665 FromStr => (
666 quote_spanned!(span=> get_one::<String>),
667 quote_spanned!(span=> get_many::<String>),
668 quote!(|s| ::std::ops::Deref::deref(s)),
669 quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(#func(s))),
670 ),
671 TryFromStr => (
672 quote_spanned!(span=> get_one::<String>),
673 quote_spanned!(span=> get_many::<String>),
674 quote!(|s| ::std::ops::Deref::deref(s)),
675 quote_spanned!(func.span()=> |s| #func(s).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))),
676 ),
677 FromOsStr => (
678 quote_spanned!(span=> get_one::<::std::ffi::OsString>),
679 quote_spanned!(span=> get_many::<::std::ffi::OsString>),
680 quote!(|s| ::std::ops::Deref::deref(s)),
681 quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(#func(s))),
682 ),
683 TryFromOsStr => (
684 quote_spanned!(span=> get_one::<::std::ffi::OsString>),
685 quote_spanned!(span=> get_many::<::std::ffi::OsString>),
686 quote!(|s| ::std::ops::Deref::deref(s)),
687 quote_spanned!(func.span()=> |s| #func(s).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))),
688 ),
689 };
690 if attrs.is_enum() && !attrs.ignore_parser() {
691 let ci = attrs.ignore_case();
692
693 parse = quote_spanned! { convert_type.span()=>
694 |s| <#convert_type as clap::ValueEnum>::from_str(s, #ci).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))
695 }
696 }
697
698 // Give this identifier the same hygiene
699 // as the `arg_matches` parameter definition. This
700 // allows us to refer to `arg_matches` within a `quote_spanned` block
701 let arg_matches = format_ident!("__clap_arg_matches");
702
703 let field_value = match **ty {
704 Ty::Option => {
705 quote_spanned! { ty.span()=>
706 #arg_matches.#get_one(#id)
707 .map(#deref)
708 .map(#parse)
709 .transpose()?
710 }
711 }
712
713 Ty::OptionOption => quote_spanned! { ty.span()=>
714 if #arg_matches.contains_id(#id) {
715 Some(
716 #arg_matches.#get_one(#id)
717 .map(#deref)
718 .map(#parse).transpose()?
719 )
720 } else {
721 None
722 }
723 },
724
725 Ty::OptionVec => quote_spanned! { ty.span()=>
726 if #arg_matches.contains_id(#id) {
727 Some(#arg_matches.#get_many(#id)
728 .map(|v| v.map(#deref).map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result<Vec<_>, clap::Error>>())
729 .transpose()?
730 .unwrap_or_else(Vec::new))
731 } else {
732 None
733 }
734 },
735
736 Ty::Vec => {
737 quote_spanned! { ty.span()=>
738 #arg_matches.#get_many(#id)
739 .map(|v| v.map(#deref).map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result<Vec<_>, clap::Error>>())
740 .transpose()?
741 .unwrap_or_else(Vec::new)
742 }
743 }
744
745 Ty::Other if occurrences => quote_spanned! { ty.span()=>
746 #parse(
747 #arg_matches.#get_one(#id)
748 )
749 },
750
751 Ty::Other if flag => {
752 if update.is_some() && is_simple_ty(&field.ty, "bool") {
753 quote_spanned! { ty.span()=>
754 *#field_name || #arg_matches.is_present(#id)
755 }
756 } else {
757 quote_spanned! { ty.span()=>
758 #parse(#arg_matches.is_present(#id))
759 }
760 }
761 }
762
763 Ty::Other => {
764 quote_spanned! { ty.span()=>
765 #arg_matches.#get_one(#id)
766 .map(#deref)
767 .ok_or_else(|| clap::Error::raw(clap::ErrorKind::MissingRequiredArgument, format!("The following required argument was not provided: {}", #id)))
768 .and_then(#parse)?
769 }
770 }
771 };
772
773 if let Some(access) = update {
774 quote_spanned! { field.span()=>
775 if #arg_matches.contains_id(#id) {
776 #access
777 *#field_name = #field_value
778 }
779 }
780 } else {
781 quote_spanned!(field.span()=> #field_name: #field_value )
782 }
783 }
784
785 #[cfg(feature = "raw-deprecated")]
786 pub fn raw_deprecated() -> TokenStream {
787 quote! {}
788 }
789
790 #[cfg(not(feature = "raw-deprecated"))]
791 pub fn raw_deprecated() -> TokenStream {
792 quote! {
793 #![allow(deprecated)] // Assuming any deprecation in here will be related to a deprecation in `Args`
794
795 }
796 }