diff options
Diffstat (limited to 'vendor/clap_derive/src')
-rw-r--r-- | vendor/clap_derive/src/attr.rs | 71 | ||||
-rw-r--r-- | vendor/clap_derive/src/derives/args.rs | 119 | ||||
-rw-r--r-- | vendor/clap_derive/src/derives/into_app.rs | 22 | ||||
-rw-r--r-- | vendor/clap_derive/src/derives/parser.rs | 54 | ||||
-rw-r--r-- | vendor/clap_derive/src/derives/subcommand.rs | 554 | ||||
-rw-r--r-- | vendor/clap_derive/src/derives/value_enum.rs | 83 | ||||
-rw-r--r-- | vendor/clap_derive/src/dummies.rs | 59 | ||||
-rw-r--r-- | vendor/clap_derive/src/item.rs | 261 | ||||
-rw-r--r-- | vendor/clap_derive/src/lib.rs | 68 | ||||
-rw-r--r-- | vendor/clap_derive/src/macros.rs | 21 | ||||
-rw-r--r-- | vendor/clap_derive/src/utils/doc_comments.rs | 24 | ||||
-rw-r--r-- | vendor/clap_derive/src/utils/error.rs | 22 | ||||
-rw-r--r-- | vendor/clap_derive/src/utils/mod.rs | 2 |
13 files changed, 739 insertions, 621 deletions
diff --git a/vendor/clap_derive/src/attr.rs b/vendor/clap_derive/src/attr.rs index e282a8f94..3bc9ac014 100644 --- a/vendor/clap_derive/src/attr.rs +++ b/vendor/clap_derive/src/attr.rs @@ -1,8 +1,6 @@ use std::iter::FromIterator; use proc_macro2::TokenStream; -use proc_macro_error::abort; -use proc_macro_error::ResultExt; use quote::quote; use quote::ToTokens; use syn::spanned::Spanned; @@ -24,49 +22,44 @@ pub struct ClapAttr { } impl ClapAttr { - pub fn parse_all(all_attrs: &[Attribute]) -> Vec<Self> { - all_attrs - .iter() - .filter_map(|attr| { - let kind = if attr.path.is_ident("clap") { - Some(Sp::new(AttrKind::Clap, attr.path.span())) - } else if attr.path.is_ident("structopt") { - Some(Sp::new(AttrKind::StructOpt, attr.path.span())) - } else if attr.path.is_ident("command") { - Some(Sp::new(AttrKind::Command, attr.path.span())) - } else if attr.path.is_ident("group") { - Some(Sp::new(AttrKind::Group, attr.path.span())) - } else if attr.path.is_ident("arg") { - Some(Sp::new(AttrKind::Arg, attr.path.span())) - } else if attr.path.is_ident("value") { - Some(Sp::new(AttrKind::Value, attr.path.span())) - } else { - None - }; - kind.map(|k| (k, attr)) - }) - .flat_map(|(k, attr)| { - attr.parse_args_with(Punctuated::<ClapAttr, Token![,]>::parse_terminated) - .unwrap_or_abort() - .into_iter() - .map(move |mut a| { - a.kind = k; - a - }) - }) - .collect() + pub fn parse_all(all_attrs: &[Attribute]) -> Result<Vec<Self>, syn::Error> { + let mut parsed = Vec::new(); + for attr in all_attrs { + let kind = if attr.path().is_ident("clap") { + Sp::new(AttrKind::Clap, attr.path().span()) + } else if attr.path().is_ident("structopt") { + Sp::new(AttrKind::StructOpt, attr.path().span()) + } else if attr.path().is_ident("command") { + Sp::new(AttrKind::Command, attr.path().span()) + } else if attr.path().is_ident("group") { + Sp::new(AttrKind::Group, attr.path().span()) + } else if attr.path().is_ident("arg") { + Sp::new(AttrKind::Arg, attr.path().span()) + } else if attr.path().is_ident("value") { + Sp::new(AttrKind::Value, attr.path().span()) + } else { + continue; + }; + for mut attr in + attr.parse_args_with(Punctuated::<ClapAttr, Token![,]>::parse_terminated)? + { + attr.kind = kind; + parsed.push(attr); + } + } + Ok(parsed) } - pub fn value_or_abort(&self) -> &AttrValue { + pub fn value_or_abort(&self) -> Result<&AttrValue, syn::Error> { self.value .as_ref() - .unwrap_or_else(|| abort!(self.name, "attribute `{}` requires a value", self.name)) + .ok_or_else(|| format_err!(self.name, "attribute `{}` requires a value", self.name)) } - pub fn lit_str_or_abort(&self) -> &LitStr { - let value = self.value_or_abort(); + pub fn lit_str_or_abort(&self) -> Result<&LitStr, syn::Error> { + let value = self.value_or_abort()?; match value { - AttrValue::LitStr(tokens) => tokens, + AttrValue::LitStr(tokens) => Ok(tokens), AttrValue::Expr(_) | AttrValue::Call(_) => { abort!( self.name, @@ -133,7 +126,7 @@ impl Parse for ClapAttr { let nested; parenthesized!(nested in input); - let method_args: Punctuated<_, Token![,]> = nested.parse_terminated(Expr::parse)?; + let method_args: Punctuated<_, _> = nested.parse_terminated(Expr::parse, Token![,])?; Some(AttrValue::Call(Vec::from_iter(method_args))) } else { None diff --git a/vendor/clap_derive/src/derives/args.rs b/vendor/clap_derive/src/derives/args.rs index b5d51bfca..e8611b6bd 100644 --- a/vendor/clap_derive/src/derives/args.rs +++ b/vendor/clap_derive/src/derives/args.rs @@ -13,38 +13,33 @@ // MIT/Apache 2.0 license. 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, 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 { +pub fn derive_args(input: &DeriveInput) -> Result<TokenStream, syn::Error> { let ident = &input.ident; - dummies::args(ident); - match input.data { Data::Struct(DataStruct { fields: Fields::Named(ref fields), .. }) => { let name = Name::Derived(ident.clone()); - let item = Item::from_args_struct(input, 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) + let item = Item::from_args_field(field, item.casing(), item.env_casing())?; + Ok((field, item)) }) - .collect::<Vec<_>>(); + .collect::<Result<Vec<_>, syn::Error>>()?; gen_for_struct(&item, ident, &input.generics, &fields) } Data::Struct(DataStruct { @@ -52,15 +47,15 @@ pub fn derive_args(input: &DeriveInput) -> TokenStream { .. }) => { let name = Name::Derived(ident.clone()); - let item = Item::from_args_struct(input, 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) + let item = Item::from_args_field(field, item.casing(), item.env_casing())?; + Ok((field, item)) }) - .collect::<Vec<_>>(); + .collect::<Result<Vec<_>, syn::Error>>()?; gen_for_struct(&item, ident, &input.generics, &fields) } _ => abort_call_site!("`#[derive(Args)]` only supports non-tuple structs"), @@ -72,7 +67,7 @@ pub fn gen_for_struct( item_name: &Ident, generics: &Generics, fields: &[(&Field, Item)], -) -> TokenStream { +) -> Result<TokenStream, syn::Error> { if !matches!(&*item.kind(), Kind::Command(_)) { abort! { item.kind().span(), "`{}` cannot be used with `command`", @@ -82,22 +77,22 @@ pub fn gen_for_struct( let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - let constructor = gen_constructor(fields); - let updater = gen_updater(fields, true); + let constructor = gen_constructor(fields)?; + let updater = gen_updater(fields, true)?; let raw_deprecated = raw_deprecated(); 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 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(); + let group_id = item.group_id(); quote!(Some(clap::Id::from(#group_id))) }; - quote! { + Ok(quote! { #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] #[allow( clippy::style, @@ -109,8 +104,8 @@ pub fn gen_for_struct( clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, + clippy::almost_swapped, )] - #[deny(clippy::correctness)] 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()) @@ -144,8 +139,8 @@ pub fn gen_for_struct( clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, + clippy::almost_swapped, )] - #[deny(clippy::correctness)] impl #impl_generics clap::Args for #item_name #ty_generics #where_clause { fn group_id() -> Option<clap::Id> { #group_id @@ -157,7 +152,7 @@ pub fn gen_for_struct( #augmentation_update } } - } + }) } /// Generate a block of code to add arguments/subcommands corresponding to @@ -167,11 +162,12 @@ pub fn gen_augment( app_var: &Ident, parent_item: &Item, override_required: bool, -) -> TokenStream { +) -> Result<TokenStream, syn::Error> { let mut subcommand_specified = false; - let args = fields.iter().filter_map(|(field, item)| { + let mut args = Vec::new(); + for (field, item) in fields { let kind = item.kind(); - match &*kind { + let genned = match &*kind { Kind::Command(_) | Kind::Value | Kind::Skip(_, _) @@ -179,7 +175,10 @@ pub fn gen_augment( | Kind::ExternalSubcommand => None, Kind::Subcommand(ty) => { if subcommand_specified { - abort!(field.span(), "`#[command(subcommand)]` can only be used once per container"); + abort!( + field.span(), + "`#[command(subcommand)]` can only be used once per container" + ); } subcommand_specified = true; @@ -354,8 +353,9 @@ pub fn gen_augment( }); }) } - } - }); + }; + args.push(genned); + } let deprecations = if !override_required { parent_item.deprecations() @@ -367,7 +367,7 @@ pub fn gen_augment( let group_app_methods = if parent_item.skip_group() { quote!() } else { - let group_id = parent_item.ident().unraw().to_string(); + let group_id = parent_item.group_id(); let literal_group_members = fields .iter() .filter_map(|(_field, item)| { @@ -400,15 +400,18 @@ pub fn gen_augment( }}; } + let group_methods = parent_item.group_methods(); + quote!( .group( clap::ArgGroup::new(#group_id) .multiple(true) + #group_methods .args(#literal_group_members) ) ) }; - quote! {{ + Ok(quote! {{ #deprecations let #app_var = #app_var #initial_app_methods @@ -416,15 +419,15 @@ pub fn gen_augment( ; #( #args )* #app_var #final_app_methods - }} + }}) } -pub fn gen_constructor(fields: &[(&Field, Item)]) -> TokenStream { +pub fn gen_constructor(fields: &[(&Field, Item)]) -> Result<TokenStream, syn::Error> { let fields = fields.iter().map(|(field, item)| { let field_name = field.ident.as_ref().unwrap(); let kind = item.kind(); let arg_matches = format_ident!("__clap_arg_matches"); - match &*kind { + let genned = match &*kind { Kind::Command(_) | Kind::Value | Kind::ExternalSubcommand => { @@ -519,18 +522,20 @@ pub fn gen_constructor(fields: &[(&Field, Item)]) -> TokenStream { }, Kind::Arg(ty) | Kind::FromGlobal(ty) => { - gen_parsers(item, ty, field_name, field, None) + gen_parsers(item, ty, field_name, field, None)? } - } - }); + }; + Ok(genned) + }).collect::<Result<Vec<_>, syn::Error>>()?; - quote! {{ + Ok(quote! {{ #( #fields ),* - }} + }}) } -pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> TokenStream { - let fields = fields.iter().map(|(field, item)| { +pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> Result<TokenStream, syn::Error> { + let mut genned_fields = Vec::new(); + for (field, item) in fields { let field_name = field.ident.as_ref().unwrap(); let kind = item.kind(); @@ -544,10 +549,8 @@ pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> TokenStream { }; let arg_matches = format_ident!("__clap_arg_matches"); - match &*kind { - Kind::Command(_) - | Kind::Value - | Kind::ExternalSubcommand => { + let genned = match &*kind { + Kind::Command(_) | Kind::Value | Kind::ExternalSubcommand => { abort! { kind.span(), "`{}` cannot be used with `arg`", kind.name(), @@ -617,17 +620,20 @@ pub fn gen_updater(fields: &[(&Field, Item)], use_self: bool) -> TokenStream { #updater } } - }, + } Kind::Skip(_, _) => quote!(), - Kind::Arg(ty) | Kind::FromGlobal(ty) => gen_parsers(item, ty, field_name, field, Some(&access)), - } - }); - - quote! { - #( #fields )* + Kind::Arg(ty) | Kind::FromGlobal(ty) => { + gen_parsers(item, ty, field_name, field, Some(&access))? + } + }; + genned_fields.push(genned); } + + Ok(quote! { + #( #genned_fields )* + }) } fn gen_parsers( @@ -636,7 +642,7 @@ fn gen_parsers( field_name: &Ident, field: &Field, update: Option<&TokenStream>, -) -> TokenStream { +) -> Result<TokenStream, syn::Error> { let span = ty.span(); let convert_type = inner_type(&field.ty); let id = item.id(); @@ -709,7 +715,7 @@ fn gen_parsers( } }; - if let Some(access) = update { + let genned = if let Some(access) = update { quote_spanned! { field.span()=> if #arg_matches.contains_id(#id) { #access @@ -718,7 +724,8 @@ fn gen_parsers( } } else { quote_spanned!(field.span()=> #field_name: #field_value ) - } + }; + Ok(genned) } #[cfg(feature = "raw-deprecated")] diff --git a/vendor/clap_derive/src/derives/into_app.rs b/vendor/clap_derive/src/derives/into_app.rs index a45667ab2..72f081fd8 100644 --- a/vendor/clap_derive/src/derives/into_app.rs +++ b/vendor/clap_derive/src/derives/into_app.rs @@ -18,7 +18,11 @@ use syn::{Generics, Ident}; use crate::item::Item; -pub fn gen_for_struct(item: &Item, item_name: &Ident, generics: &Generics) -> TokenStream { +pub fn gen_for_struct( + item: &Item, + item_name: &Ident, + generics: &Generics, +) -> Result<TokenStream, syn::Error> { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let name = item.cased_name(); @@ -36,8 +40,8 @@ pub fn gen_for_struct(item: &Item, item_name: &Ident, generics: &Generics) -> To clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, + clippy::almost_swapped, )] - #[deny(clippy::correctness)] impl #impl_generics clap::CommandFactory for #item_name #ty_generics #where_clause { fn command<'b>() -> clap::Command { let #app_var = clap::Command::new(#name); @@ -51,16 +55,20 @@ pub fn gen_for_struct(item: &Item, item_name: &Ident, generics: &Generics) -> To } }; - tokens + Ok(tokens) } -pub fn gen_for_enum(item: &Item, item_name: &Ident, generics: &Generics) -> TokenStream { +pub fn gen_for_enum( + item: &Item, + item_name: &Ident, + generics: &Generics, +) -> Result<TokenStream, syn::Error> { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let name = item.cased_name(); let app_var = Ident::new("__clap_app", Span::call_site()); - quote! { + Ok(quote! { #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] #[allow( clippy::style, @@ -72,8 +80,8 @@ pub fn gen_for_enum(item: &Item, item_name: &Ident, generics: &Generics) -> Toke clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, + clippy::almost_swapped, )] - #[deny(clippy::correctness)] impl #impl_generics clap::CommandFactory for #item_name #ty_generics #where_clause { fn command<'b>() -> clap::Command { let #app_var = clap::Command::new(#name) @@ -89,5 +97,5 @@ pub fn gen_for_enum(item: &Item, item_name: &Ident, generics: &Generics) -> Toke .arg_required_else_help(false) } } - } + }) } diff --git a/vendor/clap_derive/src/derives/parser.rs b/vendor/clap_derive/src/derives/parser.rs index 617857cac..39b0b8a77 100644 --- a/vendor/clap_derive/src/derives/parser.rs +++ b/vendor/clap_derive/src/derives/parser.rs @@ -13,7 +13,6 @@ // MIT/Apache 2.0 license. use proc_macro2::TokenStream; -use proc_macro_error::abort_call_site; use quote::quote; use syn::Ident; use syn::Variant; @@ -23,11 +22,10 @@ use syn::{ }; 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 { +pub fn derive_parser(input: &DeriveInput) -> Result<TokenStream, syn::Error> { let ident = &input.ident; let pkg_name = std::env::var("CARGO_PKG_NAME").ok().unwrap_or_default(); @@ -36,52 +34,46 @@ pub fn derive_parser(input: &DeriveInput) -> TokenStream { fields: Fields::Named(ref fields), .. }) => { - dummies::parser_struct(ident); - let name = Name::Assigned(quote!(#pkg_name)); - let item = Item::from_args_struct(input, 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) + let item = Item::from_args_field(field, item.casing(), item.env_casing())?; + Ok((field, item)) }) - .collect::<Vec<_>>(); + .collect::<Result<Vec<_>, syn::Error>>()?; gen_for_struct(&item, ident, &input.generics, &fields) } Data::Struct(DataStruct { fields: Fields::Unit, .. }) => { - dummies::parser_struct(ident); - let name = Name::Assigned(quote!(#pkg_name)); - let item = Item::from_args_struct(input, 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) + let item = Item::from_args_field(field, item.casing(), item.env_casing())?; + Ok((field, item)) }) - .collect::<Vec<_>>(); + .collect::<Result<Vec<_>, syn::Error>>()?; gen_for_struct(&item, ident, &input.generics, &fields) } Data::Enum(ref e) => { - dummies::parser_enum(ident); - let name = Name::Assigned(quote!(#pkg_name)); - let item = Item::from_subcommand_enum(input, 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) + Item::from_subcommand_variant(variant, item.casing(), item.env_casing())?; + Ok((variant, item)) }) - .collect::<Vec<_>>(); + .collect::<Result<Vec<_>, syn::Error>>()?; gen_for_enum(&item, ident, &input.generics, &variants) } _ => abort_call_site!("`#[derive(Parser)]` only supports non-tuple structs and enums"), @@ -93,18 +85,18 @@ fn gen_for_struct( item_name: &Ident, generics: &Generics, fields: &[(&Field, Item)], -) -> TokenStream { +) -> Result<TokenStream, syn::Error> { 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); + let into_app = into_app::gen_for_struct(item, item_name, generics)?; + let args = args::gen_for_struct(item, item_name, generics, fields)?; - quote! { + Ok(quote! { impl #impl_generics clap::Parser for #item_name #ty_generics #where_clause {} #into_app #args - } + }) } fn gen_for_enum( @@ -112,16 +104,16 @@ fn gen_for_enum( item_name: &Ident, generics: &Generics, variants: &[(&Variant, Item)], -) -> TokenStream { +) -> Result<TokenStream, syn::Error> { 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); + let into_app = into_app::gen_for_enum(item, item_name, generics)?; + let subcommand = subcommand::gen_for_enum(item, item_name, generics, variants)?; - quote! { + Ok(quote! { 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 8a44e0c42..403fe4557 100644 --- a/vendor/clap_derive/src/derives/subcommand.rs +++ b/vendor/clap_derive/src/derives/subcommand.rs @@ -13,33 +13,29 @@ // MIT/Apache 2.0 license. use proc_macro2::{Ident, Span, TokenStream}; -use proc_macro_error::{abort, abort_call_site}; use quote::{format_ident, quote, quote_spanned}; 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 { +pub fn derive_subcommand(input: &DeriveInput) -> Result<TokenStream, syn::Error> { let ident = &input.ident; - dummies::subcommand(ident); - match input.data { Data::Enum(ref e) => { let name = Name::Derived(ident.clone()); - let item = Item::from_subcommand_enum(input, 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) + Item::from_subcommand_variant(variant, item.casing(), item.env_casing())?; + Ok((variant, item)) }) - .collect::<Vec<_>>(); + .collect::<Result<Vec<_>, syn::Error>>()?; gen_for_enum(&item, ident, &input.generics, &variants) } _ => abort_call_site!("`#[derive(Subcommand)]` only supports enums"), @@ -51,7 +47,7 @@ pub fn gen_for_enum( item_name: &Ident, generics: &Generics, variants: &[(&Variant, Item)], -) -> TokenStream { +) -> Result<TokenStream, syn::Error> { if !matches!(&*item.kind(), Kind::Command(_)) { abort! { item.kind().span(), "`{}` cannot be used with `command`", @@ -61,14 +57,14 @@ pub fn gen_for_enum( let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); - let from_arg_matches = gen_from_arg_matches(variants); - let update_from_arg_matches = gen_update_from_arg_matches(variants); + 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); + let augmentation = gen_augment(variants, item, false)?; + let augmentation_update = gen_augment(variants, item, true)?; + let has_subcommand = gen_has_subcommand(variants)?; - quote! { + Ok(quote! { #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] #[allow( clippy::style, @@ -80,8 +76,8 @@ pub fn gen_for_enum( clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, + clippy::almost_swapped, )] - #[deny(clippy::correctness)] 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()) @@ -106,8 +102,8 @@ pub fn gen_for_enum( clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, + clippy::almost_swapped, )] - #[deny(clippy::correctness)] impl #impl_generics clap::Subcommand for #item_name #ty_generics #where_clause { fn augment_subcommands <'b>(__clap_app: clap::Command) -> clap::Command { #augmentation @@ -119,225 +115,222 @@ pub fn gen_for_enum( #has_subcommand } } - } + }) } fn gen_augment( variants: &[(&Variant, Item)], parent_item: &Item, override_required: bool, -) -> TokenStream { +) -> Result<TokenStream, syn::Error> { use syn::Fields::*; let app_var = Ident::new("__clap_app", Span::call_site()); - let subcommands: Vec<_> = variants - .iter() - .filter_map(|(variant, item)| { - let kind = item.kind(); + let mut subcommands = Vec::new(); + for (variant, item) in variants { + let kind = item.kind(); - match &*kind { - Kind::Skip(_, _) | - Kind::Arg(_) | - Kind::FromGlobal(_) | - Kind::Value => None, + let genned = match &*kind { + Kind::Skip(_, _) | Kind::Arg(_) | Kind::FromGlobal(_) | Kind::Value => None, - Kind::ExternalSubcommand => { - let ty = match variant.fields { - Unnamed(ref fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty, + Kind::ExternalSubcommand => { + 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 deprecations = if !override_required { + item.deprecations() + } else { + quote!() + }; + let subty = subty_if_name(ty, "Vec").ok_or_else(|| { + format_err!( + 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 { + Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { + let ty = &unnamed[0]; 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)); + let next_help_heading = item.next_help_heading(); + let next_display_order = item.next_display_order(); + let subcommand = if override_required { + quote! { + #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); + } + } else { + quote! { + #deprecations + let #app_var = #app_var + #next_help_heading + #next_display_order; + let #app_var = <#ty as clap::Subcommand>::augment_subcommands(#app_var); + } }; Some(subcommand) } + _ => abort!( + variant, + "`flatten` is usable only with single-typed tuple variants" + ), + }, - Kind::Flatten(_) => match variant.fields { + Kind::Subcommand(_) => { + let subcommand_var = Ident::new("__clap_subcommand", Span::call_site()); + let arg_block = match variant.fields { + Named(_) => { + abort!(variant, "non single-typed tuple enums are not supported") + } + Unit => quote!( #subcommand_var ), Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { let ty = &unnamed[0]; - 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! { - #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); + if override_required { + quote_spanned! { ty.span()=> + { + <#ty as clap::Subcommand>::augment_subcommands_for_update(#subcommand_var) + } } } else { - quote! { - #deprecations - let #app_var = #app_var - #next_help_heading - #next_display_order; - let #app_var = <#ty as clap::Subcommand>::augment_subcommands(#app_var); - } - }; - Some(subcommand) - } - _ => abort!( - variant, - "`flatten` is usable only with single-typed tuple variants" - ), - }, - - Kind::Subcommand(_) => { - let subcommand_var = Ident::new("__clap_subcommand", Span::call_site()); - let arg_block = match variant.fields { - Named(_) => { - abort!(variant, "non single-typed tuple enums are not supported") - } - Unit => quote!( #subcommand_var ), - Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { - let ty = &unnamed[0]; - if override_required { - quote_spanned! { ty.span()=> - { - <#ty as clap::Subcommand>::augment_subcommands_for_update(#subcommand_var) - } - } - } else { - quote_spanned! { ty.span()=> - { - <#ty as clap::Subcommand>::augment_subcommands(#subcommand_var) - } + quote_spanned! { ty.span()=> + { + <#ty as clap::Subcommand>::augment_subcommands(#subcommand_var) } } } - Unnamed(..) => { - abort!(variant, "non single-typed tuple enums are not supported") - } - }; + } + Unnamed(..) => { + abort!(variant, "non single-typed tuple enums are not supported") + } + }; - 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 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; + #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 + let fields = fields + .named + .iter() + .map(|field| { + let item = + Item::from_args_field(field, item.casing(), item.env_casing())?; + Ok((field, item)) + }) + .collect::<Result<Vec<_>, syn::Error>>()?; + args::gen_augment(&fields, &subcommand_var, item, override_required)? + } + Unit => { + let arg_block = quote!( #subcommand_var ); + 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; - #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 - 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) + #subcommand_var #final_from_attrs } - Unit => { - let arg_block = quote!( #subcommand_var ); - 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; - #subcommand_var #final_from_attrs - } - }, - Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { - let ty = &unnamed[0]; - let arg_block = if override_required { - quote_spanned! { ty.span()=> - { - <#ty as clap::Args>::augment_args_for_update(#subcommand_var) - } + } + Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { + let ty = &unnamed[0]; + let arg_block = if override_required { + quote_spanned! { ty.span()=> + { + <#ty as clap::Args>::augment_args_for_update(#subcommand_var) } - } else { - quote_spanned! { ty.span()=> - { - <#ty as clap::Args>::augment_args(#subcommand_var) - } + } + } else { + quote_spanned! { ty.span()=> + { + <#ty as clap::Args>::augment_args(#subcommand_var) } - }; - 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; - #subcommand_var #final_from_attrs } + }; + 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; + #subcommand_var #final_from_attrs } - Unnamed(..) => { - abort!(variant, "non single-typed tuple enums are not supported") - } - }; + } + Unnamed(..) => { + abort!(variant, "non single-typed tuple enums are not supported") + } + }; - 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 - }); - }; - Some(subcommand) - } + 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 + }); + }; + Some(subcommand) } - }) - .collect(); + }; + subcommands.push(genned); + } let deprecations = if !override_required { parent_item.deprecations() @@ -346,15 +339,15 @@ fn gen_augment( }; let initial_app_methods = parent_item.initial_top_level_methods(); let final_app_methods = parent_item.final_top_level_methods(); - quote! { + Ok(quote! { #deprecations; let #app_var = #app_var #initial_app_methods; #( #subcommands )*; #app_var #final_app_methods - } + }) } -fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> TokenStream { +fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error> { use syn::Fields::*; let mut ext_subcmd = false; @@ -391,19 +384,20 @@ fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> TokenStream { .map(|(variant, _attrs)| match variant.fields { Unnamed(ref fields) if fields.unnamed.len() == 1 => { let ty = &fields.unnamed[0]; - quote! { + Ok(quote! { if <#ty as clap::Subcommand>::has_subcommand(__clap_name) { return true; } - } + }) } _ => abort!( variant, "`flatten` is usable only with single-typed tuple variants" ), - }); + }) + .collect::<Result<Vec<_>, syn::Error>>()?; - if ext_subcmd { + let genned = if ext_subcmd { quote! { true } } else { quote! { @@ -413,77 +407,79 @@ fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> TokenStream { false } - } + }; + Ok(genned) } -fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream { +fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error> { use syn::Fields::*; - let mut ext_subcmd = None; - let subcommand_name_var = format_ident!("__clap_name"); let sub_arg_matches_var = format_ident!("__clap_arg_matches"); - let (flatten_variants, variants): (Vec<_>, Vec<_>) = variants - .iter() - .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`, \ + let mut ext_subcmd = None; + let mut flatten_variants = Vec::new(); + let mut unflatten_variants = Vec::new(); + for (variant, item) in variants { + let kind = item.kind(); + match &*kind { + Kind::Skip(_, _) | Kind::Arg(_) | Kind::FromGlobal(_) | Kind::Value => {} + + 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 + ext_subcmd = Some((span, &variant.ident, str_ty)); + } + Kind::Flatten(_) | Kind::Subcommand(_) | Kind::Command(_) => { + if matches!(&*item.kind(), Kind::Flatten(_)) { + flatten_variants.push((variant, item)); + } else { + unflatten_variants.push((variant, item)); } - Kind::Flatten(_) | Kind::Subcommand(_) | Kind::Command(_) => Some((variant, item)), } - }) - .partition(|(_, item)| { - let kind = item.kind(); - matches!(&*kind, Kind::Flatten(_)) - }); + } + } - let subcommands = variants.iter().map(|(variant, item)| { + let subcommands = unflatten_variants.iter().map(|(variant, item)| { let sub_name = item.cased_name(); let variant_name = &variant.ident; let constructor_block = match variant.fields { @@ -492,11 +488,11 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream { .named .iter() .map(|field| { - let item = Item::from_args_field(field, item.casing(), item.env_casing()); - (field, item) + let item = Item::from_args_field(field, item.casing(), item.env_casing())?; + Ok((field, item)) }) - .collect::<Vec<_>>(); - args::gen_constructor(&fields) + .collect::<Result<Vec<_>, syn::Error>>()?; + args::gen_constructor(&fields)? }, Unit => quote!(), Unnamed(ref fields) if fields.unnamed.len() == 1 => { @@ -506,18 +502,18 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream { Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident), }; - quote! { + Ok(quote! { if #subcommand_name_var == #sub_name && !#sub_arg_matches_var.contains_id("") { return ::std::result::Result::Ok(Self :: #variant_name #constructor_block) } - } - }); + }) + }).collect::<Result<Vec<_>, syn::Error>>()?; let child_subcommands = flatten_variants.iter().map(|(variant, _attrs)| { let variant_name = &variant.ident; match variant.fields { Unnamed(ref fields) if fields.unnamed.len() == 1 => { let ty = &fields.unnamed[0]; - quote! { + Ok(quote! { if __clap_arg_matches .subcommand_name() .map(|__clap_name| <#ty as clap::Subcommand>::has_subcommand(__clap_name)) @@ -526,14 +522,14 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream { let __clap_res = <#ty as clap::FromArgMatches>::from_arg_matches_mut(__clap_arg_matches)?; return ::std::result::Result::Ok(Self :: #variant_name (__clap_res)); } - } + }) } _ => abort!( variant, "`flatten` is usable only with single-typed tuple variants" ), } - }); + }).collect::<Result<Vec<_>, syn::Error>>()?; let wildcard = match ext_subcmd { Some((span, var_name, str_ty)) => quote_spanned! { span=> @@ -555,7 +551,7 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream { }; let raw_deprecated = args::raw_deprecated(); - quote! { + Ok(quote! { fn from_arg_matches_mut(__clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result<Self, clap::Error> { #raw_deprecated @@ -570,10 +566,10 @@ fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream { ::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(variants: &[(&Variant, Item)]) -> TokenStream { +fn gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error> { use syn::Fields::*; let (flatten, variants): (Vec<_>, Vec<_>) = variants @@ -607,11 +603,11 @@ fn gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream { .named .iter() .map(|field| { - let item = Item::from_args_field(field, item.casing(), item.env_casing()); - (field, item) + let item = Item::from_args_field(field, item.casing(), item.env_casing())?; + Ok((field, item)) }) - .collect::<Vec<_>>(); - let update = args::gen_updater(&fields, false); + .collect::<Result<Vec<_>, syn::Error>>()?; + let update = args::gen_updater(&fields, false)?; (quote!( { #( #field_names, )* }), quote!( { #update } )) } Unit => (quote!(), quote!({})), @@ -630,38 +626,38 @@ fn gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream { } }; - quote! { + Ok(quote! { 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 } - } - }); + }) + }).collect::<Result<Vec<_>, _>>()?; let child_subcommands = flatten.iter().map(|(variant, _attrs)| { let variant_name = &variant.ident; match variant.fields { Unnamed(ref fields) if fields.unnamed.len() == 1 => { let ty = &fields.unnamed[0]; - quote! { + Ok(quote! { if <#ty as clap::Subcommand>::has_subcommand(__clap_name) { 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(()); } } - } + }) } _ => abort!( variant, "`flatten` is usable only with single-typed tuple variants" ), } - }); + }).collect::<Result<Vec<_>, _>>()?; let raw_deprecated = args::raw_deprecated(); - quote! { + Ok(quote! { fn update_from_arg_matches_mut<'b>( &mut self, __clap_arg_matches: &mut clap::ArgMatches, @@ -679,5 +675,5 @@ fn gen_update_from_arg_matches(variants: &[(&Variant, Item)]) -> TokenStream { } ::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 a1411d02a..6f107c01c 100644 --- a/vendor/clap_derive/src/derives/value_enum.rs +++ b/vendor/clap_derive/src/derives/value_enum.rs @@ -9,39 +9,36 @@ // except according to those terms. use proc_macro2::TokenStream; -use proc_macro_error::{abort, abort_call_site}; use quote::quote; use quote::quote_spanned; 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 { +pub fn derive_value_enum(input: &DeriveInput) -> Result<TokenStream, syn::Error> { let ident = &input.ident; - dummies::value_enum(ident); - match input.data { 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<_>>(); + let item = Item::from_value_enum(input, name)?; + let mut variants = Vec::new(); + for variant in &e.variants { + let item = + Item::from_value_enum_variant(variant, item.casing(), item.env_casing())?; + variants.push((variant, item)); + } gen_for_enum(&item, ident, &variants) } _ => abort_call_site!("`#[derive(ValueEnum)]` only supports enums"), } } -pub fn gen_for_enum(item: &Item, item_name: &Ident, variants: &[(&Variant, Item)]) -> TokenStream { +pub fn gen_for_enum( + item: &Item, + item_name: &Ident, + variants: &[(&Variant, Item)], +) -> Result<TokenStream, syn::Error> { if !matches!(&*item.kind(), Kind::Value) { abort! { item.kind().span(), "`{}` cannot be used with `value`", @@ -49,11 +46,11 @@ pub fn gen_for_enum(item: &Item, item_name: &Ident, variants: &[(&Variant, Item) } } - let lits = lits(variants); + let lits = lits(variants)?; let value_variants = gen_value_variants(&lits); let to_possible_value = gen_to_possible_value(item, &lits); - quote! { + Ok(quote! { #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] #[allow( clippy::style, @@ -65,39 +62,37 @@ pub fn gen_for_enum(item: &Item, item_name: &Ident, variants: &[(&Variant, Item) clippy::nursery, clippy::cargo, clippy::suspicious_else_formatting, + clippy::almost_swapped, )] - #[deny(clippy::correctness)] impl clap::ValueEnum for #item_name { #value_variants #to_possible_value } - } + }) } -fn lits(variants: &[(&Variant, Item)]) -> Vec<(TokenStream, Ident)> { - variants - .iter() - .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 = item.field_methods(); - let deprecations = item.deprecations(); - let name = item.cased_name(); - Some(( - quote_spanned! { variant.span()=> { - #deprecations - clap::builder::PossibleValue::new(#name) - #fields - }}, - variant.ident.clone(), - )) - } - }) - .collect::<Vec<_>>() +fn lits(variants: &[(&Variant, Item)]) -> Result<Vec<(TokenStream, Ident)>, syn::Error> { + let mut genned = Vec::new(); + for (variant, item) in variants { + if let Kind::Skip(_, _) = &*item.kind() { + continue; + } + if !matches!(variant.fields, Fields::Unit) { + abort!(variant.span(), "`#[derive(ValueEnum)]` only supports unit variants. Non-unit variants must be skipped"); + } + let fields = item.field_methods(); + let deprecations = item.deprecations(); + let name = item.cased_name(); + genned.push(( + quote_spanned! { variant.span()=> { + #deprecations + clap::builder::PossibleValue::new(#name) + #fields + }}, + variant.ident.clone(), + )); + } + Ok(genned) } fn gen_value_variants(lits: &[(TokenStream, Ident)]) -> TokenStream { diff --git a/vendor/clap_derive/src/dummies.rs b/vendor/clap_derive/src/dummies.rs index 1f54e1dbc..b10bedc64 100644 --- a/vendor/clap_derive/src/dummies.rs +++ b/vendor/clap_derive/src/dummies.rs @@ -1,23 +1,20 @@ //! Dummy implementations that we emit along with an error. use proc_macro2::Ident; -use proc_macro_error::append_dummy; use quote::quote; -pub fn parser_struct(name: &Ident) { - into_app(name); - args(name); - append_dummy(quote!( impl clap::Parser for #name {} )); +#[must_use] +pub fn parser(name: &Ident) -> proc_macro2::TokenStream { + let into_app = into_app(name); + quote!( + impl clap::Parser for #name {} + #into_app + ) } -pub fn parser_enum(name: &Ident) { - into_app(name); - subcommand(name); - append_dummy(quote!( impl clap::Parser for #name {} )); -} - -pub fn into_app(name: &Ident) { - append_dummy(quote! { +#[must_use] +pub fn into_app(name: &Ident) -> proc_macro2::TokenStream { + quote! { impl clap::CommandFactory for #name { fn command<'b>() -> clap::Command { unimplemented!() @@ -26,11 +23,12 @@ pub fn into_app(name: &Ident) { unimplemented!() } } - }); + } } -pub fn from_arg_matches(name: &Ident) { - append_dummy(quote! { +#[must_use] +pub fn from_arg_matches(name: &Ident) -> proc_macro2::TokenStream { + quote! { impl clap::FromArgMatches for #name { fn from_arg_matches(_m: &clap::ArgMatches) -> ::std::result::Result<Self, clap::Error> { unimplemented!() @@ -39,12 +37,13 @@ pub fn from_arg_matches(name: &Ident) { unimplemented!() } } - }); + } } -pub fn subcommand(name: &Ident) { - from_arg_matches(name); - append_dummy(quote! { +#[must_use] +pub fn subcommand(name: &Ident) -> proc_macro2::TokenStream { + let from_arg_matches = from_arg_matches(name); + quote! { impl clap::Subcommand for #name { fn augment_subcommands(_cmd: clap::Command) -> clap::Command { unimplemented!() @@ -56,12 +55,14 @@ pub fn subcommand(name: &Ident) { unimplemented!() } } - }); + #from_arg_matches + } } -pub fn args(name: &Ident) { - from_arg_matches(name); - append_dummy(quote! { +#[must_use] +pub fn args(name: &Ident) -> proc_macro2::TokenStream { + let from_arg_matches = from_arg_matches(name); + quote! { impl clap::Args for #name { fn augment_args(_cmd: clap::Command) -> clap::Command { unimplemented!() @@ -70,11 +71,13 @@ pub fn args(name: &Ident) { unimplemented!() } } - }); + #from_arg_matches + } } -pub fn value_enum(name: &Ident) { - append_dummy(quote! { +#[must_use] +pub fn value_enum(name: &Ident) -> proc_macro2::TokenStream { + quote! { impl clap::ValueEnum for #name { fn value_variants<'a>() -> &'a [Self]{ unimplemented!() @@ -86,5 +89,5 @@ pub fn value_enum(name: &Ident) { unimplemented!() } } - }) + } } diff --git a/vendor/clap_derive/src/item.rs b/vendor/clap_derive/src/item.rs index 5e8272ac0..9b29ff9e8 100644 --- a/vendor/clap_derive/src/item.rs +++ b/vendor/clap_derive/src/item.rs @@ -16,7 +16,6 @@ use std::env; use heck::{ToKebabCase, ToLowerCamelCase, ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase}; use proc_macro2::{self, Span, TokenStream}; -use proc_macro_error::abort; use quote::{format_ident, quote, quote_spanned, ToTokens}; use syn::DeriveInput; use syn::{self, ext::IdentExt, spanned::Spanned, Attribute, Field, Ident, LitStr, Type, Variant}; @@ -33,7 +32,6 @@ pub const DEFAULT_ENV_CASING: CasingStyle = CasingStyle::ScreamingSnake; #[derive(Clone)] pub struct Item { name: Name, - ident: Ident, casing: Sp<CasingStyle>, env_casing: Sp<CasingStyle>, ty: Option<Type>, @@ -49,11 +47,13 @@ pub struct Item { is_enum: bool, is_positional: bool, skip_group: bool, + group_id: Name, + group_methods: Vec<Method>, kind: Sp<Kind>, } impl Item { - pub fn from_args_struct(input: &DeriveInput, name: Name) -> Self { + pub fn from_args_struct(input: &DeriveInput, name: Name) -> Result<Self, syn::Error> { let ident = input.ident.clone(); let span = input.ident.span(); let attrs = &input.attrs; @@ -62,15 +62,15 @@ impl Item { let kind = Sp::new(Kind::Command(Sp::new(Ty::Other, span)), span); let mut res = Self::new(name, ident, None, argument_casing, env_casing, kind); - let parsed_attrs = ClapAttr::parse_all(attrs); - res.infer_kind(&parsed_attrs); - res.push_attrs(&parsed_attrs); + let parsed_attrs = ClapAttr::parse_all(attrs)?; + res.infer_kind(&parsed_attrs)?; + res.push_attrs(&parsed_attrs)?; res.push_doc_comment(attrs, "about", Some("long_about")); - res + Ok(res) } - pub fn from_subcommand_enum(input: &DeriveInput, name: Name) -> Self { + pub fn from_subcommand_enum(input: &DeriveInput, name: Name) -> Result<Self, syn::Error> { let ident = input.ident.clone(); let span = input.ident.span(); let attrs = &input.attrs; @@ -79,15 +79,15 @@ impl Item { let kind = Sp::new(Kind::Command(Sp::new(Ty::Other, span)), span); let mut res = Self::new(name, ident, None, argument_casing, env_casing, kind); - let parsed_attrs = ClapAttr::parse_all(attrs); - res.infer_kind(&parsed_attrs); - res.push_attrs(&parsed_attrs); + let parsed_attrs = ClapAttr::parse_all(attrs)?; + res.infer_kind(&parsed_attrs)?; + res.push_attrs(&parsed_attrs)?; res.push_doc_comment(attrs, "about", Some("long_about")); - res + Ok(res) } - pub fn from_value_enum(input: &DeriveInput, name: Name) -> Self { + pub fn from_value_enum(input: &DeriveInput, name: Name) -> Result<Self, syn::Error> { let ident = input.ident.clone(); let span = input.ident.span(); let attrs = &input.attrs; @@ -96,9 +96,9 @@ impl Item { let kind = Sp::new(Kind::Value, span); let mut res = Self::new(name, ident, None, argument_casing, env_casing, kind); - let parsed_attrs = ClapAttr::parse_all(attrs); - res.infer_kind(&parsed_attrs); - res.push_attrs(&parsed_attrs); + let parsed_attrs = ClapAttr::parse_all(attrs)?; + res.infer_kind(&parsed_attrs)?; + res.push_attrs(&parsed_attrs)?; // Ignoring `push_doc_comment` as there is no top-level clap builder to add documentation // to @@ -110,14 +110,14 @@ impl Item { ); } - res + Ok(res) } pub fn from_subcommand_variant( variant: &Variant, struct_casing: Sp<CasingStyle>, env_casing: Sp<CasingStyle>, - ) -> Self { + ) -> Result<Self, syn::Error> { let name = variant.ident.clone(); let ident = variant.ident.clone(); let span = variant.span(); @@ -138,9 +138,9 @@ impl Item { env_casing, kind, ); - let parsed_attrs = ClapAttr::parse_all(&variant.attrs); - res.infer_kind(&parsed_attrs); - res.push_attrs(&parsed_attrs); + let parsed_attrs = ClapAttr::parse_all(&variant.attrs)?; + res.infer_kind(&parsed_attrs)?; + res.push_attrs(&parsed_attrs)?; if matches!(&*res.kind, Kind::Command(_) | Kind::Subcommand(_)) { res.push_doc_comment(&variant.attrs, "about", Some("long_about")); } @@ -164,14 +164,14 @@ impl Item { | Kind::Arg(_) => (), } - res + Ok(res) } pub fn from_value_enum_variant( variant: &Variant, argument_casing: Sp<CasingStyle>, env_casing: Sp<CasingStyle>, - ) -> Self { + ) -> Result<Self, syn::Error> { let ident = variant.ident.clone(); let span = variant.span(); let kind = Sp::new(Kind::Value, span); @@ -183,21 +183,21 @@ impl Item { env_casing, kind, ); - let parsed_attrs = ClapAttr::parse_all(&variant.attrs); - res.infer_kind(&parsed_attrs); - res.push_attrs(&parsed_attrs); + let parsed_attrs = ClapAttr::parse_all(&variant.attrs)?; + res.infer_kind(&parsed_attrs)?; + res.push_attrs(&parsed_attrs)?; if matches!(&*res.kind, Kind::Value) { res.push_doc_comment(&variant.attrs, "help", None); } - res + Ok(res) } pub fn from_args_field( field: &Field, struct_casing: Sp<CasingStyle>, env_casing: Sp<CasingStyle>, - ) -> Self { + ) -> Result<Self, syn::Error> { let name = field.ident.clone().unwrap(); let ident = field.ident.clone().unwrap(); let span = field.span(); @@ -211,9 +211,9 @@ impl Item { env_casing, kind, ); - let parsed_attrs = ClapAttr::parse_all(&field.attrs); - res.infer_kind(&parsed_attrs); - res.push_attrs(&parsed_attrs); + let parsed_attrs = ClapAttr::parse_all(&field.attrs)?; + res.infer_kind(&parsed_attrs)?; + res.push_attrs(&parsed_attrs)?; if matches!(&*res.kind, Kind::Arg(_)) { res.push_doc_comment(&field.attrs, "help", Some("long_help")); } @@ -244,7 +244,7 @@ impl Item { | Kind::ExternalSubcommand => {} } - res + Ok(res) } fn new( @@ -255,9 +255,9 @@ impl Item { env_casing: Sp<CasingStyle>, kind: Sp<Kind>, ) -> Self { + let group_id = Name::Derived(ident); Self { name, - ident, ty, casing, env_casing, @@ -273,11 +273,17 @@ impl Item { is_enum: false, is_positional: true, skip_group: false, + group_id, + group_methods: vec![], kind, } } fn push_method(&mut self, kind: AttrKind, name: Ident, arg: impl ToTokens) { + self.push_method_(kind, name, arg.to_token_stream()); + } + + fn push_method_(&mut self, kind: AttrKind, name: Ident, arg: TokenStream) { if name == "id" { match kind { AttrKind::Command | AttrKind::Value => { @@ -291,10 +297,15 @@ impl Item { kind.as_str() ), }); + self.name = Name::Assigned(arg); + } + AttrKind::Group => { + self.group_id = Name::Assigned(arg); + } + AttrKind::Arg | AttrKind::Clap | AttrKind::StructOpt => { + self.name = Name::Assigned(arg); } - AttrKind::Group | AttrKind::Arg | AttrKind::Clap | AttrKind::StructOpt => {} } - self.name = Name::Assigned(quote!(#arg)); } else if name == "name" { match kind { AttrKind::Arg => { @@ -309,27 +320,29 @@ impl Item { kind.as_str() ), }); + self.name = Name::Assigned(arg); + } + AttrKind::Group => self.group_methods.push(Method::new(name, arg)), + AttrKind::Command | AttrKind::Value | AttrKind::Clap | AttrKind::StructOpt => { + self.name = Name::Assigned(arg); } - AttrKind::Group - | AttrKind::Command - | AttrKind::Value - | AttrKind::Clap - | AttrKind::StructOpt => {} } - self.name = Name::Assigned(quote!(#arg)); } else if name == "value_parser" { - self.value_parser = Some(ValueParser::Explicit(Method::new(name, quote!(#arg)))); + self.value_parser = Some(ValueParser::Explicit(Method::new(name, arg))); } else if name == "action" { - self.action = Some(Action::Explicit(Method::new(name, quote!(#arg)))); + self.action = Some(Action::Explicit(Method::new(name, arg))); } else { if name == "short" || name == "long" { self.is_positional = false; } - self.methods.push(Method::new(name, quote!(#arg))); + match kind { + AttrKind::Group => self.group_methods.push(Method::new(name, arg)), + _ => self.methods.push(Method::new(name, arg)), + }; } } - fn infer_kind(&mut self, attrs: &[ClapAttr]) { + fn infer_kind(&mut self, attrs: &[ClapAttr]) -> Result<(), syn::Error> { for attr in attrs { if let Some(AttrValue::Call(_)) = &attr.value { continue; @@ -339,7 +352,7 @@ impl Item { let kind = match &attr.magic { Some(MagicAttrName::FromGlobal) => { if attr.value.is_some() { - let expr = attr.value_or_abort(); + let expr = attr.value_or_abort()?; abort!(expr, "attribute `{}` does not accept a value", attr.name); } let ty = self @@ -352,7 +365,7 @@ impl Item { } Some(MagicAttrName::Subcommand) if attr.value.is_none() => { if attr.value.is_some() { - let expr = attr.value_or_abort(); + let expr = attr.value_or_abort()?; abort!(expr, "attribute `{}` does not accept a value", attr.name); } let ty = self @@ -365,7 +378,7 @@ impl Item { } Some(MagicAttrName::ExternalSubcommand) if attr.value.is_none() => { if attr.value.is_some() { - let expr = attr.value_or_abort(); + let expr = attr.value_or_abort()?; abort!(expr, "attribute `{}` does not accept a value", attr.name); } let kind = Sp::new(Kind::ExternalSubcommand, attr.name.clone().span()); @@ -373,7 +386,7 @@ impl Item { } Some(MagicAttrName::Flatten) if attr.value.is_none() => { if attr.value.is_some() { - let expr = attr.value_or_abort(); + let expr = attr.value_or_abort()?; abort!(expr, "attribute `{}` does not accept a value", attr.name); } let ty = self @@ -396,12 +409,14 @@ impl Item { }; if let Some(kind) = kind { - self.set_kind(kind); + self.set_kind(kind)?; } } + + Ok(()) } - fn push_attrs(&mut self, attrs: &[ClapAttr]) { + fn push_attrs(&mut self, attrs: &[ClapAttr]) -> Result<(), syn::Error> { for attr in attrs { let actual_attr_kind = *attr.kind.get(); let expected_attr_kind = self.kind.attr_kind(); @@ -437,7 +452,7 @@ impl Item { match &attr.magic { Some(MagicAttrName::Short) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Arg])?; self.push_method( *attr.kind.get(), @@ -447,13 +462,13 @@ impl Item { } Some(MagicAttrName::Long) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Arg])?; self.push_method(*attr.kind.get(), attr.name.clone(), self.name.clone().translate(*self.casing)); } Some(MagicAttrName::ValueParser) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Arg])?; self.deprecations.push(Deprecation { span: attr.name.span(), @@ -465,7 +480,7 @@ impl Item { } Some(MagicAttrName::Action) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Arg])?; self.deprecations.push(Deprecation { span: attr.name.span(), @@ -477,7 +492,7 @@ impl Item { } Some(MagicAttrName::Env) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Arg])?; self.push_method( *attr.kind.get(), @@ -487,7 +502,7 @@ impl Item { } Some(MagicAttrName::ValueEnum) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Arg])?; self.is_enum = true } @@ -497,45 +512,45 @@ impl Item { } Some(MagicAttrName::About) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Command]); + assert_attr_kind(attr, &[AttrKind::Command])?; if let Some(method) = - Method::from_env(attr.name.clone(), "CARGO_PKG_DESCRIPTION") + Method::from_env(attr.name.clone(), "CARGO_PKG_DESCRIPTION")? { self.methods.push(method); } } Some(MagicAttrName::LongAbout) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Command]); + assert_attr_kind(attr, &[AttrKind::Command])?; self.force_long_help = true; } Some(MagicAttrName::LongHelp) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Arg])?; self.force_long_help = true; } Some(MagicAttrName::Author) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Command]); + assert_attr_kind(attr, &[AttrKind::Command])?; - if let Some(method) = Method::from_env(attr.name.clone(), "CARGO_PKG_AUTHORS") { + if let Some(method) = Method::from_env(attr.name.clone(), "CARGO_PKG_AUTHORS")? { self.methods.push(method); } } Some(MagicAttrName::Version) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Command]); + assert_attr_kind(attr, &[AttrKind::Command])?; - if let Some(method) = Method::from_env(attr.name.clone(), "CARGO_PKG_VERSION") { + if let Some(method) = Method::from_env(attr.name.clone(), "CARGO_PKG_VERSION")? { self.methods.push(method); } } Some(MagicAttrName::DefaultValueT) => { - assert_attr_kind(attr, &[AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Arg])?; let ty = if let Some(ty) = self.ty.as_ref() { ty @@ -543,7 +558,7 @@ impl Item { abort!( attr.name.clone(), "#[arg(default_value_t)] (without an argument) can be used \ - only on field level"; + only on field level\n\n= note: {note}\n\n", note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") @@ -560,7 +575,7 @@ impl Item { .any(|a| a.magic == Some(MagicAttrName::ValueEnum)) { quote_spanned!(attr.name.clone().span()=> { - static DEFAULT_VALUE: clap::__macro_refs::once_cell::sync::Lazy<String> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_VALUE: clap::__derive_refs::once_cell::sync::Lazy<String> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { let val: #ty = #val; clap::ValueEnum::to_possible_value(&val).unwrap().get_name().to_owned() }); @@ -569,7 +584,7 @@ impl Item { }) } else { quote_spanned!(attr.name.clone().span()=> { - static DEFAULT_VALUE: clap::__macro_refs::once_cell::sync::Lazy<String> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_VALUE: clap::__derive_refs::once_cell::sync::Lazy<String> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { let val: #ty = #val; ::std::string::ToString::to_string(&val) }); @@ -583,7 +598,7 @@ impl Item { } Some(MagicAttrName::DefaultValuesT) => { - assert_attr_kind(attr, &[AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Arg])?; let ty = if let Some(ty) = self.ty.as_ref() { ty @@ -591,18 +606,18 @@ impl Item { abort!( attr.name.clone(), "#[arg(default_values_t)] (without an argument) can be used \ - only on field level"; + only on field level\n\n= note: {note}\n\n", note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") }; - let expr = attr.value_or_abort(); + let expr = attr.value_or_abort()?; let container_type = Ty::from_syn_ty(ty); if *container_type != Ty::Vec { abort!( attr.name.clone(), - "#[arg(default_values_t)] can be used only on Vec types"; + "#[arg(default_values_t)] can be used only on Vec types\n\n= note: {note}\n\n", note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") @@ -628,11 +643,11 @@ impl Item { }) } - static DEFAULT_STRINGS: clap::__macro_refs::once_cell::sync::Lazy<Vec<::std::string::String>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_STRINGS: clap::__derive_refs::once_cell::sync::Lazy<Vec<::std::string::String>> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { iter_to_vals(#expr).collect() }); - static DEFAULT_VALUES: clap::__macro_refs::once_cell::sync::Lazy<Vec<&str>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_VALUES: clap::__derive_refs::once_cell::sync::Lazy<Vec<&str>> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { DEFAULT_STRINGS.iter().map(::std::string::String::as_str).collect() }); DEFAULT_VALUES.iter().copied() @@ -648,11 +663,11 @@ impl Item { iterable.into_iter().map(|val| val.borrow().to_string()) } - static DEFAULT_STRINGS: clap::__macro_refs::once_cell::sync::Lazy<Vec<::std::string::String>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_STRINGS: clap::__derive_refs::once_cell::sync::Lazy<Vec<::std::string::String>> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { iter_to_vals(#expr).collect() }); - static DEFAULT_VALUES: clap::__macro_refs::once_cell::sync::Lazy<Vec<&str>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_VALUES: clap::__derive_refs::once_cell::sync::Lazy<Vec<&str>> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { DEFAULT_STRINGS.iter().map(::std::string::String::as_str).collect() }); DEFAULT_VALUES.iter().copied() @@ -667,7 +682,7 @@ impl Item { } Some(MagicAttrName::DefaultValueOsT) => { - assert_attr_kind(attr, &[AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Arg])?; let ty = if let Some(ty) = self.ty.as_ref() { ty @@ -675,7 +690,7 @@ impl Item { abort!( attr.name.clone(), "#[arg(default_value_os_t)] (without an argument) can be used \ - only on field level"; + only on field level\n\n= note: {note}\n\n", note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") @@ -692,7 +707,7 @@ impl Item { .any(|a| a.magic == Some(MagicAttrName::ValueEnum)) { quote_spanned!(attr.name.clone().span()=> { - static DEFAULT_VALUE: clap::__macro_refs::once_cell::sync::Lazy<::std::ffi::OsString> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_VALUE: clap::__derive_refs::once_cell::sync::Lazy<::std::ffi::OsString> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { let val: #ty = #val; clap::ValueEnum::to_possible_value(&val).unwrap().get_name().to_owned() }); @@ -701,7 +716,7 @@ impl Item { }) } else { quote_spanned!(attr.name.clone().span()=> { - static DEFAULT_VALUE: clap::__macro_refs::once_cell::sync::Lazy<::std::ffi::OsString> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_VALUE: clap::__derive_refs::once_cell::sync::Lazy<::std::ffi::OsString> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { let val: #ty = #val; ::std::ffi::OsString::from(val) }); @@ -715,7 +730,7 @@ impl Item { } Some(MagicAttrName::DefaultValuesOsT) => { - assert_attr_kind(attr, &[AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Arg])?; let ty = if let Some(ty) = self.ty.as_ref() { ty @@ -723,18 +738,18 @@ impl Item { abort!( attr.name.clone(), "#[arg(default_values_os_t)] (without an argument) can be used \ - only on field level"; + only on field level\n\n= note: {note}\n\n", note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") }; - let expr = attr.value_or_abort(); + let expr = attr.value_or_abort()?; let container_type = Ty::from_syn_ty(ty); if *container_type != Ty::Vec { abort!( attr.name.clone(), - "#[arg(default_values_os_t)] can be used only on Vec types"; + "#[arg(default_values_os_t)] can be used only on Vec types\n\n= note: {note}\n\n", note = "see \ https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") @@ -760,11 +775,11 @@ impl Item { }) } - static DEFAULT_OS_STRINGS: clap::__macro_refs::once_cell::sync::Lazy<Vec<::std::ffi::OsString>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_OS_STRINGS: clap::__derive_refs::once_cell::sync::Lazy<Vec<::std::ffi::OsString>> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { iter_to_vals(#expr).collect() }); - static DEFAULT_VALUES: clap::__macro_refs::once_cell::sync::Lazy<Vec<&::std::ffi::OsStr>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_VALUES: clap::__derive_refs::once_cell::sync::Lazy<Vec<&::std::ffi::OsStr>> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { DEFAULT_OS_STRINGS.iter().map(::std::ffi::OsString::as_os_str).collect() }); DEFAULT_VALUES.iter().copied() @@ -780,11 +795,11 @@ impl Item { iterable.into_iter().map(|val| val.borrow().into()) } - static DEFAULT_OS_STRINGS: clap::__macro_refs::once_cell::sync::Lazy<Vec<::std::ffi::OsString>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_OS_STRINGS: clap::__derive_refs::once_cell::sync::Lazy<Vec<::std::ffi::OsString>> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { iter_to_vals(#expr).collect() }); - static DEFAULT_VALUES: clap::__macro_refs::once_cell::sync::Lazy<Vec<&::std::ffi::OsStr>> = clap::__macro_refs::once_cell::sync::Lazy::new(|| { + static DEFAULT_VALUES: clap::__derive_refs::once_cell::sync::Lazy<Vec<&::std::ffi::OsStr>> = clap::__derive_refs::once_cell::sync::Lazy::new(|| { DEFAULT_OS_STRINGS.iter().map(::std::ffi::OsString::as_os_str).collect() }); DEFAULT_VALUES.iter().copied() @@ -799,29 +814,29 @@ impl Item { } Some(MagicAttrName::NextDisplayOrder) => { - assert_attr_kind(attr, &[AttrKind::Command]); + assert_attr_kind(attr, &[AttrKind::Command])?; - let expr = attr.value_or_abort(); + let expr = attr.value_or_abort()?; self.next_display_order = Some(Method::new(attr.name.clone(), quote!(#expr))); } Some(MagicAttrName::NextHelpHeading) => { - assert_attr_kind(attr, &[AttrKind::Command]); + assert_attr_kind(attr, &[AttrKind::Command])?; - let expr = attr.value_or_abort(); + let expr = attr.value_or_abort()?; self.next_help_heading = Some(Method::new(attr.name.clone(), quote!(#expr))); } Some(MagicAttrName::RenameAll) => { - let lit = attr.lit_str_or_abort(); - self.casing = CasingStyle::from_lit(lit); + let lit = attr.lit_str_or_abort()?; + self.casing = CasingStyle::from_lit(lit)?; } Some(MagicAttrName::RenameAllEnv) => { - assert_attr_kind(attr, &[AttrKind::Command, AttrKind::Arg]); + assert_attr_kind(attr, &[AttrKind::Command, AttrKind::Arg])?; - let lit = attr.lit_str_or_abort(); - self.env_casing = CasingStyle::from_lit(lit); + let lit = attr.lit_str_or_abort()?; + self.env_casing = CasingStyle::from_lit(lit)?; } Some(MagicAttrName::Skip) if actual_attr_kind == AttrKind::Group => { @@ -839,20 +854,20 @@ impl Item { | Some(MagicAttrName::Author) | Some(MagicAttrName::Version) => { - let expr = attr.value_or_abort(); + let expr = attr.value_or_abort()?; self.push_method(*attr.kind.get(), attr.name.clone(), expr); } // Magic only for the default, otherwise just forward to the builder Some(MagicAttrName::ValueParser) | Some(MagicAttrName::Action) => { - let expr = attr.value_or_abort(); + let expr = attr.value_or_abort()?; self.push_method(*attr.kind.get(), attr.name.clone(), expr); } // Directives that never receive a value Some(MagicAttrName::ValueEnum) | Some(MagicAttrName::VerbatimDocComment) => { - let expr = attr.value_or_abort(); + let expr = attr.value_or_abort()?; abort!(expr, "attribute `{}` does not accept a value", attr.name); } @@ -883,6 +898,8 @@ impl Item { ); } } + + Ok(()) } fn push_doc_comment(&mut self, attrs: &[Attribute], short_name: &str, long_name: Option<&str>) { @@ -912,7 +929,7 @@ impl Item { } } - fn set_kind(&mut self, kind: Sp<Kind>) { + fn set_kind(&mut self, kind: Sp<Kind>) -> Result<(), syn::Error> { match (self.kind.get(), kind.get()) { (Kind::Arg(_), Kind::FromGlobal(_)) | (Kind::Arg(_), Kind::Subcommand(_)) @@ -932,6 +949,7 @@ impl Item { abort!(kind.span(), "`{}` cannot be used with `{}`", new, old); } } + Ok(()) } pub fn find_default_method(&self) -> Option<&Method> { @@ -964,6 +982,15 @@ impl Item { quote!( #(#doc_comment)* #(#methods)* ) } + pub fn group_id(&self) -> TokenStream { + self.group_id.clone().raw() + } + + pub fn group_methods(&self) -> TokenStream { + let group_methods = &self.group_methods; + quote!( #(#group_methods)* ) + } + pub fn deprecations(&self) -> proc_macro2::TokenStream { let deprecations = &self.deprecations; quote!( #(#deprecations)* ) @@ -979,10 +1006,6 @@ impl Item { quote!( #(#next_help_heading)* ) } - pub fn ident(&self) -> &Ident { - &self.ident - } - pub fn id(&self) -> TokenStream { self.name.clone().raw() } @@ -1211,19 +1234,21 @@ impl Method { Method { name, args } } - fn from_env(ident: Ident, env_var: &str) -> Option<Self> { + fn from_env(ident: Ident, env_var: &str) -> Result<Option<Self>, syn::Error> { let mut lit = match env::var(env_var) { Ok(val) => { if val.is_empty() { - return None; + return Ok(None); } LitStr::new(&val, ident.span()) } Err(_) => { - abort!(ident, - "cannot derive `{}` from Cargo.toml", ident; - note = "`{}` environment variable is not set", env_var; - help = "use `{} = \"...\"` to set {} manually", ident, ident; + abort!( + ident, + "cannot derive `{}` from Cargo.toml\n\n= note: {note}\n\n= help: {help}\n\n", + ident, + note = format_args!("`{}` environment variable is not set", env_var), + help = format_args!("use `{} = \"...\"` to set {} manually", ident, ident) ); } }; @@ -1233,7 +1258,7 @@ impl Method { lit = LitStr::new(&edited, lit.span()); } - Some(Method::new(ident, quote!(#lit))) + Ok(Some(Method::new(ident, quote!(#lit)))) } pub(crate) fn args(&self) -> &TokenStream { @@ -1299,7 +1324,7 @@ impl ToTokens for Deprecation { } } -fn assert_attr_kind(attr: &ClapAttr, possible_kind: &[AttrKind]) { +fn assert_attr_kind(attr: &ClapAttr, possible_kind: &[AttrKind]) -> Result<(), syn::Error> { if *attr.kind.get() == AttrKind::Clap || *attr.kind.get() == AttrKind::StructOpt { // deprecated } else if !possible_kind.contains(attr.kind.get()) { @@ -1315,6 +1340,7 @@ fn assert_attr_kind(attr: &ClapAttr, possible_kind: &[AttrKind]) { options.join(", ") ); } + Ok(()) } /// replace all `:` with `, ` when not inside the `<>` @@ -1364,13 +1390,13 @@ pub enum CasingStyle { } impl CasingStyle { - fn from_lit(name: &LitStr) -> Sp<Self> { + fn from_lit(name: &LitStr) -> Result<Sp<Self>, syn::Error> { use self::CasingStyle::*; let normalized = name.value().to_upper_camel_case().to_lowercase(); let cs = |kind| Sp::new(kind, name.span()); - match normalized.as_ref() { + let s = match normalized.as_ref() { "camel" | "camelcase" => cs(Camel), "kebab" | "kebabcase" => cs(Kebab), "pascal" | "pascalcase" => cs(Pascal), @@ -1380,7 +1406,8 @@ impl CasingStyle { "upper" | "uppercase" => cs(Upper), "verbatim" | "verbatimcase" => cs(Verbatim), s => abort!(name, "unsupported casing: `{}`", s), - } + }; + Ok(s) } } diff --git a/vendor/clap_derive/src/lib.rs b/vendor/clap_derive/src/lib.rs index 84f2f0ded..d3cae9b65 100644 --- a/vendor/clap_derive/src/lib.rs +++ b/vendor/clap_derive/src/lib.rs @@ -19,8 +19,11 @@ extern crate proc_macro; use proc_macro::TokenStream; -use proc_macro_error::proc_macro_error; use syn::{parse_macro_input, DeriveInput}; +use syn::{Data, DataStruct, Fields}; + +#[macro_use] +mod macros; mod attr; mod derives; @@ -30,10 +33,14 @@ mod utils; /// Generates the `ValueEnum` impl. #[proc_macro_derive(ValueEnum, attributes(clap, value))] -#[proc_macro_error] pub fn value_enum(input: TokenStream) -> TokenStream { let input: DeriveInput = parse_macro_input!(input); - derives::derive_value_enum(&input).into() + derives::derive_value_enum(&input) + .unwrap_or_else(|err| { + let dummy = dummies::value_enum(&input.ident); + to_compile_error(err, dummy) + }) + .into() } /// Generates the `Parser` implementation. @@ -43,24 +50,67 @@ pub fn value_enum(input: TokenStream) -> TokenStream { /// implementing a conversion code to instantiate an instance of the user /// context struct. #[proc_macro_derive(Parser, attributes(clap, structopt, command, arg, group))] -#[proc_macro_error] pub fn parser(input: TokenStream) -> TokenStream { let input: DeriveInput = parse_macro_input!(input); - derives::derive_parser(&input).into() + derives::derive_parser(&input) + .unwrap_or_else(|err| { + let specific_dummy = match input.data { + Data::Struct(DataStruct { + fields: Fields::Named(ref _fields), + .. + }) => Some(dummies::args(&input.ident)), + Data::Struct(DataStruct { + fields: Fields::Unit, + .. + }) => Some(dummies::args(&input.ident)), + Data::Enum(_) => Some(dummies::subcommand(&input.ident)), + _ => None, + }; + let dummy = specific_dummy + .map(|specific_dummy| { + let parser_dummy = dummies::parser(&input.ident); + quote::quote! { + #parser_dummy + #specific_dummy + } + }) + .unwrap_or_else(|| quote::quote!()); + to_compile_error(err, dummy) + }) + .into() } /// Generates the `Subcommand` impl. #[proc_macro_derive(Subcommand, attributes(clap, command, arg, group))] -#[proc_macro_error] pub fn subcommand(input: TokenStream) -> TokenStream { let input: DeriveInput = parse_macro_input!(input); - derives::derive_subcommand(&input).into() + derives::derive_subcommand(&input) + .unwrap_or_else(|err| { + let dummy = dummies::subcommand(&input.ident); + to_compile_error(err, dummy) + }) + .into() } /// Generates the `Args` impl. #[proc_macro_derive(Args, attributes(clap, command, arg, group))] -#[proc_macro_error] pub fn args(input: TokenStream) -> TokenStream { let input: DeriveInput = parse_macro_input!(input); - derives::derive_args(&input).into() + derives::derive_args(&input) + .unwrap_or_else(|err| { + let dummy = dummies::args(&input.ident); + to_compile_error(err, dummy) + }) + .into() +} + +fn to_compile_error( + error: syn::Error, + dummy: proc_macro2::TokenStream, +) -> proc_macro2::TokenStream { + let compile_errors = error.to_compile_error(); + quote::quote!( + #dummy + #compile_errors + ) } diff --git a/vendor/clap_derive/src/macros.rs b/vendor/clap_derive/src/macros.rs new file mode 100644 index 000000000..282048bc1 --- /dev/null +++ b/vendor/clap_derive/src/macros.rs @@ -0,0 +1,21 @@ +macro_rules! format_err { + ($obj:expr, $($format:tt)+) => {{ + #[allow(unused_imports)] + use $crate::utils::error::*; + let msg = format!($($format)+); + $obj.EXPECTED_Span_OR_ToTokens(msg) + }}; +} + +macro_rules! abort { + ($obj:expr, $($format:tt)+) => {{ + return Err(format_err!($obj, $($format)+)); + }}; +} + +macro_rules! abort_call_site { + ($($format:tt)+) => {{ + let span = proc_macro2::Span::call_site(); + abort!(span, $($format)+) + }}; +} diff --git a/vendor/clap_derive/src/utils/doc_comments.rs b/vendor/clap_derive/src/utils/doc_comments.rs index 5183b6b25..63c6ad1ef 100644 --- a/vendor/clap_derive/src/utils/doc_comments.rs +++ b/vendor/clap_derive/src/utils/doc_comments.rs @@ -6,24 +6,26 @@ use std::iter; pub fn extract_doc_comment(attrs: &[syn::Attribute]) -> Vec<String> { - use syn::Lit::*; - use syn::Meta::*; - use syn::MetaNameValue; - // multiline comments (`/** ... */`) may have LFs (`\n`) in them, // we need to split so we could handle the lines correctly // // we also need to remove leading and trailing blank lines let mut lines: Vec<_> = attrs .iter() - .filter(|attr| attr.path.is_ident("doc")) + .filter(|attr| attr.path().is_ident("doc")) .filter_map(|attr| { - if let Ok(NameValue(MetaNameValue { lit: Str(s), .. })) = attr.parse_meta() { - Some(s.value()) - } else { - // non #[doc = "..."] attributes are not our concern - // we leave them for rustc to handle - None + // non #[doc = "..."] attributes are not our concern + // we leave them for rustc to handle + match &attr.meta { + syn::Meta::NameValue(syn::MetaNameValue { + value: + syn::Expr::Lit(syn::ExprLit { + lit: syn::Lit::Str(s), + .. + }), + .. + }) => Some(s.value()), + _ => None, } }) .skip_while(|s| is_blank(s)) diff --git a/vendor/clap_derive/src/utils/error.rs b/vendor/clap_derive/src/utils/error.rs new file mode 100644 index 000000000..276e34949 --- /dev/null +++ b/vendor/clap_derive/src/utils/error.rs @@ -0,0 +1,22 @@ +pub trait SpanError { + #[allow(non_snake_case)] + fn EXPECTED_Span_OR_ToTokens<D: std::fmt::Display>(&self, msg: D) -> syn::Error; +} + +pub trait ToTokensError { + #[allow(non_snake_case)] + fn EXPECTED_Span_OR_ToTokens<D: std::fmt::Display>(&self, msg: D) -> syn::Error; +} + +impl<T: quote::ToTokens> ToTokensError for T { + fn EXPECTED_Span_OR_ToTokens<D: std::fmt::Display>(&self, msg: D) -> syn::Error { + // Curb monomorphization from generating too many identical `new_spanned`. + syn::Error::new_spanned(self.to_token_stream(), msg) + } +} + +impl SpanError for proc_macro2::Span { + fn EXPECTED_Span_OR_ToTokens<D: std::fmt::Display>(&self, msg: D) -> syn::Error { + syn::Error::new(*self, msg) + } +} diff --git a/vendor/clap_derive/src/utils/mod.rs b/vendor/clap_derive/src/utils/mod.rs index 9f8b6f380..13e6e7106 100644 --- a/vendor/clap_derive/src/utils/mod.rs +++ b/vendor/clap_derive/src/utils/mod.rs @@ -1,3 +1,5 @@ +pub mod error; + mod doc_comments; mod spanned; mod ty; |