summaryrefslogtreecommitdiffstats
path: root/vendor/clap_derive/src/derives
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/clap_derive/src/derives')
-rw-r--r--vendor/clap_derive/src/derives/args.rs801
-rw-r--r--vendor/clap_derive/src/derives/into_app.rs62
-rw-r--r--vendor/clap_derive/src/derives/parser.rs90
-rw-r--r--vendor/clap_derive/src/derives/subcommand.rs495
-rw-r--r--vendor/clap_derive/src/derives/value_enum.rs85
5 files changed, 743 insertions, 790 deletions
diff --git a/vendor/clap_derive/src/derives/args.rs b/vendor/clap_derive/src/derives/args.rs
index 4195a0810..b5d51bfca 100644
--- a/vendor/clap_derive/src/derives/args.rs
+++ b/vendor/clap_derive/src/derives/args.rs
@@ -12,20 +12,19 @@
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.
-use crate::{
- attrs::{Attrs, Kind, Name, ParserKind, DEFAULT_CASING, DEFAULT_ENV_CASING},
- dummies,
- utils::{inner_type, is_simple_ty, sub_type, Sp, Ty},
-};
-
use proc_macro2::{Ident, Span, TokenStream};
use proc_macro_error::{abort, abort_call_site};
use quote::{format_ident, quote, quote_spanned};
+use syn::ext::IdentExt;
use syn::{
- punctuated::Punctuated, spanned::Spanned, token::Comma, Attribute, Data, DataStruct,
- DeriveInput, Field, Fields, Generics, Type,
+ punctuated::Punctuated, spanned::Spanned, token::Comma, Data, DataStruct, DeriveInput, Field,
+ Fields, Generics,
};
+use crate::dummies;
+use crate::item::{Item, Kind, Name};
+use crate::utils::{inner_type, sub_type, Sp, Ty};
+
pub fn derive_args(input: &DeriveInput) -> TokenStream {
let ident = &input.ident;
@@ -35,87 +34,68 @@ pub fn derive_args(input: &DeriveInput) -> TokenStream {
Data::Struct(DataStruct {
fields: Fields::Named(ref fields),
..
- }) => gen_for_struct(ident, &input.generics, &fields.named, &input.attrs),
+ }) => {
+ let name = Name::Derived(ident.clone());
+ let item = Item::from_args_struct(input, name);
+ let fields = fields
+ .named
+ .iter()
+ .map(|field| {
+ let item = Item::from_args_field(field, item.casing(), item.env_casing());
+ (field, item)
+ })
+ .collect::<Vec<_>>();
+ gen_for_struct(&item, ident, &input.generics, &fields)
+ }
Data::Struct(DataStruct {
fields: Fields::Unit,
..
- }) => gen_for_struct(
- ident,
- &input.generics,
- &Punctuated::<Field, Comma>::new(),
- &input.attrs,
- ),
+ }) => {
+ let name = Name::Derived(ident.clone());
+ let item = Item::from_args_struct(input, name);
+ let fields = Punctuated::<Field, Comma>::new();
+ let fields = fields
+ .iter()
+ .map(|field| {
+ let item = Item::from_args_field(field, item.casing(), item.env_casing());
+ (field, item)
+ })
+ .collect::<Vec<_>>();
+ gen_for_struct(&item, ident, &input.generics, &fields)
+ }
_ => abort_call_site!("`#[derive(Args)]` only supports non-tuple structs"),
}
}
pub fn gen_for_struct(
- struct_name: &Ident,
+ item: &Item,
+ item_name: &Ident,
generics: &Generics,
- fields: &Punctuated<Field, Comma>,
- attrs: &[Attribute],
+ fields: &[(&Field, Item)],
) -> TokenStream {
- let from_arg_matches = gen_from_arg_matches_for_struct(struct_name, generics, fields, attrs);
-
- let attrs = Attrs::from_struct(
- Span::call_site(),
- attrs,
- Name::Derived(struct_name.clone()),
- Sp::call_site(DEFAULT_CASING),
- Sp::call_site(DEFAULT_ENV_CASING),
- );
- let app_var = Ident::new("__clap_app", Span::call_site());
- let augmentation = gen_augment(fields, &app_var, &attrs, false);
- let augmentation_update = gen_augment(fields, &app_var, &attrs, true);
-
- let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
-
- quote! {
- #from_arg_matches
-
- #[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
- #[allow(
- clippy::style,
- clippy::complexity,
- clippy::pedantic,
- clippy::restriction,
- clippy::perf,
- clippy::deprecated,
- clippy::nursery,
- clippy::cargo,
- clippy::suspicious_else_formatting,
- )]
- #[deny(clippy::correctness)]
- impl #impl_generics clap::Args for #struct_name #ty_generics #where_clause {
- fn augment_args<'b>(#app_var: clap::Command<'b>) -> clap::Command<'b> {
- #augmentation
- }
- fn augment_args_for_update<'b>(#app_var: clap::Command<'b>) -> clap::Command<'b> {
- #augmentation_update
- }
+ if !matches!(&*item.kind(), Kind::Command(_)) {
+ abort! { item.kind().span(),
+ "`{}` cannot be used with `command`",
+ item.kind().name(),
}
}
-}
-pub fn gen_from_arg_matches_for_struct(
- struct_name: &Ident,
- generics: &Generics,
- fields: &Punctuated<Field, Comma>,
- attrs: &[Attribute],
-) -> TokenStream {
- let attrs = Attrs::from_struct(
- Span::call_site(),
- attrs,
- Name::Derived(struct_name.clone()),
- Sp::call_site(DEFAULT_CASING),
- Sp::call_site(DEFAULT_ENV_CASING),
- );
-
- let constructor = gen_constructor(fields, &attrs);
- let updater = gen_updater(fields, &attrs, true);
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ let constructor = gen_constructor(fields);
+ let updater = gen_updater(fields, true);
let raw_deprecated = raw_deprecated();
- let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+ let app_var = Ident::new("__clap_app", Span::call_site());
+ let augmentation = gen_augment(fields, &app_var, item, false);
+ let augmentation_update = gen_augment(fields, &app_var, item, true);
+
+ let group_id = if item.skip_group() {
+ quote!(None)
+ } else {
+ let group_id = item.ident().unraw().to_string();
+ quote!(Some(clap::Id::from(#group_id)))
+ };
quote! {
#[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
@@ -131,14 +111,14 @@ pub fn gen_from_arg_matches_for_struct(
clippy::suspicious_else_formatting,
)]
#[deny(clippy::correctness)]
- impl #impl_generics clap::FromArgMatches for #struct_name #ty_generics #where_clause {
+ impl #impl_generics clap::FromArgMatches for #item_name #ty_generics #where_clause {
fn from_arg_matches(__clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result<Self, clap::Error> {
Self::from_arg_matches_mut(&mut __clap_arg_matches.clone())
}
fn from_arg_matches_mut(__clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result<Self, clap::Error> {
#raw_deprecated
- let v = #struct_name #constructor;
+ let v = #item_name #constructor;
::std::result::Result::Ok(v)
}
@@ -152,229 +132,149 @@ pub fn gen_from_arg_matches_for_struct(
::std::result::Result::Ok(())
}
}
+
+ #[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
+ #[allow(
+ clippy::style,
+ clippy::complexity,
+ clippy::pedantic,
+ clippy::restriction,
+ clippy::perf,
+ clippy::deprecated,
+ clippy::nursery,
+ clippy::cargo,
+ clippy::suspicious_else_formatting,
+ )]
+ #[deny(clippy::correctness)]
+ impl #impl_generics clap::Args for #item_name #ty_generics #where_clause {
+ fn group_id() -> Option<clap::Id> {
+ #group_id
+ }
+ fn augment_args<'b>(#app_var: clap::Command) -> clap::Command {
+ #augmentation
+ }
+ fn augment_args_for_update<'b>(#app_var: clap::Command) -> clap::Command {
+ #augmentation_update
+ }
+ }
}
}
/// Generate a block of code to add arguments/subcommands corresponding to
/// the `fields` to an cmd.
pub fn gen_augment(
- fields: &Punctuated<Field, Comma>,
+ fields: &[(&Field, Item)],
app_var: &Ident,
- parent_attribute: &Attrs,
+ parent_item: &Item,
override_required: bool,
) -> TokenStream {
- let mut subcmds = fields.iter().filter_map(|field| {
- let attrs = Attrs::from_field(
- field,
- parent_attribute.casing(),
- parent_attribute.env_casing(),
- );
- let kind = attrs.kind();
- if let Kind::Subcommand(ty) = &*kind {
- let subcmd_type = match (**ty, sub_type(&field.ty)) {
- (Ty::Option, Some(sub_type)) => sub_type,
- _ => &field.ty,
- };
- let required = if **ty == Ty::Option {
- quote!()
- } else {
- quote_spanned! { kind.span()=>
- #[allow(deprecated)]
- let #app_var = #app_var.setting(
- clap::AppSettings::SubcommandRequiredElseHelp
- );
+ let mut subcommand_specified = false;
+ let args = fields.iter().filter_map(|(field, item)| {
+ let kind = item.kind();
+ match &*kind {
+ Kind::Command(_)
+ | Kind::Value
+ | Kind::Skip(_, _)
+ | Kind::FromGlobal(_)
+ | Kind::ExternalSubcommand => None,
+ Kind::Subcommand(ty) => {
+ if subcommand_specified {
+ abort!(field.span(), "`#[command(subcommand)]` can only be used once per container");
}
- };
+ subcommand_specified = true;
- let span = field.span();
- let ts = if override_required {
- quote! {
- let #app_var = <#subcmd_type as clap::Subcommand>::augment_subcommands_for_update( #app_var );
- }
- } else{
- quote! {
+ let subcmd_type = match (**ty, sub_type(&field.ty)) {
+ (Ty::Option, Some(sub_type)) => sub_type,
+ _ => &field.ty,
+ };
+ let implicit_methods = if **ty == Ty::Option {
+ quote!()
+ } else {
+ quote_spanned! { kind.span()=>
+ .subcommand_required(true)
+ .arg_required_else_help(true)
+ }
+ };
+
+ let override_methods = if override_required {
+ quote_spanned! { kind.span()=>
+ .subcommand_required(false)
+ .arg_required_else_help(false)
+ }
+ } else {
+ quote!()
+ };
+
+ Some(quote! {
let #app_var = <#subcmd_type as clap::Subcommand>::augment_subcommands( #app_var );
- #required
- }
- };
- Some((span, ts))
- } else {
- None
- }
- });
- let subcmd = subcmds.next().map(|(_, ts)| ts);
- if let Some((span, _)) = subcmds.next() {
- abort!(
- span,
- "multiple subcommand sets are not allowed, that's the second"
- );
- }
+ let #app_var = #app_var
+ #implicit_methods
+ #override_methods;
+ })
+ }
+ Kind::Flatten(ty) => {
+ let inner_type = match (**ty, sub_type(&field.ty)) {
+ (Ty::Option, Some(sub_type)) => sub_type,
+ _ => &field.ty,
+ };
- let args = fields.iter().filter_map(|field| {
- let attrs = Attrs::from_field(
- field,
- parent_attribute.casing(),
- parent_attribute.env_casing(),
- );
- let kind = attrs.kind();
- match &*kind {
- Kind::Subcommand(_)
- | Kind::Skip(_)
- | Kind::FromGlobal(_)
- | Kind::ExternalSubcommand => None,
- Kind::Flatten => {
- let ty = &field.ty;
- let old_heading_var = format_ident!("__clap_old_heading");
- let next_help_heading = attrs.next_help_heading();
- let next_display_order = attrs.next_display_order();
+ let next_help_heading = item.next_help_heading();
+ let next_display_order = item.next_display_order();
if override_required {
Some(quote_spanned! { kind.span()=>
- let #old_heading_var = #app_var.get_next_help_heading();
- let #app_var = #app_var #next_help_heading #next_display_order;
- let #app_var = <#ty as clap::Args>::augment_args_for_update(#app_var);
- let #app_var = #app_var.next_help_heading(#old_heading_var);
+ let #app_var = #app_var
+ #next_help_heading
+ #next_display_order;
+ let #app_var = <#inner_type as clap::Args>::augment_args_for_update(#app_var);
})
} else {
Some(quote_spanned! { kind.span()=>
- let #old_heading_var = #app_var.get_next_help_heading();
- let #app_var = #app_var #next_help_heading #next_display_order;
- let #app_var = <#ty as clap::Args>::augment_args(#app_var);
- let #app_var = #app_var.next_help_heading(#old_heading_var);
+ let #app_var = #app_var
+ #next_help_heading
+ #next_display_order;
+ let #app_var = <#inner_type as clap::Args>::augment_args(#app_var);
})
}
}
Kind::Arg(ty) => {
- let convert_type = inner_type(&field.ty);
-
- let parser = attrs.parser(&field.ty);
-
- let value_parser = attrs.value_parser(&field.ty);
- let action = attrs.action(&field.ty);
- let func = &parser.func;
-
- let mut occurrences = false;
- let mut flag = false;
- let validator = match *parser.kind {
- _ if attrs.ignore_parser() || attrs.is_enum() => quote!(),
- ParserKind::TryFromStr => quote_spanned! { func.span()=>
- .validator(|s| {
- #func(s)
- .map(|_: #convert_type| ())
- })
- },
- ParserKind::TryFromOsStr => quote_spanned! { func.span()=>
- .validator_os(|s| #func(s).map(|_: #convert_type| ()))
- },
- ParserKind::FromStr | ParserKind::FromOsStr => quote!(),
- ParserKind::FromFlag => {
- flag = true;
- quote!()
- }
- ParserKind::FromOccurrences => {
- occurrences = true;
- quote!()
- }
- };
- let parse_deprecation = match *parser.kind {
- _ if !attrs.explicit_parser() || cfg!(not(feature = "deprecated")) => quote!(),
- ParserKind::FromStr => quote_spanned! { func.span()=>
- #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]`")]
- fn parse_from_str() {
- }
- parse_from_str();
- },
- ParserKind::TryFromStr => quote_spanned! { func.span()=>
- #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]`")]
- fn parse_try_from_str() {
- }
- parse_try_from_str();
- },
- ParserKind::FromOsStr => quote_spanned! { func.span()=>
- #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser)]` for `PathBuf` or `#[clap(value_parser = ...)]` with a custom `TypedValueParser`")]
- fn parse_from_os_str() {
- }
- parse_from_os_str();
- },
- ParserKind::TryFromOsStr => quote_spanned! { func.span()=>
- #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]` with a custom `TypedValueParser`")]
- fn parse_try_from_os_str() {
- }
- parse_try_from_os_str();
- },
- ParserKind::FromFlag => quote_spanned! { func.span()=>
- #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(action = ArgAction::SetTrue)]`")]
- fn parse_from_flag() {
- }
- parse_from_flag();
- },
- ParserKind::FromOccurrences => quote_spanned! { func.span()=>
- #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(action = ArgAction::Count)]` with a field type of `u8`")]
- fn parse_from_occurrences() {
- }
- parse_from_occurrences();
- },
- };
-
- let value_name = attrs.value_name();
- let possible_values = if attrs.is_enum() && !attrs.ignore_parser() {
- gen_value_enum_possible_values(convert_type)
- } else {
- quote!()
- };
+ let value_parser = item.value_parser(&field.ty);
+ let action = item.action(&field.ty);
+ let value_name = item.value_name();
let implicit_methods = match **ty {
+ Ty::Unit => {
+ // Leaving out `value_parser` as it will always fail
+ quote_spanned! { ty.span()=>
+ .value_name(#value_name)
+ #action
+ }
+ }
Ty::Option => {
quote_spanned! { ty.span()=>
- .takes_value(true)
.value_name(#value_name)
- #possible_values
- #validator
#value_parser
#action
}
}
Ty::OptionOption => quote_spanned! { ty.span()=>
- .takes_value(true)
.value_name(#value_name)
- .min_values(0)
- .max_values(1)
- .multiple_values(false)
- #possible_values
- #validator
+ .num_args(0..=1)
#value_parser
#action
},
Ty::OptionVec => {
- if attrs.ignore_parser() {
- if attrs.is_positional() {
- quote_spanned! { ty.span()=>
- .takes_value(true)
- .value_name(#value_name)
- .multiple_values(true) // action won't be sufficient for getting multiple
- #possible_values
- #validator
- #value_parser
- #action
- }
- } else {
- quote_spanned! { ty.span()=>
- .takes_value(true)
- .value_name(#value_name)
- #possible_values
- #validator
- #value_parser
- #action
- }
+ if item.is_positional() {
+ quote_spanned! { ty.span()=>
+ .value_name(#value_name)
+ .num_args(1..) // action won't be sufficient for getting multiple
+ #value_parser
+ #action
}
} else {
quote_spanned! { ty.span()=>
- .takes_value(true)
.value_name(#value_name)
- .multiple_occurrences(true)
- #possible_values
- #validator
#value_parser
#action
}
@@ -382,72 +282,63 @@ pub fn gen_augment(
}
Ty::Vec => {
- if attrs.ignore_parser() {
- if attrs.is_positional() {
- quote_spanned! { ty.span()=>
- .takes_value(true)
- .value_name(#value_name)
- .multiple_values(true) // action won't be sufficient for getting multiple
- #possible_values
- #validator
- #value_parser
- #action
- }
- } else {
- quote_spanned! { ty.span()=>
- .takes_value(true)
- .value_name(#value_name)
- #possible_values
- #validator
- #value_parser
- #action
- }
+ if item.is_positional() {
+ quote_spanned! { ty.span()=>
+ .value_name(#value_name)
+ .num_args(1..) // action won't be sufficient for getting multiple
+ #value_parser
+ #action
}
} else {
quote_spanned! { ty.span()=>
- .takes_value(true)
.value_name(#value_name)
- .multiple_occurrences(true)
- #possible_values
- #validator
#value_parser
#action
}
}
}
- Ty::Other if occurrences => quote_spanned! { ty.span()=>
- .multiple_occurrences(true)
- },
-
- Ty::Other if flag => quote_spanned! { ty.span()=>
- .takes_value(false)
- },
+ Ty::VecVec | Ty::OptionVecVec => {
+ quote_spanned! { ty.span() =>
+ .value_name(#value_name)
+ #value_parser
+ #action
+ }
+ }
Ty::Other => {
- let required = attrs.find_default_method().is_none() && !override_required;
+ let required = item.find_default_method().is_none();
// `ArgAction::takes_values` is assuming `ArgAction::default_value` will be
// set though that won't always be true but this should be good enough,
// otherwise we'll report an "arg required" error when unwrapping.
let action_value = action.args();
quote_spanned! { ty.span()=>
- .takes_value(true)
.value_name(#value_name)
.required(#required && #action_value.takes_values())
- #possible_values
- #validator
#value_parser
#action
}
}
};
- let id = attrs.id();
- let explicit_methods = attrs.field_methods(true);
+ let id = item.id();
+ let explicit_methods = item.field_methods();
+ let deprecations = if !override_required {
+ item.deprecations()
+ } else {
+ quote!()
+ };
+ let override_methods = if override_required {
+ quote_spanned! { kind.span()=>
+ .required(false)
+ }
+ } else {
+ quote!()
+ };
Some(quote_spanned! { field.span()=>
let #app_var = #app_var.arg({
- #parse_deprecation
+ #deprecations
#[allow(deprecated)]
let arg = clap::Arg::new(#id)
@@ -455,6 +346,10 @@ pub fn gen_augment(
let arg = arg
#explicit_methods;
+
+ let arg = arg
+ #override_methods;
+
arg
});
})
@@ -462,36 +357,80 @@ pub fn gen_augment(
}
});
- let initial_app_methods = parent_attribute.initial_top_level_methods();
- let final_app_methods = parent_attribute.final_top_level_methods();
+ let deprecations = if !override_required {
+ parent_item.deprecations()
+ } else {
+ quote!()
+ };
+ let initial_app_methods = parent_item.initial_top_level_methods();
+ let final_app_methods = parent_item.final_top_level_methods();
+ let group_app_methods = if parent_item.skip_group() {
+ quote!()
+ } else {
+ let group_id = parent_item.ident().unraw().to_string();
+ let literal_group_members = fields
+ .iter()
+ .filter_map(|(_field, item)| {
+ let kind = item.kind();
+ if matches!(*kind, Kind::Arg(_)) {
+ Some(item.id())
+ } else {
+ None
+ }
+ })
+ .collect::<Vec<_>>();
+ let literal_group_members_len = literal_group_members.len();
+ let mut literal_group_members = quote! {{
+ let members: [clap::Id; #literal_group_members_len] = [#( clap::Id::from(#literal_group_members) ),* ];
+ members
+ }};
+ // HACK: Validation isn't ready yet for nested arg groups, so just don't populate the group in
+ // that situation
+ let possible_group_members_len = fields
+ .iter()
+ .filter(|(_field, item)| {
+ let kind = item.kind();
+ matches!(*kind, Kind::Flatten(_))
+ })
+ .count();
+ if 0 < possible_group_members_len {
+ literal_group_members = quote! {{
+ let members: [clap::Id; 0] = [];
+ members
+ }};
+ }
+
+ quote!(
+ .group(
+ clap::ArgGroup::new(#group_id)
+ .multiple(true)
+ .args(#literal_group_members)
+ )
+ )
+ };
quote! {{
- let #app_var = #app_var #initial_app_methods;
+ #deprecations
+ let #app_var = #app_var
+ #initial_app_methods
+ #group_app_methods
+ ;
#( #args )*
- #subcmd
#app_var #final_app_methods
}}
}
-fn gen_value_enum_possible_values(ty: &Type) -> TokenStream {
- quote_spanned! { ty.span()=>
- .possible_values(<#ty as clap::ValueEnum>::value_variants().iter().filter_map(clap::ValueEnum::to_possible_value))
- }
-}
-
-pub fn gen_constructor(fields: &Punctuated<Field, Comma>, parent_attribute: &Attrs) -> TokenStream {
- let fields = fields.iter().map(|field| {
- let attrs = Attrs::from_field(
- field,
- parent_attribute.casing(),
- parent_attribute.env_casing(),
- );
+pub fn gen_constructor(fields: &[(&Field, Item)]) -> TokenStream {
+ let fields = fields.iter().map(|(field, item)| {
let field_name = field.ident.as_ref().unwrap();
- let kind = attrs.kind();
+ let kind = item.kind();
let arg_matches = format_ident!("__clap_arg_matches");
match &*kind {
- Kind::ExternalSubcommand => {
+ Kind::Command(_)
+ | Kind::Value
+ | Kind::ExternalSubcommand => {
abort! { kind.span(),
- "`external_subcommand` can be used only on enum variants"
+ "`{}` cannot be used with `arg`",
+ kind.name(),
}
}
Kind::Subcommand(ty) => {
@@ -511,27 +450,76 @@ pub fn gen_constructor(fields: &Punctuated<Field, Comma>, parent_attribute: &Att
}
}
},
- _ => {
+ Ty::Other => {
quote_spanned! { kind.span()=>
#field_name: {
<#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut(#arg_matches)?
}
}
},
+ Ty::Unit |
+ Ty::Vec |
+ Ty::OptionOption |
+ Ty::OptionVec |
+ Ty::VecVec |
+ Ty::OptionVecVec => {
+ abort!(
+ ty.span(),
+ "{} types are not supported for subcommand",
+ ty.as_str()
+ );
+ }
}
}
- Kind::Flatten => quote_spanned! { kind.span()=>
- #field_name: clap::FromArgMatches::from_arg_matches_mut(#arg_matches)?
+ Kind::Flatten(ty) => {
+ let inner_type = match (**ty, sub_type(&field.ty)) {
+ (Ty::Option, Some(sub_type)) => sub_type,
+ _ => &field.ty,
+ };
+ match **ty {
+ Ty::Other => {
+ quote_spanned! { kind.span()=>
+ #field_name: <#inner_type as clap::FromArgMatches>::from_arg_matches_mut(#arg_matches)?
+ }
+ },
+ Ty::Option => {
+ quote_spanned! { kind.span()=>
+ #field_name: {
+ let group_id = <#inner_type as clap::Args>::group_id()
+ .expect("`#[arg(flatten)]`ed field type implements `Args::group_id`");
+ if #arg_matches.contains_id(group_id.as_str()) {
+ Some(
+ <#inner_type as clap::FromArgMatches>::from_arg_matches_mut(#arg_matches)?
+ )
+ } else {
+ None
+ }
+ }
+ }
+ },
+ Ty::Unit |
+ Ty::Vec |
+ Ty::OptionOption |
+ Ty::OptionVec |
+ Ty::VecVec |
+ Ty::OptionVecVec => {
+ abort!(
+ ty.span(),
+ "{} types are not supported for flatten",
+ ty.as_str()
+ );
+ }
+ }
},
- Kind::Skip(val) => match val {
+ Kind::Skip(val, _) => match val {
None => quote_spanned!(kind.span()=> #field_name: Default::default()),
Some(val) => quote_spanned!(kind.span()=> #field_name: (#val).into()),
},
Kind::Arg(ty) | Kind::FromGlobal(ty) => {
- gen_parsers(&attrs, ty, field_name, field, None)
+ gen_parsers(item, ty, field_name, field, None)
}
}
});
@@ -541,19 +529,10 @@ pub fn gen_constructor(fields: &Punctuated<Field, Comma>, parent_attribute: &Att
}}
}
-pub fn gen_updater(
- fields: &Punctuated<Field, Comma>,
- parent_attribute: &Attrs,
- use_self: bool,
-) -> TokenStream {
- let fields = fields.iter().map(|field| {
- let attrs = Attrs::from_field(
- field,
- parent_attribute.casing(),
- parent_attribute.env_casing(),
- );
+pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> TokenStream {
+ let fields = fields.iter().map(|(field, item)| {
let field_name = field.ident.as_ref().unwrap();
- let kind = attrs.kind();
+ let kind = item.kind();
let access = if use_self {
quote! {
@@ -566,9 +545,12 @@ pub fn gen_updater(
let arg_matches = format_ident!("__clap_arg_matches");
match &*kind {
- Kind::ExternalSubcommand => {
+ Kind::Command(_)
+ | Kind::Value
+ | Kind::ExternalSubcommand => {
abort! { kind.span(),
- "`external_subcommand` can be used only on enum variants"
+ "`{}` cannot be used with `arg`",
+ kind.name(),
}
}
Kind::Subcommand(ty) => {
@@ -604,15 +586,42 @@ pub fn gen_updater(
}
}
- Kind::Flatten => quote_spanned! { kind.span()=> {
- #access
- clap::FromArgMatches::update_from_arg_matches_mut(#field_name, #arg_matches)?;
+ Kind::Flatten(ty) => {
+ let inner_type = match (**ty, sub_type(&field.ty)) {
+ (Ty::Option, Some(sub_type)) => sub_type,
+ _ => &field.ty,
+ };
+
+ let updater = quote_spanned! { ty.span()=>
+ <#inner_type as clap::FromArgMatches>::update_from_arg_matches_mut(#field_name, #arg_matches)?;
+ };
+
+ let updater = match **ty {
+ Ty::Option => quote_spanned! { kind.span()=>
+ if let Some(#field_name) = #field_name.as_mut() {
+ #updater
+ } else {
+ *#field_name = Some(<#inner_type as clap::FromArgMatches>::from_arg_matches_mut(
+ #arg_matches
+ )?);
+ }
+ },
+ _ => quote_spanned! { kind.span()=>
+ #updater
+ },
+ };
+
+ quote_spanned! { kind.span()=>
+ {
+ #access
+ #updater
+ }
}
},
- Kind::Skip(_) => quote!(),
+ Kind::Skip(_, _) => quote!(),
- Kind::Arg(ty) | Kind::FromGlobal(ty) => gen_parsers(&attrs, ty, field_name, field, Some(&access)),
+ Kind::Arg(ty) | Kind::FromGlobal(ty) => gen_parsers(item, ty, field_name, field, Some(&access)),
}
});
@@ -622,78 +631,18 @@ pub fn gen_updater(
}
fn gen_parsers(
- attrs: &Attrs,
+ item: &Item,
ty: &Sp<Ty>,
field_name: &Ident,
field: &Field,
update: Option<&TokenStream>,
) -> TokenStream {
- use self::ParserKind::*;
-
- let parser = attrs.parser(&field.ty);
- let func = &parser.func;
- let span = parser.kind.span();
+ let span = ty.span();
let convert_type = inner_type(&field.ty);
- let id = attrs.id();
- let mut flag = false;
- let mut occurrences = false;
- let (get_one, get_many, deref, mut parse) = match *parser.kind {
- _ if attrs.ignore_parser() => (
- quote_spanned!(span=> remove_one::<#convert_type>),
- quote_spanned!(span=> remove_many::<#convert_type>),
- quote!(|s| s),
- quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(s)),
- ),
- FromOccurrences => {
- occurrences = true;
- (
- quote_spanned!(span=> occurrences_of),
- quote!(),
- quote!(|s| ::std::ops::Deref::deref(s)),
- func.clone(),
- )
- }
- FromFlag => {
- flag = true;
- (
- quote!(),
- quote!(),
- quote!(|s| ::std::ops::Deref::deref(s)),
- func.clone(),
- )
- }
- FromStr => (
- quote_spanned!(span=> get_one::<String>),
- quote_spanned!(span=> get_many::<String>),
- quote!(|s| ::std::ops::Deref::deref(s)),
- quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(#func(s))),
- ),
- TryFromStr => (
- quote_spanned!(span=> get_one::<String>),
- quote_spanned!(span=> get_many::<String>),
- quote!(|s| ::std::ops::Deref::deref(s)),
- quote_spanned!(func.span()=> |s| #func(s).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))),
- ),
- FromOsStr => (
- quote_spanned!(span=> get_one::<::std::ffi::OsString>),
- quote_spanned!(span=> get_many::<::std::ffi::OsString>),
- quote!(|s| ::std::ops::Deref::deref(s)),
- quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(#func(s))),
- ),
- TryFromOsStr => (
- quote_spanned!(span=> get_one::<::std::ffi::OsString>),
- quote_spanned!(span=> get_many::<::std::ffi::OsString>),
- quote!(|s| ::std::ops::Deref::deref(s)),
- quote_spanned!(func.span()=> |s| #func(s).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))),
- ),
- };
- if attrs.is_enum() && !attrs.ignore_parser() {
- let ci = attrs.ignore_case();
-
- parse = quote_spanned! { convert_type.span()=>
- |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)))
- }
- }
+ let id = item.id();
+ let get_one = quote_spanned!(span=> remove_one::<#convert_type>);
+ let get_many = quote_spanned!(span=> remove_many::<#convert_type>);
+ let get_occurrences = quote_spanned!(span=> remove_occurrences::<#convert_type>);
// Give this identifier the same hygiene
// as the `arg_matches` parameter definition. This
@@ -701,12 +650,15 @@ fn gen_parsers(
let arg_matches = format_ident!("__clap_arg_matches");
let field_value = match **ty {
+ Ty::Unit => {
+ quote_spanned! { ty.span()=>
+ ()
+ }
+ }
+
Ty::Option => {
quote_spanned! { ty.span()=>
#arg_matches.#get_one(#id)
- .map(#deref)
- .map(#parse)
- .transpose()?
}
}
@@ -714,8 +666,6 @@ fn gen_parsers(
if #arg_matches.contains_id(#id) {
Some(
#arg_matches.#get_one(#id)
- .map(#deref)
- .map(#parse).transpose()?
)
} else {
None
@@ -725,8 +675,7 @@ fn gen_parsers(
Ty::OptionVec => quote_spanned! { ty.span()=>
if #arg_matches.contains_id(#id) {
Some(#arg_matches.#get_many(#id)
- .map(|v| v.map(#deref).map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result<Vec<_>, clap::Error>>())
- .transpose()?
+ .map(|v| v.collect::<Vec<_>>())
.unwrap_or_else(Vec::new))
} else {
None
@@ -736,36 +685,26 @@ fn gen_parsers(
Ty::Vec => {
quote_spanned! { ty.span()=>
#arg_matches.#get_many(#id)
- .map(|v| v.map(#deref).map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result<Vec<_>, clap::Error>>())
- .transpose()?
+ .map(|v| v.collect::<Vec<_>>())
.unwrap_or_else(Vec::new)
}
}
- Ty::Other if occurrences => quote_spanned! { ty.span()=>
- #parse(
- #arg_matches.#get_one(#id)
- )
+ Ty::VecVec => quote_spanned! { ty.span()=>
+ #arg_matches.#get_occurrences(#id)
+ .map(|g| g.map(::std::iter::Iterator::collect).collect::<Vec<Vec<_>>>())
+ .unwrap_or_else(Vec::new)
},
- Ty::Other if flag => {
- if update.is_some() && is_simple_ty(&field.ty, "bool") {
- quote_spanned! { ty.span()=>
- *#field_name || #arg_matches.is_present(#id)
- }
- } else {
- quote_spanned! { ty.span()=>
- #parse(#arg_matches.is_present(#id))
- }
- }
- }
+ Ty::OptionVecVec => quote_spanned! { ty.span()=>
+ #arg_matches.#get_occurrences(#id)
+ .map(|g| g.map(::std::iter::Iterator::collect).collect::<Vec<Vec<_>>>())
+ },
Ty::Other => {
quote_spanned! { ty.span()=>
#arg_matches.#get_one(#id)
- .map(#deref)
- .ok_or_else(|| clap::Error::raw(clap::ErrorKind::MissingRequiredArgument, format!("The following required argument was not provided: {}", #id)))
- .and_then(#parse)?
+ .ok_or_else(|| clap::Error::raw(clap::error::ErrorKind::MissingRequiredArgument, format!("The following required argument was not provided: {}", #id)))?
}
}
};
diff --git a/vendor/clap_derive/src/derives/into_app.rs b/vendor/clap_derive/src/derives/into_app.rs
index 319735753..a45667ab2 100644
--- a/vendor/clap_derive/src/derives/into_app.rs
+++ b/vendor/clap_derive/src/derives/into_app.rs
@@ -12,36 +12,18 @@
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.
-use std::env;
-
use proc_macro2::{Span, TokenStream};
use quote::quote;
-use syn::{Attribute, Generics, Ident};
+use syn::{Generics, Ident};
-use crate::{
- attrs::{Attrs, Name, DEFAULT_CASING, DEFAULT_ENV_CASING},
- utils::Sp,
-};
+use crate::item::Item;
-pub fn gen_for_struct(
- struct_name: &Ident,
- generics: &Generics,
- attrs: &[Attribute],
-) -> TokenStream {
- let app_name = env::var("CARGO_PKG_NAME").ok().unwrap_or_default();
+pub fn gen_for_struct(item: &Item, item_name: &Ident, generics: &Generics) -> TokenStream {
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
- let attrs = Attrs::from_struct(
- Span::call_site(),
- attrs,
- Name::Assigned(quote!(#app_name)),
- Sp::call_site(DEFAULT_CASING),
- Sp::call_site(DEFAULT_ENV_CASING),
- );
- let name = attrs.cased_name();
+ let name = item.cased_name();
let app_var = Ident::new("__clap_app", Span::call_site());
- let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
-
let tokens = quote! {
#[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
#[allow(
@@ -56,14 +38,13 @@ pub fn gen_for_struct(
clippy::suspicious_else_formatting,
)]
#[deny(clippy::correctness)]
- #[allow(deprecated)]
- impl #impl_generics clap::CommandFactory for #struct_name #ty_generics #where_clause {
- fn into_app<'b>() -> clap::Command<'b> {
+ impl #impl_generics clap::CommandFactory for #item_name #ty_generics #where_clause {
+ fn command<'b>() -> clap::Command {
let #app_var = clap::Command::new(#name);
<Self as clap::Args>::augment_args(#app_var)
}
- fn into_app_for_update<'b>() -> clap::Command<'b> {
+ fn command_for_update<'b>() -> clap::Command {
let #app_var = clap::Command::new(#name);
<Self as clap::Args>::augment_args_for_update(#app_var)
}
@@ -73,21 +54,12 @@ pub fn gen_for_struct(
tokens
}
-pub fn gen_for_enum(enum_name: &Ident, generics: &Generics, attrs: &[Attribute]) -> TokenStream {
- let app_name = env::var("CARGO_PKG_NAME").ok().unwrap_or_default();
+pub fn gen_for_enum(item: &Item, item_name: &Ident, generics: &Generics) -> TokenStream {
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
- let attrs = Attrs::from_struct(
- Span::call_site(),
- attrs,
- Name::Assigned(quote!(#app_name)),
- Sp::call_site(DEFAULT_CASING),
- Sp::call_site(DEFAULT_ENV_CASING),
- );
- let name = attrs.cased_name();
+ let name = item.cased_name();
let app_var = Ident::new("__clap_app", Span::call_site());
- let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
-
quote! {
#[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
#[allow(
@@ -102,17 +74,19 @@ pub fn gen_for_enum(enum_name: &Ident, generics: &Generics, attrs: &[Attribute])
clippy::suspicious_else_formatting,
)]
#[deny(clippy::correctness)]
- impl #impl_generics clap::CommandFactory for #enum_name #ty_generics #where_clause {
- fn into_app<'b>() -> clap::Command<'b> {
- #[allow(deprecated)]
+ impl #impl_generics clap::CommandFactory for #item_name #ty_generics #where_clause {
+ fn command<'b>() -> clap::Command {
let #app_var = clap::Command::new(#name)
- .setting(clap::AppSettings::SubcommandRequiredElseHelp);
+ .subcommand_required(true)
+ .arg_required_else_help(true);
<Self as clap::Subcommand>::augment_subcommands(#app_var)
}
- fn into_app_for_update<'b>() -> clap::Command<'b> {
+ fn command_for_update<'b>() -> clap::Command {
let #app_var = clap::Command::new(#name);
<Self as clap::Subcommand>::augment_subcommands_for_update(#app_var)
+ .subcommand_required(false)
+ .arg_required_else_help(false)
}
}
}
diff --git a/vendor/clap_derive/src/derives/parser.rs b/vendor/clap_derive/src/derives/parser.rs
index 621430f31..617857cac 100644
--- a/vendor/clap_derive/src/derives/parser.rs
+++ b/vendor/clap_derive/src/derives/parser.rs
@@ -12,21 +12,24 @@
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.
-use crate::{
- derives::{args, into_app, subcommand},
- dummies,
-};
-
use proc_macro2::TokenStream;
use proc_macro_error::abort_call_site;
use quote::quote;
+use syn::Ident;
+use syn::Variant;
use syn::{
- self, punctuated::Punctuated, token::Comma, Attribute, Data, DataEnum, DataStruct, DeriveInput,
- Field, Fields, Generics, Ident,
+ self, punctuated::Punctuated, token::Comma, Data, DataStruct, DeriveInput, Field, Fields,
+ Generics,
};
+use crate::derives::{args, into_app, subcommand};
+use crate::dummies;
+use crate::item::Item;
+use crate::item::Name;
+
pub fn derive_parser(input: &DeriveInput) -> TokenStream {
let ident = &input.ident;
+ let pkg_name = std::env::var("CARGO_PKG_NAME").ok().unwrap_or_default();
match input.data {
Data::Struct(DataStruct {
@@ -34,41 +37,70 @@ pub fn derive_parser(input: &DeriveInput) -> TokenStream {
..
}) => {
dummies::parser_struct(ident);
- gen_for_struct(ident, &input.generics, &fields.named, &input.attrs)
+
+ let name = Name::Assigned(quote!(#pkg_name));
+ let item = Item::from_args_struct(input, name);
+ let fields = fields
+ .named
+ .iter()
+ .map(|field| {
+ let item = Item::from_args_field(field, item.casing(), item.env_casing());
+ (field, item)
+ })
+ .collect::<Vec<_>>();
+ gen_for_struct(&item, ident, &input.generics, &fields)
}
Data::Struct(DataStruct {
fields: Fields::Unit,
..
}) => {
dummies::parser_struct(ident);
- gen_for_struct(
- ident,
- &input.generics,
- &Punctuated::<Field, Comma>::new(),
- &input.attrs,
- )
+
+ let name = Name::Assigned(quote!(#pkg_name));
+ let item = Item::from_args_struct(input, name);
+ let fields = Punctuated::<Field, Comma>::new();
+ let fields = fields
+ .iter()
+ .map(|field| {
+ let item = Item::from_args_field(field, item.casing(), item.env_casing());
+ (field, item)
+ })
+ .collect::<Vec<_>>();
+ gen_for_struct(&item, ident, &input.generics, &fields)
}
Data::Enum(ref e) => {
dummies::parser_enum(ident);
- gen_for_enum(ident, &input.generics, &input.attrs, e)
+
+ let name = Name::Assigned(quote!(#pkg_name));
+ let item = Item::from_subcommand_enum(input, name);
+ let variants = e
+ .variants
+ .iter()
+ .map(|variant| {
+ let item =
+ Item::from_subcommand_variant(variant, item.casing(), item.env_casing());
+ (variant, item)
+ })
+ .collect::<Vec<_>>();
+ gen_for_enum(&item, ident, &input.generics, &variants)
}
_ => abort_call_site!("`#[derive(Parser)]` only supports non-tuple structs and enums"),
}
}
fn gen_for_struct(
- name: &Ident,
+ item: &Item,
+ item_name: &Ident,
generics: &Generics,
- fields: &Punctuated<Field, Comma>,
- attrs: &[Attribute],
+ fields: &[(&Field, Item)],
) -> TokenStream {
- let into_app = into_app::gen_for_struct(name, generics, attrs);
- let args = args::gen_for_struct(name, generics, fields, attrs);
-
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+ let into_app = into_app::gen_for_struct(item, item_name, generics);
+ let args = args::gen_for_struct(item, item_name, generics, fields);
+
quote! {
- impl #impl_generics clap::Parser for #name #ty_generics #where_clause {}
+ impl #impl_generics clap::Parser for #item_name #ty_generics #where_clause {}
#into_app
#args
@@ -76,18 +108,18 @@ fn gen_for_struct(
}
fn gen_for_enum(
- name: &Ident,
+ item: &Item,
+ item_name: &Ident,
generics: &Generics,
- attrs: &[Attribute],
- e: &DataEnum,
+ variants: &[(&Variant, Item)],
) -> TokenStream {
- let into_app = into_app::gen_for_enum(name, generics, attrs);
- let subcommand = subcommand::gen_for_enum(name, generics, attrs, e);
-
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+ let into_app = into_app::gen_for_enum(item, item_name, generics);
+ let subcommand = subcommand::gen_for_enum(item, item_name, generics, variants);
+
quote! {
- impl #impl_generics clap::Parser for #name #ty_generics #where_clause {}
+ impl #impl_generics clap::Parser for #item_name #ty_generics #where_clause {}
#into_app
#subcommand
diff --git a/vendor/clap_derive/src/derives/subcommand.rs b/vendor/clap_derive/src/derives/subcommand.rs
index 07bdce5ec..8a44e0c42 100644
--- a/vendor/clap_derive/src/derives/subcommand.rs
+++ b/vendor/clap_derive/src/derives/subcommand.rs
@@ -11,20 +11,16 @@
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.
-use crate::{
- attrs::{Attrs, Kind, Name, DEFAULT_CASING, DEFAULT_ENV_CASING},
- derives::args,
- dummies,
- utils::{is_simple_ty, subty_if_name, Sp},
-};
use proc_macro2::{Ident, Span, TokenStream};
use proc_macro_error::{abort, abort_call_site};
use quote::{format_ident, quote, quote_spanned};
-use syn::{
- punctuated::Punctuated, spanned::Spanned, Attribute, Data, DataEnum, DeriveInput,
- FieldsUnnamed, Generics, Token, Variant,
-};
+use syn::{spanned::Spanned, Data, DeriveInput, FieldsUnnamed, Generics, Variant};
+
+use crate::derives::args;
+use crate::dummies;
+use crate::item::{Item, Kind, Name};
+use crate::utils::{is_simple_ty, subty_if_name};
pub fn derive_subcommand(input: &DeriveInput) -> TokenStream {
let ident = &input.ident;
@@ -32,35 +28,47 @@ pub fn derive_subcommand(input: &DeriveInput) -> TokenStream {
dummies::subcommand(ident);
match input.data {
- Data::Enum(ref e) => gen_for_enum(ident, &input.generics, &input.attrs, e),
+ Data::Enum(ref e) => {
+ let name = Name::Derived(ident.clone());
+ let item = Item::from_subcommand_enum(input, name);
+ let variants = e
+ .variants
+ .iter()
+ .map(|variant| {
+ let item =
+ Item::from_subcommand_variant(variant, item.casing(), item.env_casing());
+ (variant, item)
+ })
+ .collect::<Vec<_>>();
+ gen_for_enum(&item, ident, &input.generics, &variants)
+ }
_ => abort_call_site!("`#[derive(Subcommand)]` only supports enums"),
}
}
pub fn gen_for_enum(
- enum_name: &Ident,
+ item: &Item,
+ item_name: &Ident,
generics: &Generics,
- attrs: &[Attribute],
- e: &DataEnum,
+ variants: &[(&Variant, Item)],
) -> TokenStream {
- let from_arg_matches = gen_from_arg_matches_for_enum(enum_name, generics, attrs, e);
-
- let attrs = Attrs::from_struct(
- Span::call_site(),
- attrs,
- Name::Derived(enum_name.clone()),
- Sp::call_site(DEFAULT_CASING),
- Sp::call_site(DEFAULT_ENV_CASING),
- );
- let augmentation = gen_augment(&e.variants, &attrs, false);
- let augmentation_update = gen_augment(&e.variants, &attrs, true);
- let has_subcommand = gen_has_subcommand(&e.variants, &attrs);
+ if !matches!(&*item.kind(), Kind::Command(_)) {
+ abort! { item.kind().span(),
+ "`{}` cannot be used with `command`",
+ item.kind().name(),
+ }
+ }
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
- quote! {
- #from_arg_matches
+ let from_arg_matches = gen_from_arg_matches(variants);
+ let update_from_arg_matches = gen_update_from_arg_matches(variants);
+
+ let augmentation = gen_augment(variants, item, false);
+ let augmentation_update = gen_augment(variants, item, true);
+ let has_subcommand = gen_has_subcommand(variants);
+ quote! {
#[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
#[allow(
clippy::style,
@@ -74,40 +82,19 @@ pub fn gen_for_enum(
clippy::suspicious_else_formatting,
)]
#[deny(clippy::correctness)]
- impl #impl_generics clap::Subcommand for #enum_name #ty_generics #where_clause {
- fn augment_subcommands <'b>(__clap_app: clap::Command<'b>) -> clap::Command<'b> {
- #augmentation
- }
- fn augment_subcommands_for_update <'b>(__clap_app: clap::Command<'b>) -> clap::Command<'b> {
- #augmentation_update
- }
- fn has_subcommand(__clap_name: &str) -> bool {
- #has_subcommand
+ impl #impl_generics clap::FromArgMatches for #item_name #ty_generics #where_clause {
+ fn from_arg_matches(__clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result<Self, clap::Error> {
+ Self::from_arg_matches_mut(&mut __clap_arg_matches.clone())
}
- }
- }
-}
-fn gen_from_arg_matches_for_enum(
- name: &Ident,
- generics: &Generics,
- attrs: &[Attribute],
- e: &DataEnum,
-) -> TokenStream {
- let attrs = Attrs::from_struct(
- Span::call_site(),
- attrs,
- Name::Derived(name.clone()),
- Sp::call_site(DEFAULT_CASING),
- Sp::call_site(DEFAULT_ENV_CASING),
- );
-
- let from_arg_matches = gen_from_arg_matches(name, &e.variants, &attrs);
- let update_from_arg_matches = gen_update_from_arg_matches(name, &e.variants, &attrs);
+ #from_arg_matches
- let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+ 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
+ }
- quote! {
#[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
#[allow(
clippy::style,
@@ -121,24 +108,23 @@ fn gen_from_arg_matches_for_enum(
clippy::suspicious_else_formatting,
)]
#[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, clap::Error> {
- Self::from_arg_matches_mut(&mut __clap_arg_matches.clone())
+ impl #impl_generics clap::Subcommand for #item_name #ty_generics #where_clause {
+ fn augment_subcommands <'b>(__clap_app: clap::Command) -> clap::Command {
+ #augmentation
}
-
- #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())
+ fn augment_subcommands_for_update <'b>(__clap_app: clap::Command) -> clap::Command {
+ #augmentation_update
+ }
+ fn has_subcommand(__clap_name: &str) -> bool {
+ #has_subcommand
}
- #update_from_arg_matches
}
}
}
fn gen_augment(
- variants: &Punctuated<Variant, Token![,]>,
- parent_attribute: &Attrs,
+ variants: &[(&Variant, Item)],
+ parent_item: &Item,
override_required: bool,
) -> TokenStream {
use syn::Fields::*;
@@ -147,16 +133,14 @@ fn gen_augment(
let subcommands: Vec<_> = variants
.iter()
- .filter_map(|variant| {
- let attrs = Attrs::from_variant(
- variant,
- parent_attribute.casing(),
- parent_attribute.env_casing(),
- );
- let kind = attrs.kind();
+ .filter_map(|(variant, item)| {
+ let kind = item.kind();
match &*kind {
- Kind::Skip(_) => None,
+ Kind::Skip(_, _) |
+ Kind::Arg(_) |
+ Kind::FromGlobal(_) |
+ Kind::Value => None,
Kind::ExternalSubcommand => {
let ty = match variant.fields {
@@ -169,47 +153,51 @@ fn gen_augment(
or `Vec<OsString>`."
),
};
- let subcommand = match subty_if_name(ty, "Vec") {
- Some(subty) => {
- if is_simple_ty(subty, "OsString") {
- quote_spanned! { kind.span()=>
- let #app_var = #app_var.allow_external_subcommands(true).allow_invalid_utf8_for_external_subcommands(true);
- }
- } else {
- quote_spanned! { kind.span()=>
- let #app_var = #app_var.allow_external_subcommands(true);
- }
- }
- }
-
- None => abort!(
+ let deprecations = if !override_required {
+ item.deprecations()
+ } else {
+ quote!()
+ };
+ let subty = subty_if_name(ty, "Vec").unwrap_or_else(|| {
+ abort!(
ty.span(),
"The type must be `Vec<_>` \
to be used with `external_subcommand`."
- ),
+ )
+ });
+ let subcommand = quote_spanned! { kind.span()=>
+ #deprecations
+ let #app_var = #app_var
+ .external_subcommand_value_parser(clap::value_parser!(#subty));
};
Some(subcommand)
}
- Kind::Flatten => match variant.fields {
+ Kind::Flatten(_) => match variant.fields {
Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => {
let ty = &unnamed[0];
- let old_heading_var = format_ident!("__clap_old_heading");
- let next_help_heading = attrs.next_help_heading();
- let next_display_order = attrs.next_display_order();
+ let deprecations = if !override_required {
+ item.deprecations()
+ } else {
+ quote!()
+ };
+ let next_help_heading = item.next_help_heading();
+ let next_display_order = item.next_display_order();
let subcommand = if override_required {
quote! {
- let #old_heading_var = #app_var.get_next_help_heading();
- let #app_var = #app_var #next_help_heading #next_display_order;
+ #deprecations
+ let #app_var = #app_var
+ #next_help_heading
+ #next_display_order;
let #app_var = <#ty as clap::Subcommand>::augment_subcommands_for_update(#app_var);
- let #app_var = #app_var.next_help_heading(#old_heading_var);
}
} else {
quote! {
- let #old_heading_var = #app_var.get_next_help_heading();
- let #app_var = #app_var #next_help_heading #next_display_order;
+ #deprecations
+ let #app_var = #app_var
+ #next_help_heading
+ #next_display_order;
let #app_var = <#ty as clap::Subcommand>::augment_subcommands(#app_var);
- let #app_var = #app_var.next_help_heading(#old_heading_var);
}
};
Some(subcommand)
@@ -248,33 +236,56 @@ 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 name = item.cased_name();
+ let deprecations = if !override_required {
+ item.deprecations()
+ } else {
+ quote!()
+ };
+ let initial_app_methods = item.initial_top_level_methods();
+ let final_from_attrs = item.final_top_level_methods();
+ let override_methods = if override_required {
+ quote_spanned! { kind.span()=>
+ .subcommand_required(false)
+ .arg_required_else_help(false)
+ }
+ } else {
+ quote!()
+ };
let subcommand = quote! {
let #app_var = #app_var.subcommand({
+ #deprecations;
let #subcommand_var = clap::Command::new(#name);
+ let #subcommand_var = #subcommand_var
+ .subcommand_required(true)
+ .arg_required_else_help(true);
let #subcommand_var = #subcommand_var #initial_app_methods;
let #subcommand_var = #arg_block;
- #[allow(deprecated)]
- let #subcommand_var = #subcommand_var.setting(clap::AppSettings::SubcommandRequiredElseHelp);
- #subcommand_var #final_from_attrs
+ #subcommand_var #final_from_attrs #override_methods
});
};
Some(subcommand)
}
- _ => {
+ Kind::Command(_) => {
let subcommand_var = Ident::new("__clap_subcommand", Span::call_site());
let sub_augment = match variant.fields {
Named(ref fields) => {
// Defer to `gen_augment` for adding cmd methods
- args::gen_augment(&fields.named, &subcommand_var, &attrs, override_required)
+ let fields = fields
+ .named
+ .iter()
+ .map(|field| {
+ let item = Item::from_args_field(field, item.casing(), item.env_casing());
+ (field, item)
+ })
+ .collect::<Vec<_>>();
+ args::gen_augment(&fields, &subcommand_var, item, override_required)
}
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();
+ let initial_app_methods = item.initial_top_level_methods();
+ let final_from_attrs = item.final_top_level_methods();
quote! {
let #subcommand_var = #subcommand_var #initial_app_methods;
let #subcommand_var = #arg_block;
@@ -296,8 +307,8 @@ fn gen_augment(
}
}
};
- let initial_app_methods = attrs.initial_top_level_methods();
- let final_from_attrs = attrs.final_top_level_methods();
+ let initial_app_methods = item.initial_top_level_methods();
+ let final_from_attrs = item.final_top_level_methods();
quote! {
let #subcommand_var = #subcommand_var #initial_app_methods;
let #subcommand_var = #arg_block;
@@ -309,9 +320,15 @@ fn gen_augment(
}
};
- let name = attrs.cased_name();
+ let deprecations = if !override_required {
+ item.deprecations()
+ } else {
+ quote!()
+ };
+ let name = item.cased_name();
let subcommand = quote! {
let #app_var = #app_var.subcommand({
+ #deprecations
let #subcommand_var = clap::Command::new(#name);
#sub_augment
});
@@ -322,46 +339,47 @@ fn gen_augment(
})
.collect();
- let initial_app_methods = parent_attribute.initial_top_level_methods();
- let final_app_methods = parent_attribute.final_top_level_methods();
+ let deprecations = if !override_required {
+ parent_item.deprecations()
+ } else {
+ quote!()
+ };
+ let initial_app_methods = parent_item.initial_top_level_methods();
+ let final_app_methods = parent_item.final_top_level_methods();
quote! {
- let #app_var = #app_var #initial_app_methods;
- #( #subcommands )*;
- #app_var #final_app_methods
+ #deprecations;
+ let #app_var = #app_var #initial_app_methods;
+ #( #subcommands )*;
+ #app_var #final_app_methods
}
}
-fn gen_has_subcommand(
- variants: &Punctuated<Variant, Token![,]>,
- parent_attribute: &Attrs,
-) -> TokenStream {
+fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> TokenStream {
use syn::Fields::*;
let mut ext_subcmd = false;
let (flatten_variants, variants): (Vec<_>, Vec<_>) = variants
.iter()
- .filter_map(|variant| {
- let attrs = Attrs::from_variant(
- variant,
- parent_attribute.casing(),
- parent_attribute.env_casing(),
- );
+ .filter_map(|(variant, item)| {
+ let kind = item.kind();
+ match &*kind {
+ Kind::Skip(_, _) | Kind::Arg(_) | Kind::FromGlobal(_) | Kind::Value => None,
- if let Kind::ExternalSubcommand = &*attrs.kind() {
- ext_subcmd = true;
- None
- } else {
- Some((variant, attrs))
+ Kind::ExternalSubcommand => {
+ ext_subcmd = true;
+ None
+ }
+ Kind::Flatten(_) | Kind::Subcommand(_) | Kind::Command(_) => Some((variant, item)),
}
})
- .partition(|(_, attrs)| {
- let kind = attrs.kind();
- matches!(&*kind, Kind::Flatten)
+ .partition(|(_, item)| {
+ let kind = item.kind();
+ matches!(&*kind, Kind::Flatten(_))
});
- let subcommands = variants.iter().map(|(_variant, attrs)| {
- let sub_name = attrs.cased_name();
+ let subcommands = variants.iter().map(|(_variant, item)| {
+ let sub_name = item.cased_name();
quote! {
if #sub_name == __clap_name {
return true
@@ -398,11 +416,7 @@ fn gen_has_subcommand(
}
}
-fn gen_from_arg_matches(
- name: &Ident,
- variants: &Punctuated<Variant, Token![,]>,
- parent_attribute: &Attrs,
-) -> TokenStream {
+fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream {
use syn::Fields::*;
let mut ext_subcmd = None;
@@ -411,71 +425,79 @@ fn gen_from_arg_matches(
let sub_arg_matches_var = format_ident!("__clap_arg_matches");
let (flatten_variants, variants): (Vec<_>, Vec<_>) = variants
.iter()
- .filter_map(|variant| {
- let attrs = Attrs::from_variant(
- variant,
- parent_attribute.casing(),
- parent_attribute.env_casing(),
- );
-
- if let Kind::ExternalSubcommand = &*attrs.kind() {
- if ext_subcmd.is_some() {
- abort!(
- attrs.kind().span(),
- "Only one variant can be marked with `external_subcommand`, \
+ .filter_map(|(variant, item)| {
+ let kind = item.kind();
+ match &*kind {
+ Kind::Skip(_, _) | Kind::Arg(_) | Kind::FromGlobal(_) | Kind::Value => None,
+
+ Kind::ExternalSubcommand => {
+ if ext_subcmd.is_some() {
+ abort!(
+ item.kind().span(),
+ "Only one variant can be marked with `external_subcommand`, \
this is the second"
- );
- }
+ );
+ }
- let ty = match variant.fields {
- Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
+ let ty = match variant.fields {
+ Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
- _ => abort!(
- variant,
- "The enum variant marked with `external_subcommand` must be \
+ _ => abort!(
+ variant,
+ "The enum variant marked with `external_subcommand` must be \
a single-typed tuple, and the type must be either `Vec<String>` \
or `Vec<OsString>`."
- ),
- };
-
- let (span, str_ty) = match subty_if_name(ty, "Vec") {
- Some(subty) => {
- if is_simple_ty(subty, "String") {
- (subty.span(), quote!(::std::string::String))
- } else if is_simple_ty(subty, "OsString") {
- (subty.span(), quote!(::std::ffi::OsString))
- } else {
- abort!(
- ty.span(),
- "The type must be either `Vec<String>` or `Vec<OsString>` \
+ ),
+ };
+
+ let (span, str_ty) = match subty_if_name(ty, "Vec") {
+ Some(subty) => {
+ if is_simple_ty(subty, "String") {
+ (subty.span(), quote!(::std::string::String))
+ } else if is_simple_ty(subty, "OsString") {
+ (subty.span(), quote!(::std::ffi::OsString))
+ } else {
+ abort!(
+ ty.span(),
+ "The type must be either `Vec<String>` or `Vec<OsString>` \
to be used with `external_subcommand`."
- );
+ );
+ }
}
- }
- None => abort!(
- ty.span(),
- "The type must be either `Vec<String>` or `Vec<OsString>` \
+ None => abort!(
+ ty.span(),
+ "The type must be either `Vec<String>` or `Vec<OsString>` \
to be used with `external_subcommand`."
- ),
- };
+ ),
+ };
- ext_subcmd = Some((span, &variant.ident, str_ty));
- None
- } else {
- Some((variant, attrs))
+ ext_subcmd = Some((span, &variant.ident, str_ty));
+ None
+ }
+ Kind::Flatten(_) | Kind::Subcommand(_) | Kind::Command(_) => Some((variant, item)),
}
})
- .partition(|(_, attrs)| {
- let kind = attrs.kind();
- matches!(&*kind, Kind::Flatten)
+ .partition(|(_, item)| {
+ let kind = item.kind();
+ matches!(&*kind, Kind::Flatten(_))
});
- let subcommands = variants.iter().map(|(variant, attrs)| {
- let sub_name = attrs.cased_name();
+ let subcommands = variants.iter().map(|(variant, item)| {
+ let sub_name = item.cased_name();
let variant_name = &variant.ident;
let constructor_block = match variant.fields {
- Named(ref fields) => args::gen_constructor(&fields.named, attrs),
+ Named(ref fields) => {
+ let fields = fields
+ .named
+ .iter()
+ .map(|field| {
+ let item = Item::from_args_field(field, item.casing(), item.env_casing());
+ (field, item)
+ })
+ .collect::<Vec<_>>();
+ args::gen_constructor(&fields)
+ },
Unit => quote!(),
Unnamed(ref fields) if fields.unnamed.len() == 1 => {
let ty = &fields.unnamed[0];
@@ -484,17 +506,9 @@ fn gen_from_arg_matches(
Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident),
};
- if cfg!(feature = "unstable-v4") {
- quote! {
- if #sub_name == #subcommand_name_var && !#sub_arg_matches_var.contains_id("") {
- return ::std::result::Result::Ok(#name :: #variant_name #constructor_block)
- }
- }
- } else {
- quote! {
- if #sub_name == #subcommand_name_var {
- return ::std::result::Result::Ok(#name :: #variant_name #constructor_block)
- }
+ quote! {
+ if #subcommand_name_var == #sub_name && !#sub_arg_matches_var.contains_id("") {
+ return ::std::result::Result::Ok(Self :: #variant_name #constructor_block)
}
}
});
@@ -510,7 +524,7 @@ fn gen_from_arg_matches(
.unwrap_or_default()
{
let __clap_res = <#ty as clap::FromArgMatches>::from_arg_matches_mut(__clap_arg_matches)?;
- return ::std::result::Result::Ok(#name :: #variant_name (__clap_res));
+ return ::std::result::Result::Ok(Self :: #variant_name (__clap_res));
}
}
}
@@ -523,12 +537,12 @@ fn gen_from_arg_matches(
let wildcard = match ext_subcmd {
Some((span, var_name, str_ty)) => quote_spanned! { span=>
- ::std::result::Result::Ok(#name::#var_name(
+ ::std::result::Result::Ok(Self::#var_name(
::std::iter::once(#str_ty::from(#subcommand_name_var))
.chain(
#sub_arg_matches_var
.remove_many::<#str_ty>("")
- .into_iter().flatten() // `""` isn't present, bug in `unstable-v4`
+ .unwrap()
.map(#str_ty::from)
)
.collect::<::std::vec::Vec<_>>()
@@ -536,7 +550,7 @@ fn gen_from_arg_matches(
},
None => quote! {
- ::std::result::Result::Err(clap::Error::raw(clap::ErrorKind::UnrecognizedSubcommand, format!("The subcommand '{}' wasn't recognized", #subcommand_name_var)))
+ ::std::result::Result::Err(clap::Error::raw(clap::error::ErrorKind::InvalidSubcommand, format!("The subcommand '{}' wasn't recognized", #subcommand_name_var)))
},
};
@@ -553,61 +567,52 @@ fn gen_from_arg_matches(
#wildcard
} else {
- ::std::result::Result::Err(clap::Error::raw(clap::ErrorKind::MissingSubcommand, "A subcommand is required but one was not provided."))
+ ::std::result::Result::Err(clap::Error::raw(clap::error::ErrorKind::MissingSubcommand, "A subcommand is required but one was not provided."))
}
}
}
}
-fn gen_update_from_arg_matches(
- name: &Ident,
- variants: &Punctuated<Variant, Token![,]>,
- parent_attribute: &Attrs,
-) -> TokenStream {
+fn gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream {
use syn::Fields::*;
let (flatten, variants): (Vec<_>, Vec<_>) = variants
.iter()
- .filter_map(|variant| {
- let attrs = Attrs::from_variant(
- variant,
- parent_attribute.casing(),
- parent_attribute.env_casing(),
- );
-
- match &*attrs.kind() {
+ .filter_map(|(variant, item)| {
+ let kind = item.kind();
+ match &*kind {
// Fallback to `from_arg_matches_mut`
- Kind::ExternalSubcommand => None,
- _ => Some((variant, attrs)),
+ Kind::Skip(_, _)
+ | Kind::Arg(_)
+ | Kind::FromGlobal(_)
+ | Kind::Value
+ | Kind::ExternalSubcommand => None,
+ Kind::Flatten(_) | Kind::Subcommand(_) | Kind::Command(_) => Some((variant, item)),
}
})
- .partition(|(_, attrs)| {
- let kind = attrs.kind();
- matches!(&*kind, Kind::Flatten)
+ .partition(|(_, item)| {
+ let kind = item.kind();
+ matches!(&*kind, Kind::Flatten(_))
});
- let subcommands = variants.iter().map(|(variant, attrs)| {
- let sub_name = attrs.cased_name();
+ let subcommands = variants.iter().map(|(variant, item)| {
+ let sub_name = item.cased_name();
let variant_name = &variant.ident;
let (pattern, updater) = match variant.fields {
Named(ref fields) => {
- let (fields, update): (Vec<_>, Vec<_>) = fields
+ let field_names = fields.named.iter().map(|field| {
+ field.ident.as_ref().unwrap()
+ }).collect::<Vec<_>>();
+ let fields = fields
.named
.iter()
.map(|field| {
- let attrs = Attrs::from_field(
- field,
- parent_attribute.casing(),
- parent_attribute.env_casing(),
- );
- let field_name = field.ident.as_ref().unwrap();
- (
- quote!( ref mut #field_name ),
- args::gen_updater(&fields.named, &attrs, false),
- )
+ let item = Item::from_args_field(field, item.casing(), item.env_casing());
+ (field, item)
})
- .unzip();
- (quote!( { #( #fields, )* }), quote!( { #( #update )* } ))
+ .collect::<Vec<_>>();
+ let update = args::gen_updater(&fields, false);
+ (quote!( { #( #field_names, )* }), quote!( { #update } ))
}
Unit => (quote!(), quote!({})),
Unnamed(ref fields) => {
@@ -626,7 +631,7 @@ fn gen_update_from_arg_matches(
};
quote! {
- #name :: #variant_name #pattern if #sub_name == __clap_name => {
+ Self :: #variant_name #pattern if #sub_name == __clap_name => {
let (_, mut __clap_arg_sub_matches) = __clap_arg_matches.remove_subcommand().unwrap();
let __clap_arg_matches = &mut __clap_arg_sub_matches;
#updater
@@ -641,7 +646,7 @@ fn gen_update_from_arg_matches(
let ty = &fields.unnamed[0];
quote! {
if <#ty as clap::Subcommand>::has_subcommand(__clap_name) {
- if let #name :: #variant_name (child) = s {
+ if let Self :: #variant_name (child) = s {
<#ty as clap::FromArgMatches>::update_from_arg_matches_mut(child, __clap_arg_matches)?;
return ::std::result::Result::Ok(());
}
diff --git a/vendor/clap_derive/src/derives/value_enum.rs b/vendor/clap_derive/src/derives/value_enum.rs
index 06d514f0e..a1411d02a 100644
--- a/vendor/clap_derive/src/derives/value_enum.rs
+++ b/vendor/clap_derive/src/derives/value_enum.rs
@@ -8,20 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use crate::{
- attrs::{Attrs, Kind, Name, DEFAULT_CASING, DEFAULT_ENV_CASING},
- dummies,
- utils::Sp,
-};
-
-use proc_macro2::{Span, TokenStream};
+use proc_macro2::TokenStream;
use proc_macro_error::{abort, abort_call_site};
use quote::quote;
use quote::quote_spanned;
-use syn::{
- punctuated::Punctuated, spanned::Spanned, token::Comma, Attribute, Data, DataEnum, DeriveInput,
- Fields, Ident, Variant,
-};
+use syn::{spanned::Spanned, Data, DeriveInput, Fields, Ident, Variant};
+
+use crate::dummies;
+use crate::item::{Item, Kind, Name};
pub fn derive_value_enum(input: &DeriveInput) -> TokenStream {
let ident = &input.ident;
@@ -29,23 +23,35 @@ pub fn derive_value_enum(input: &DeriveInput) -> TokenStream {
dummies::value_enum(ident);
match input.data {
- Data::Enum(ref e) => gen_for_enum(ident, &input.attrs, e),
+ Data::Enum(ref e) => {
+ let name = Name::Derived(ident.clone());
+ let item = Item::from_value_enum(input, name);
+ let variants = e
+ .variants
+ .iter()
+ .map(|variant| {
+ let item =
+ Item::from_value_enum_variant(variant, item.casing(), item.env_casing());
+ (variant, item)
+ })
+ .collect::<Vec<_>>();
+ gen_for_enum(&item, ident, &variants)
+ }
_ => abort_call_site!("`#[derive(ValueEnum)]` only supports enums"),
}
}
-pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStream {
- let attrs = Attrs::from_struct(
- Span::call_site(),
- attrs,
- Name::Derived(name.clone()),
- Sp::call_site(DEFAULT_CASING),
- Sp::call_site(DEFAULT_ENV_CASING),
- );
+pub fn gen_for_enum(item: &Item, item_name: &Ident, variants: &[(&Variant, Item)]) -> TokenStream {
+ if !matches!(&*item.kind(), Kind::Value) {
+ abort! { item.kind().span(),
+ "`{}` cannot be used with `value`",
+ item.kind().name(),
+ }
+ }
- let lits = lits(&e.variants, &attrs);
+ let lits = lits(variants);
let value_variants = gen_value_variants(&lits);
- let to_possible_value = gen_to_possible_value(&lits);
+ let to_possible_value = gen_to_possible_value(item, &lits);
quote! {
#[allow(dead_code, unreachable_code, unused_variables, unused_braces)]
@@ -61,38 +67,32 @@ pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStr
clippy::suspicious_else_formatting,
)]
#[deny(clippy::correctness)]
- impl clap::ValueEnum for #name {
+ impl clap::ValueEnum for #item_name {
#value_variants
#to_possible_value
}
}
}
-fn lits(
- variants: &Punctuated<Variant, Comma>,
- parent_attribute: &Attrs,
-) -> Vec<(TokenStream, Ident)> {
+fn lits(variants: &[(&Variant, Item)]) -> Vec<(TokenStream, Ident)> {
variants
.iter()
- .filter_map(|variant| {
- let attrs = Attrs::from_value_enum_variant(
- variant,
- parent_attribute.casing(),
- parent_attribute.env_casing(),
- );
- if let Kind::Skip(_) = &*attrs.kind() {
+ .filter_map(|(variant, item)| {
+ if let Kind::Skip(_, _) = &*item.kind() {
None
} else {
if !matches!(variant.fields, Fields::Unit) {
abort!(variant.span(), "`#[derive(ValueEnum)]` only supports unit variants. Non-unit variants must be skipped");
}
- let fields = attrs.field_methods(false);
- let name = attrs.cased_name();
+ let fields = item.field_methods();
+ let deprecations = item.deprecations();
+ let name = item.cased_name();
Some((
- quote_spanned! { variant.span()=>
- clap::PossibleValue::new(#name)
+ quote_spanned! { variant.span()=> {
+ #deprecations
+ clap::builder::PossibleValue::new(#name)
#fields
- },
+ }},
variant.ident.clone(),
))
}
@@ -110,11 +110,14 @@ fn gen_value_variants(lits: &[(TokenStream, Ident)]) -> TokenStream {
}
}
-fn gen_to_possible_value(lits: &[(TokenStream, Ident)]) -> TokenStream {
+fn gen_to_possible_value(item: &Item, lits: &[(TokenStream, Ident)]) -> TokenStream {
let (lit, variant): (Vec<TokenStream>, Vec<Ident>) = lits.iter().cloned().unzip();
+ let deprecations = item.deprecations();
+
quote! {
- fn to_possible_value<'a>(&self) -> ::std::option::Option<clap::PossibleValue<'a>> {
+ fn to_possible_value<'a>(&self) -> ::std::option::Option<clap::builder::PossibleValue> {
+ #deprecations
match self {
#(Self::#variant => Some(#lit),)*
_ => None