diff options
Diffstat (limited to 'vendor/clap_derive/src')
-rw-r--r-- | vendor/clap_derive/src/attr.rs | 215 | ||||
-rw-r--r-- | vendor/clap_derive/src/derives/args.rs | 765 | ||||
-rw-r--r-- | vendor/clap_derive/src/derives/into_app.rs | 117 | ||||
-rw-r--r-- | vendor/clap_derive/src/derives/mod.rs | 23 | ||||
-rw-r--r-- | vendor/clap_derive/src/derives/parser.rs | 119 | ||||
-rw-r--r-- | vendor/clap_derive/src/derives/subcommand.rs | 674 | ||||
-rw-r--r-- | vendor/clap_derive/src/derives/value_enum.rs | 130 | ||||
-rw-r--r-- | vendor/clap_derive/src/dummies.rs | 99 | ||||
-rw-r--r-- | vendor/clap_derive/src/item.rs | 1468 | ||||
-rw-r--r-- | vendor/clap_derive/src/lib.rs | 116 | ||||
-rw-r--r-- | vendor/clap_derive/src/macros.rs | 21 | ||||
-rw-r--r-- | vendor/clap_derive/src/utils/doc_comments.rs | 126 | ||||
-rw-r--r-- | vendor/clap_derive/src/utils/error.rs | 22 | ||||
-rw-r--r-- | vendor/clap_derive/src/utils/mod.rs | 13 | ||||
-rw-r--r-- | vendor/clap_derive/src/utils/spanned.rs | 89 | ||||
-rw-r--r-- | vendor/clap_derive/src/utils/ty.rs | 165 |
16 files changed, 0 insertions, 4162 deletions
diff --git a/vendor/clap_derive/src/attr.rs b/vendor/clap_derive/src/attr.rs deleted file mode 100644 index 3bc9ac0..0000000 --- a/vendor/clap_derive/src/attr.rs +++ /dev/null @@ -1,215 +0,0 @@ -use std::iter::FromIterator; - -use proc_macro2::TokenStream; -use quote::quote; -use quote::ToTokens; -use syn::spanned::Spanned; -use syn::{ - parenthesized, - parse::{Parse, ParseStream}, - punctuated::Punctuated, - Attribute, Expr, Ident, LitStr, Token, -}; - -use crate::utils::Sp; - -#[derive(Clone)] -pub struct ClapAttr { - pub kind: Sp<AttrKind>, - pub name: Ident, - pub magic: Option<MagicAttrName>, - pub value: Option<AttrValue>, -} - -impl ClapAttr { - 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) -> Result<&AttrValue, syn::Error> { - self.value - .as_ref() - .ok_or_else(|| format_err!(self.name, "attribute `{}` requires a value", self.name)) - } - - pub fn lit_str_or_abort(&self) -> Result<&LitStr, syn::Error> { - let value = self.value_or_abort()?; - match value { - AttrValue::LitStr(tokens) => Ok(tokens), - AttrValue::Expr(_) | AttrValue::Call(_) => { - abort!( - self.name, - "attribute `{}` can only accept string literals", - self.name - ) - } - } - } -} - -impl Parse for ClapAttr { - fn parse(input: ParseStream) -> syn::Result<Self> { - let name: Ident = input.parse()?; - let name_str = name.to_string(); - - let magic = match name_str.as_str() { - "rename_all" => Some(MagicAttrName::RenameAll), - "rename_all_env" => Some(MagicAttrName::RenameAllEnv), - "skip" => Some(MagicAttrName::Skip), - "next_display_order" => Some(MagicAttrName::NextDisplayOrder), - "next_help_heading" => Some(MagicAttrName::NextHelpHeading), - "default_value_t" => Some(MagicAttrName::DefaultValueT), - "default_values_t" => Some(MagicAttrName::DefaultValuesT), - "default_value_os_t" => Some(MagicAttrName::DefaultValueOsT), - "default_values_os_t" => Some(MagicAttrName::DefaultValuesOsT), - "long" => Some(MagicAttrName::Long), - "short" => Some(MagicAttrName::Short), - "value_parser" => Some(MagicAttrName::ValueParser), - "action" => Some(MagicAttrName::Action), - "env" => Some(MagicAttrName::Env), - "flatten" => Some(MagicAttrName::Flatten), - "value_enum" => Some(MagicAttrName::ValueEnum), - "from_global" => Some(MagicAttrName::FromGlobal), - "subcommand" => Some(MagicAttrName::Subcommand), - "external_subcommand" => Some(MagicAttrName::ExternalSubcommand), - "verbatim_doc_comment" => Some(MagicAttrName::VerbatimDocComment), - "about" => Some(MagicAttrName::About), - "long_about" => Some(MagicAttrName::LongAbout), - "long_help" => Some(MagicAttrName::LongHelp), - "author" => Some(MagicAttrName::Author), - "version" => Some(MagicAttrName::Version), - _ => None, - }; - - let value = if input.peek(Token![=]) { - // `name = value` attributes. - let assign_token = input.parse::<Token![=]>()?; // skip '=' - if input.peek(LitStr) { - let lit: LitStr = input.parse()?; - Some(AttrValue::LitStr(lit)) - } else { - match input.parse::<Expr>() { - Ok(expr) => Some(AttrValue::Expr(expr)), - - Err(_) => abort! { - assign_token, - "expected `string literal` or `expression` after `=`" - }, - } - } - } else if input.peek(syn::token::Paren) { - // `name(...)` attributes. - let nested; - parenthesized!(nested in input); - - let method_args: Punctuated<_, _> = nested.parse_terminated(Expr::parse, Token![,])?; - Some(AttrValue::Call(Vec::from_iter(method_args))) - } else { - None - }; - - Ok(Self { - kind: Sp::new(AttrKind::Clap, name.span()), - name, - magic, - value, - }) - } -} - -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum MagicAttrName { - Short, - Long, - ValueParser, - Action, - Env, - Flatten, - ValueEnum, - FromGlobal, - Subcommand, - VerbatimDocComment, - ExternalSubcommand, - About, - LongAbout, - LongHelp, - Author, - Version, - RenameAllEnv, - RenameAll, - Skip, - DefaultValueT, - DefaultValuesT, - DefaultValueOsT, - DefaultValuesOsT, - NextDisplayOrder, - NextHelpHeading, -} - -#[derive(Clone)] -#[allow(clippy::large_enum_variant)] -pub enum AttrValue { - LitStr(LitStr), - Expr(Expr), - Call(Vec<Expr>), -} - -impl ToTokens for AttrValue { - fn to_tokens(&self, tokens: &mut TokenStream) { - match self { - Self::LitStr(t) => t.to_tokens(tokens), - Self::Expr(t) => t.to_tokens(tokens), - Self::Call(t) => { - let t = quote!(#(#t),*); - t.to_tokens(tokens) - } - } - } -} - -#[derive(Copy, Clone, PartialEq, Eq)] -pub enum AttrKind { - Clap, - StructOpt, - Command, - Group, - Arg, - Value, -} - -impl AttrKind { - pub fn as_str(&self) -> &'static str { - match self { - Self::Clap => "clap", - Self::StructOpt => "structopt", - Self::Command => "command", - Self::Group => "group", - Self::Arg => "arg", - Self::Value => "value", - } - } -} diff --git a/vendor/clap_derive/src/derives/args.rs b/vendor/clap_derive/src/derives/args.rs deleted file mode 100644 index 279f6ca..0000000 --- a/vendor/clap_derive/src/derives/args.rs +++ /dev/null @@ -1,765 +0,0 @@ -// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>, -// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and -// Ana Hobden (@hoverbear) <operator@hoverbear.org> -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// This work was derived from Structopt (https://github.com/TeXitoi/structopt) -// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the -// MIT/Apache 2.0 license. - -use proc_macro2::{Ident, Span, TokenStream}; -use quote::{format_ident, quote, quote_spanned}; -use syn::{ - punctuated::Punctuated, spanned::Spanned, token::Comma, Data, DataStruct, DeriveInput, Field, - Fields, FieldsNamed, Generics, -}; - -use crate::item::{Item, Kind, Name}; -use crate::utils::{inner_type, sub_type, Sp, Ty}; - -pub fn derive_args(input: &DeriveInput) -> Result<TokenStream, syn::Error> { - let ident = &input.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 fields = collect_args_fields(&item, fields)?; - gen_for_struct(&item, ident, &input.generics, &fields) - } - Data::Struct(DataStruct { - fields: Fields::Unit, - .. - }) => { - 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())?; - Ok((field, item)) - }) - .collect::<Result<Vec<_>, syn::Error>>()?; - gen_for_struct(&item, ident, &input.generics, &fields) - } - _ => abort_call_site!("`#[derive(Args)]` only supports non-tuple structs"), - } -} - -pub fn gen_for_struct( - item: &Item, - item_name: &Ident, - generics: &Generics, - fields: &[(&Field, Item)], -) -> Result<TokenStream, syn::Error> { - 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(); - - 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 group_id = if item.skip_group() { - quote!(None) - } else { - let group_id = item.group_id(); - quote!(Some(clap::Id::from(#group_id))) - }; - - Ok(quote! { - #[allow( - dead_code, - unreachable_code, - unused_variables, - unused_braces, - unused_qualifications, - )] - #[allow( - clippy::style, - clippy::complexity, - clippy::pedantic, - clippy::restriction, - clippy::perf, - clippy::deprecated, - clippy::nursery, - clippy::cargo, - clippy::suspicious_else_formatting, - clippy::almost_swapped, - clippy::redundant_locals, - )] - #[automatically_derived] - 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 = #item_name #constructor; - ::std::result::Result::Ok(v) - } - - fn update_from_arg_matches(&mut self, __clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result<(), clap::Error> { - self.update_from_arg_matches_mut(&mut __clap_arg_matches.clone()) - } - - fn update_from_arg_matches_mut(&mut self, __clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result<(), clap::Error> { - #raw_deprecated - #updater - ::std::result::Result::Ok(()) - } - } - - #[allow( - dead_code, - unreachable_code, - unused_variables, - unused_braces, - unused_qualifications, - )] - #[allow( - clippy::style, - clippy::complexity, - clippy::pedantic, - clippy::restriction, - clippy::perf, - clippy::deprecated, - clippy::nursery, - clippy::cargo, - clippy::suspicious_else_formatting, - clippy::almost_swapped, - clippy::redundant_locals, - )] - #[automatically_derived] - 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: &[(&Field, Item)], - app_var: &Ident, - parent_item: &Item, - override_required: bool, -) -> Result<TokenStream, syn::Error> { - let mut subcommand_specified = false; - let mut args = Vec::new(); - for (field, item) in fields { - let kind = item.kind(); - let genned = 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 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 ); - 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 next_help_heading = item.next_help_heading(); - let next_display_order = item.next_display_order(); - if override_required { - Some(quote_spanned! { kind.span()=> - 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 #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 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()=> - .value_name(#value_name) - #value_parser - #action - } - } - - Ty::OptionOption => quote_spanned! { ty.span()=> - .value_name(#value_name) - .num_args(0..=1) - #value_parser - #action - }, - - Ty::OptionVec => { - 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()=> - .value_name(#value_name) - #value_parser - #action - } - } - } - - Ty::Vec => { - 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()=> - .value_name(#value_name) - #value_parser - #action - } - } - } - - Ty::VecVec | Ty::OptionVecVec => { - quote_spanned! { ty.span() => - .value_name(#value_name) - #value_parser - #action - } - } - - Ty::Other => { - 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()=> - .value_name(#value_name) - .required(#required && #action_value.takes_values()) - #value_parser - #action - } - } - }; - - 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({ - #deprecations - - #[allow(deprecated)] - let arg = clap::Arg::new(#id) - #implicit_methods; - - let arg = arg - #explicit_methods; - - let arg = arg - #override_methods; - - arg - }); - }) - } - }; - args.push(genned); - } - - 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.group_id(); - 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 - }}; - } - - let group_methods = parent_item.group_methods(); - - quote!( - .group( - clap::ArgGroup::new(#group_id) - .multiple(true) - #group_methods - .args(#literal_group_members) - ) - ) - }; - Ok(quote! {{ - #deprecations - let #app_var = #app_var - #initial_app_methods - #group_app_methods - ; - #( #args )* - #app_var #final_app_methods - }}) -} - -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"); - let genned = match &*kind { - Kind::Command(_) - | Kind::Value - | Kind::ExternalSubcommand => { - abort! { kind.span(), - "`{}` cannot be used with `arg`", - kind.name(), - } - } - Kind::Subcommand(ty) => { - let subcmd_type = match (**ty, sub_type(&field.ty)) { - (Ty::Option, Some(sub_type)) => sub_type, - _ => &field.ty, - }; - match **ty { - Ty::Option => { - quote_spanned! { kind.span()=> - #field_name: { - if #arg_matches.subcommand_name().map(<#subcmd_type as clap::Subcommand>::has_subcommand).unwrap_or(false) { - Some(<#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut(#arg_matches)?) - } else { - None - } - } - } - }, - 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(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 { - 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(item, ty, field_name, field, None)? - } - }; - Ok(genned) - }).collect::<Result<Vec<_>, syn::Error>>()?; - - Ok(quote! {{ - #( #fields ),* - }}) -} - -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(); - - let access = if use_self { - quote! { - #[allow(non_snake_case)] - let #field_name = &mut self.#field_name; - } - } else { - quote!() - }; - let arg_matches = format_ident!("__clap_arg_matches"); - - let genned = match &*kind { - Kind::Command(_) | Kind::Value | Kind::ExternalSubcommand => { - abort! { kind.span(), - "`{}` cannot be used with `arg`", - kind.name(), - } - } - Kind::Subcommand(ty) => { - let subcmd_type = match (**ty, sub_type(&field.ty)) { - (Ty::Option, Some(sub_type)) => sub_type, - _ => &field.ty, - }; - - let updater = quote_spanned! { ty.span()=> - <#subcmd_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(<#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut( - #arg_matches - )?); - } - }, - _ => quote_spanned! { kind.span()=> - #updater - }, - }; - - quote_spanned! { kind.span()=> - { - #access - #updater - } - } - } - - 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::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( - item: &Item, - ty: &Sp<Ty>, - field_name: &Ident, - field: &Field, - update: Option<&TokenStream>, -) -> Result<TokenStream, syn::Error> { - let span = ty.span(); - let convert_type = inner_type(&field.ty); - 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 - // allows us to refer to `arg_matches` within a `quote_spanned` block - 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) - } - } - - Ty::OptionOption => quote_spanned! { ty.span()=> - if #arg_matches.contains_id(#id) { - Some( - #arg_matches.#get_one(#id) - ) - } else { - None - } - }, - - Ty::OptionVec => quote_spanned! { ty.span()=> - if #arg_matches.contains_id(#id) { - Some(#arg_matches.#get_many(#id) - .map(|v| v.collect::<Vec<_>>()) - .unwrap_or_else(Vec::new)) - } else { - None - } - }, - - Ty::Vec => { - quote_spanned! { ty.span()=> - #arg_matches.#get_many(#id) - .map(|v| v.collect::<Vec<_>>()) - .unwrap_or_else(Vec::new) - } - } - - 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::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) - .ok_or_else(|| clap::Error::raw(clap::error::ErrorKind::MissingRequiredArgument, concat!("The following required argument was not provided: ", #id)))? - } - } - }; - - let genned = if let Some(access) = update { - quote_spanned! { field.span()=> - if #arg_matches.contains_id(#id) { - #access - *#field_name = #field_value - } - } - } else { - quote_spanned!(field.span()=> #field_name: #field_value ) - }; - Ok(genned) -} - -#[cfg(feature = "raw-deprecated")] -pub fn raw_deprecated() -> TokenStream { - quote! {} -} - -#[cfg(not(feature = "raw-deprecated"))] -pub fn raw_deprecated() -> TokenStream { - quote! { - #![allow(deprecated)] // Assuming any deprecation in here will be related to a deprecation in `Args` - - } -} - -pub fn collect_args_fields<'a>( - item: &'a Item, - fields: &'a FieldsNamed, -) -> Result<Vec<(&'a Field, Item)>, syn::Error> { - fields - .named - .iter() - .map(|field| { - let item = Item::from_args_field(field, item.casing(), item.env_casing())?; - Ok((field, item)) - }) - .collect() -} diff --git a/vendor/clap_derive/src/derives/into_app.rs b/vendor/clap_derive/src/derives/into_app.rs deleted file mode 100644 index 5abf4ea..0000000 --- a/vendor/clap_derive/src/derives/into_app.rs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>, -// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and -// Ana Hobden (@hoverbear) <operator@hoverbear.org> -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// This work was derived from Structopt (https://github.com/TeXitoi/structopt) -// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the -// MIT/Apache 2.0 license. - -use proc_macro2::{Span, TokenStream}; -use quote::quote; -use syn::{Generics, Ident}; - -use crate::item::Item; - -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(); - let app_var = Ident::new("__clap_app", Span::call_site()); - - let tokens = quote! { - #[allow( - dead_code, - unreachable_code, - unused_variables, - unused_braces, - unused_qualifications, - )] - #[allow( - clippy::style, - clippy::complexity, - clippy::pedantic, - clippy::restriction, - clippy::perf, - clippy::deprecated, - clippy::nursery, - clippy::cargo, - clippy::suspicious_else_formatting, - clippy::almost_swapped, - clippy::redundant_locals, - )] - #[automatically_derived] - 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 command_for_update<'b>() -> clap::Command { - let #app_var = clap::Command::new(#name); - <Self as clap::Args>::augment_args_for_update(#app_var) - } - } - }; - - Ok(tokens) -} - -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()); - - Ok(quote! { - #[allow( - dead_code, - unreachable_code, - unused_variables, - unused_braces, - unused_qualifications, - )] - #[allow( - clippy::style, - clippy::complexity, - clippy::pedantic, - clippy::restriction, - clippy::perf, - clippy::deprecated, - clippy::nursery, - clippy::cargo, - clippy::suspicious_else_formatting, - clippy::almost_swapped, - clippy::redundant_locals, - )] - #[automatically_derived] - impl #impl_generics clap::CommandFactory for #item_name #ty_generics #where_clause { - fn command<'b>() -> clap::Command { - let #app_var = clap::Command::new(#name) - .subcommand_required(true) - .arg_required_else_help(true); - <Self as clap::Subcommand>::augment_subcommands(#app_var) - } - - 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/mod.rs b/vendor/clap_derive/src/derives/mod.rs deleted file mode 100644 index 3deeb91..0000000 --- a/vendor/clap_derive/src/derives/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>, -// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and -// Ana Hobden (@hoverbear) <operator@hoverbear.org> -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// This work was derived from Structopt (https://github.com/TeXitoi/structopt) -// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the -// MIT/Apache 2.0 license. -mod args; -mod into_app; -mod parser; -mod subcommand; -mod value_enum; - -pub use self::parser::derive_parser; -pub use args::derive_args; -pub use subcommand::derive_subcommand; -pub use value_enum::derive_value_enum; diff --git a/vendor/clap_derive/src/derives/parser.rs b/vendor/clap_derive/src/derives/parser.rs deleted file mode 100644 index e511bda..0000000 --- a/vendor/clap_derive/src/derives/parser.rs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>, -// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and -// Ana Hobden (@hoverbear) <operator@hoverbear.org> -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// This work was derived from Structopt (https://github.com/TeXitoi/structopt) -// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the -// MIT/Apache 2.0 license. - -use proc_macro2::TokenStream; -use quote::quote; -use syn::Ident; -use syn::Variant; -use syn::{ - self, punctuated::Punctuated, token::Comma, Data, DataStruct, DeriveInput, Field, Fields, - Generics, -}; - -use crate::derives::args::collect_args_fields; -use crate::derives::{args, into_app, subcommand}; -use crate::item::Item; -use crate::item::Name; - -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(); - - match input.data { - Data::Struct(DataStruct { - fields: Fields::Named(ref fields), - .. - }) => { - let name = Name::Assigned(quote!(#pkg_name)); - let item = Item::from_args_struct(input, name)?; - let fields = collect_args_fields(&item, fields)?; - gen_for_struct(&item, ident, &input.generics, &fields) - } - Data::Struct(DataStruct { - fields: Fields::Unit, - .. - }) => { - 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())?; - Ok((field, item)) - }) - .collect::<Result<Vec<_>, syn::Error>>()?; - gen_for_struct(&item, ident, &input.generics, &fields) - } - Data::Enum(ref 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())?; - Ok((variant, item)) - }) - .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"), - } -} - -fn gen_for_struct( - item: &Item, - item_name: &Ident, - generics: &Generics, - fields: &[(&Field, Item)], -) -> 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)?; - - Ok(quote! { - #[automatically_derived] - #[allow( - unused_qualifications, - clippy::redundant_locals, - )] - impl #impl_generics clap::Parser for #item_name #ty_generics #where_clause {} - - #into_app - #args - }) -} - -fn gen_for_enum( - item: &Item, - item_name: &Ident, - generics: &Generics, - variants: &[(&Variant, Item)], -) -> 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)?; - - Ok(quote! { - #[automatically_derived] - 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 deleted file mode 100644 index da438d3..0000000 --- a/vendor/clap_derive/src/derives/subcommand.rs +++ /dev/null @@ -1,674 +0,0 @@ -// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>, -// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and -// Ana Hobden (@hoverbear) <operator@hoverbear.org> -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// This work was derived from Structopt (https://github.com/TeXitoi/structopt) -// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the -// MIT/Apache 2.0 license. - -use proc_macro2::{Ident, Span, TokenStream}; -use quote::{format_ident, quote, quote_spanned}; -use syn::{spanned::Spanned, Data, DeriveInput, FieldsUnnamed, Generics, Variant}; - -use crate::derives::args; -use crate::derives::args::collect_args_fields; -use crate::item::{Item, Kind, Name}; -use crate::utils::{is_simple_ty, subty_if_name}; - -pub fn derive_subcommand(input: &DeriveInput) -> Result<TokenStream, syn::Error> { - let ident = &input.ident; - - match input.data { - 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())?; - Ok((variant, item)) - }) - .collect::<Result<Vec<_>, syn::Error>>()?; - gen_for_enum(&item, ident, &input.generics, &variants) - } - _ => abort_call_site!("`#[derive(Subcommand)]` only supports enums"), - } -} - -pub fn gen_for_enum( - item: &Item, - item_name: &Ident, - generics: &Generics, - variants: &[(&Variant, Item)], -) -> Result<TokenStream, syn::Error> { - 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(); - - 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)?; - - Ok(quote! { - #[allow( - dead_code, - unreachable_code, - unused_variables, - unused_braces, - unused_qualifications, - )] - #[allow( - clippy::style, - clippy::complexity, - clippy::pedantic, - clippy::restriction, - clippy::perf, - clippy::deprecated, - clippy::nursery, - clippy::cargo, - clippy::suspicious_else_formatting, - clippy::almost_swapped, - clippy::redundant_locals, - )] - #[automatically_derived] - 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()) - } - - #from_arg_matches - - fn update_from_arg_matches(&mut self, __clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result<(), clap::Error> { - self.update_from_arg_matches_mut(&mut __clap_arg_matches.clone()) - } - #update_from_arg_matches - } - - #[allow( - dead_code, - unreachable_code, - unused_variables, - unused_braces, - unused_qualifications, - )] - #[allow( - clippy::style, - clippy::complexity, - clippy::pedantic, - clippy::restriction, - clippy::perf, - clippy::deprecated, - clippy::nursery, - clippy::cargo, - clippy::suspicious_else_formatting, - clippy::almost_swapped, - clippy::redundant_locals, - )] - #[automatically_derived] - impl #impl_generics clap::Subcommand for #item_name #ty_generics #where_clause { - fn augment_subcommands <'b>(__clap_app: clap::Command) -> clap::Command { - #augmentation - } - fn augment_subcommands_for_update <'b>(__clap_app: clap::Command) -> clap::Command { - #augmentation_update - } - fn has_subcommand(__clap_name: &str) -> bool { - #has_subcommand - } - } - }) -} - -fn gen_augment( - variants: &[(&Variant, Item)], - parent_item: &Item, - override_required: bool, -) -> Result<TokenStream, syn::Error> { - use syn::Fields::*; - - let app_var = Ident::new("__clap_app", Span::call_site()); - - let mut subcommands = Vec::new(); - for (variant, item) in variants { - let kind = item.kind(); - - 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, - - _ => 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].ty; - 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); - } - } 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].ty; - 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) - } - } - } - } - 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 #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 = collect_args_fields(item, fields)?; - 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 - } - } - Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { - let ty = &unnamed[0].ty; - 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) - } - } - }; - 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") - } - }; - - 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) - } - }; - subcommands.push(genned); - } - - 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(); - Ok(quote! { - #deprecations; - let #app_var = #app_var #initial_app_methods; - #( #subcommands )*; - #app_var #final_app_methods - }) -} - -fn gen_has_subcommand(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error> { - use syn::Fields::*; - - let mut ext_subcmd = false; - - 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 => { - ext_subcmd = true; - None - } - 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 sub_name = item.cased_name(); - quote! { - if #sub_name == __clap_name { - return true - } - } - }); - let child_subcommands = flatten_variants - .iter() - .map(|(variant, _attrs)| match variant.fields { - Unnamed(ref fields) if fields.unnamed.len() == 1 => { - let ty = &fields.unnamed[0].ty; - 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>>()?; - - let genned = if ext_subcmd { - quote! { true } - } else { - quote! { - #( #subcommands )* - - #( #child_subcommands )else* - - false - } - }; - Ok(genned) -} - -fn gen_from_arg_matches(variants: &[(&Variant, Item)]) -> Result<TokenStream, syn::Error> { - use syn::Fields::*; - - let subcommand_name_var = format_ident!("__clap_name"); - let sub_arg_matches_var = format_ident!("__clap_arg_matches"); - - 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, - - _ => 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>` \ - to be used with `external_subcommand`." - ); - } - } - - 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)); - } - Kind::Flatten(_) | Kind::Subcommand(_) | Kind::Command(_) => { - if matches!(&*item.kind(), Kind::Flatten(_)) { - flatten_variants.push((variant, item)); - } else { - unflatten_variants.push((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 { - Named(ref fields) => { - let fields = collect_args_fields(item, fields)?; - args::gen_constructor(&fields)? - }, - Unit => quote!(), - Unnamed(ref fields) if fields.unnamed.len() == 1 => { - let ty = &fields.unnamed[0].ty; - quote!( ( <#ty as clap::FromArgMatches>::from_arg_matches_mut(__clap_arg_matches)? ) ) - } - Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident), - }; - - 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].ty; - Ok(quote! { - if __clap_arg_matches - .subcommand_name() - .map(|__clap_name| <#ty as clap::Subcommand>::has_subcommand(__clap_name)) - .unwrap_or_default() - { - 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=> - ::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>("") - .unwrap() - .map(#str_ty::from) - ) - .collect::<::std::vec::Vec<_>>() - )) - }, - - None => quote! { - ::std::result::Result::Err(clap::Error::raw(clap::error::ErrorKind::InvalidSubcommand, format!("The subcommand '{}' wasn't recognized", #subcommand_name_var))) - }, - }; - - let raw_deprecated = args::raw_deprecated(); - Ok(quote! { - fn from_arg_matches_mut(__clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result<Self, clap::Error> { - #raw_deprecated - - #( #child_subcommands )else* - - if let Some((#subcommand_name_var, mut __clap_arg_sub_matches)) = __clap_arg_matches.remove_subcommand() { - let #sub_arg_matches_var = &mut __clap_arg_sub_matches; - #( #subcommands )* - - #wildcard - } else { - ::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)]) -> Result<TokenStream, syn::Error> { - use syn::Fields::*; - - let (flatten, variants): (Vec<_>, Vec<_>) = variants - .iter() - .filter_map(|(variant, item)| { - let kind = item.kind(); - match &*kind { - // Fallback to `from_arg_matches_mut` - Kind::Skip(_, _) - | Kind::Arg(_) - | Kind::FromGlobal(_) - | Kind::Value - | Kind::ExternalSubcommand => None, - 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 sub_name = item.cased_name(); - let variant_name = &variant.ident; - let (pattern, updater) = match variant.fields { - Named(ref fields) => { - let field_names = fields.named.iter().map(|field| { - field.ident.as_ref().unwrap() - }).collect::<Vec<_>>(); - let fields = collect_args_fields(item, fields)?; - let update = args::gen_updater(&fields, false)?; - (quote!( { #( #field_names, )* }), quote!( { #update } )) - } - Unit => (quote!(), quote!({})), - Unnamed(ref fields) => { - if fields.unnamed.len() == 1 { - ( - quote!((ref mut __clap_arg)), - quote!(clap::FromArgMatches::update_from_arg_matches_mut( - __clap_arg, - __clap_arg_matches - )?), - ) - } else { - abort_call_site!("{}: tuple enums are not supported", variant.ident) - } - } - }; - - 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].ty; - 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(); - Ok(quote! { - fn update_from_arg_matches_mut<'b>( - &mut self, - __clap_arg_matches: &mut clap::ArgMatches, - ) -> ::std::result::Result<(), clap::Error> { - #raw_deprecated - - if let Some(__clap_name) = __clap_arg_matches.subcommand_name() { - match self { - #( #subcommands ),* - s => { - #( #child_subcommands )* - *s = <Self as clap::FromArgMatches>::from_arg_matches_mut(__clap_arg_matches)?; - } - } - } - ::std::result::Result::Ok(()) - } - }) -} diff --git a/vendor/clap_derive/src/derives/value_enum.rs b/vendor/clap_derive/src/derives/value_enum.rs deleted file mode 100644 index c0e0434..0000000 --- a/vendor/clap_derive/src/derives/value_enum.rs +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>, -// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and -// Ana Hobden (@hoverbear) <operator@hoverbear.org> -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use proc_macro2::TokenStream; -use quote::quote; -use quote::quote_spanned; -use syn::{spanned::Spanned, Data, DeriveInput, Fields, Ident, Variant}; - -use crate::item::{Item, Kind, Name}; - -pub fn derive_value_enum(input: &DeriveInput) -> Result<TokenStream, syn::Error> { - let ident = &input.ident; - - match input.data { - Data::Enum(ref e) => { - let name = Name::Derived(ident.clone()); - 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)], -) -> Result<TokenStream, syn::Error> { - if !matches!(&*item.kind(), Kind::Value) { - abort! { item.kind().span(), - "`{}` cannot be used with `value`", - item.kind().name(), - } - } - - let lits = lits(variants)?; - let value_variants = gen_value_variants(&lits); - let to_possible_value = gen_to_possible_value(item, &lits); - - Ok(quote! { - #[allow( - dead_code, - unreachable_code, - unused_variables, - unused_braces, - unused_qualifications, - )] - #[allow( - clippy::style, - clippy::complexity, - clippy::pedantic, - clippy::restriction, - clippy::perf, - clippy::deprecated, - clippy::nursery, - clippy::cargo, - clippy::suspicious_else_formatting, - clippy::almost_swapped, - clippy::redundant_locals, - )] - #[automatically_derived] - impl clap::ValueEnum for #item_name { - #value_variants - #to_possible_value - } - }) -} - -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 { - let lit = lits.iter().map(|l| &l.1).collect::<Vec<_>>(); - - quote! { - fn value_variants<'a>() -> &'a [Self]{ - &[#(Self::#lit),*] - } - } -} - -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::builder::PossibleValue> { - #deprecations - match self { - #(Self::#variant => Some(#lit),)* - _ => None - } - } - } -} diff --git a/vendor/clap_derive/src/dummies.rs b/vendor/clap_derive/src/dummies.rs deleted file mode 100644 index 3a1581b..0000000 --- a/vendor/clap_derive/src/dummies.rs +++ /dev/null @@ -1,99 +0,0 @@ -//! Dummy implementations that we emit along with an error. - -use proc_macro2::Ident; -use quote::quote; - -#[must_use] -pub fn parser(name: &Ident) -> proc_macro2::TokenStream { - let into_app = into_app(name); - quote!( - #[automatically_derived] - impl clap::Parser for #name {} - #into_app - ) -} - -#[must_use] -pub fn into_app(name: &Ident) -> proc_macro2::TokenStream { - quote! { - #[automatically_derived] - impl clap::CommandFactory for #name { - fn command<'b>() -> clap::Command { - unimplemented!() - } - fn command_for_update<'b>() -> clap::Command { - unimplemented!() - } - } - } -} - -#[must_use] -pub fn from_arg_matches(name: &Ident) -> proc_macro2::TokenStream { - quote! { - #[automatically_derived] - impl clap::FromArgMatches for #name { - fn from_arg_matches(_m: &clap::ArgMatches) -> ::std::result::Result<Self, clap::Error> { - unimplemented!() - } - fn update_from_arg_matches(&mut self, matches: &clap::ArgMatches) -> ::std::result::Result<(), clap::Error>{ - unimplemented!() - } - } - } -} - -#[must_use] -pub fn subcommand(name: &Ident) -> proc_macro2::TokenStream { - let from_arg_matches = from_arg_matches(name); - quote! { - #[automatically_derived] - impl clap::Subcommand for #name { - fn augment_subcommands(_cmd: clap::Command) -> clap::Command { - unimplemented!() - } - fn augment_subcommands_for_update(_cmd: clap::Command) -> clap::Command { - unimplemented!() - } - fn has_subcommand(name: &str) -> bool { - unimplemented!() - } - } - #from_arg_matches - } -} - -#[must_use] -pub fn args(name: &Ident) -> proc_macro2::TokenStream { - let from_arg_matches = from_arg_matches(name); - quote! { - #[automatically_derived] - impl clap::Args for #name { - fn augment_args(_cmd: clap::Command) -> clap::Command { - unimplemented!() - } - fn augment_args_for_update(_cmd: clap::Command) -> clap::Command { - unimplemented!() - } - } - #from_arg_matches - } -} - -#[must_use] -pub fn value_enum(name: &Ident) -> proc_macro2::TokenStream { - quote! { - #[automatically_derived] - impl clap::ValueEnum for #name { - fn value_variants<'a>() -> &'a [Self]{ - unimplemented!() - } - fn from_str(_input: &str, _ignore_case: bool) -> ::std::result::Result<Self, String> { - unimplemented!() - } - fn to_possible_value<'a>(&self) -> ::std::option::Option<clap::builder::PossibleValue>{ - unimplemented!() - } - } - } -} diff --git a/vendor/clap_derive/src/item.rs b/vendor/clap_derive/src/item.rs deleted file mode 100644 index 114849f..0000000 --- a/vendor/clap_derive/src/item.rs +++ /dev/null @@ -1,1468 +0,0 @@ -// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>, -// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and -// Ana Hobden (@hoverbear) <operator@hoverbear.org> -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// This work was derived from Structopt (https://github.com/TeXitoi/structopt) -// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the -// MIT/Apache 2.0 license. - -use std::env; - -use heck::{ToKebabCase, ToLowerCamelCase, ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase}; -use proc_macro2::{self, Span, TokenStream}; -use quote::{format_ident, quote, quote_spanned, ToTokens}; -use syn::DeriveInput; -use syn::{self, ext::IdentExt, spanned::Spanned, Attribute, Field, Ident, LitStr, Type, Variant}; - -use crate::attr::*; -use crate::utils::{extract_doc_comment, format_doc_comment, inner_type, is_simple_ty, Sp, Ty}; - -/// Default casing style for generated arguments. -pub const DEFAULT_CASING: CasingStyle = CasingStyle::Kebab; - -/// Default casing style for environment variables -pub const DEFAULT_ENV_CASING: CasingStyle = CasingStyle::ScreamingSnake; - -#[derive(Clone)] -pub struct Item { - name: Name, - casing: Sp<CasingStyle>, - env_casing: Sp<CasingStyle>, - ty: Option<Type>, - doc_comment: Vec<Method>, - methods: Vec<Method>, - deprecations: Vec<Deprecation>, - value_parser: Option<ValueParser>, - action: Option<Action>, - verbatim_doc_comment: bool, - force_long_help: bool, - next_display_order: Option<Method>, - next_help_heading: Option<Method>, - 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) -> Result<Self, syn::Error> { - let ident = input.ident.clone(); - let span = input.ident.span(); - let attrs = &input.attrs; - let argument_casing = Sp::new(DEFAULT_CASING, span); - let env_casing = Sp::new(DEFAULT_ENV_CASING, span); - 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)?; - res.push_doc_comment(attrs, "about", Some("long_about")); - - Ok(res) - } - - 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; - let argument_casing = Sp::new(DEFAULT_CASING, span); - let env_casing = Sp::new(DEFAULT_ENV_CASING, span); - 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)?; - res.push_doc_comment(attrs, "about", Some("long_about")); - - Ok(res) - } - - 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; - let argument_casing = Sp::new(DEFAULT_CASING, span); - let env_casing = Sp::new(DEFAULT_ENV_CASING, span); - 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)?; - // Ignoring `push_doc_comment` as there is no top-level clap builder to add documentation - // to - - if res.has_explicit_methods() { - abort!( - res.methods[0].name.span(), - "{} doesn't exist for `ValueEnum` enums", - res.methods[0].name - ); - } - - Ok(res) - } - - pub fn from_subcommand_variant( - variant: &Variant, - struct_casing: Sp<CasingStyle>, - env_casing: Sp<CasingStyle>, - ) -> Result<Self, syn::Error> { - let name = variant.ident.clone(); - let ident = variant.ident.clone(); - let span = variant.span(); - let ty = match variant.fields { - syn::Fields::Unnamed(syn::FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { - Ty::from_syn_ty(&unnamed[0].ty) - } - syn::Fields::Named(_) | syn::Fields::Unnamed(..) | syn::Fields::Unit => { - Sp::new(Ty::Other, span) - } - }; - let kind = Sp::new(Kind::Command(ty), span); - let mut res = Self::new( - Name::Derived(name), - ident, - None, - struct_casing, - env_casing, - kind, - ); - 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")); - } - - match &*res.kind { - Kind::Flatten(_) => { - if res.has_explicit_methods() { - abort!( - res.kind.span(), - "methods are not allowed for flattened entry" - ); - } - } - - Kind::Subcommand(_) - | Kind::ExternalSubcommand - | Kind::FromGlobal(_) - | Kind::Skip(_, _) - | Kind::Command(_) - | Kind::Value - | Kind::Arg(_) => (), - } - - Ok(res) - } - - pub fn from_value_enum_variant( - variant: &Variant, - argument_casing: Sp<CasingStyle>, - env_casing: Sp<CasingStyle>, - ) -> Result<Self, syn::Error> { - let ident = variant.ident.clone(); - let span = variant.span(); - let kind = Sp::new(Kind::Value, span); - let mut res = Self::new( - Name::Derived(variant.ident.clone()), - ident, - None, - argument_casing, - env_casing, - kind, - ); - 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); - } - - Ok(res) - } - - pub fn from_args_field( - field: &Field, - struct_casing: Sp<CasingStyle>, - env_casing: Sp<CasingStyle>, - ) -> Result<Self, syn::Error> { - let name = field.ident.clone().unwrap(); - let ident = field.ident.clone().unwrap(); - let span = field.span(); - let ty = Ty::from_syn_ty(&field.ty); - let kind = Sp::new(Kind::Arg(ty), span); - let mut res = Self::new( - Name::Derived(name), - ident, - Some(field.ty.clone()), - struct_casing, - env_casing, - kind, - ); - 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")); - } - - match &*res.kind { - Kind::Flatten(_) => { - if res.has_explicit_methods() { - abort!( - res.kind.span(), - "methods are not allowed for flattened entry" - ); - } - } - - Kind::Subcommand(_) => { - if res.has_explicit_methods() { - abort!( - res.kind.span(), - "methods in attributes are not allowed for subcommand" - ); - } - } - Kind::Skip(_, _) - | Kind::FromGlobal(_) - | Kind::Arg(_) - | Kind::Command(_) - | Kind::Value - | Kind::ExternalSubcommand => {} - } - - Ok(res) - } - - fn new( - name: Name, - ident: Ident, - ty: Option<Type>, - casing: Sp<CasingStyle>, - env_casing: Sp<CasingStyle>, - kind: Sp<Kind>, - ) -> Self { - let group_id = Name::Derived(ident); - Self { - name, - ty, - casing, - env_casing, - doc_comment: vec![], - methods: vec![], - deprecations: vec![], - value_parser: None, - action: None, - verbatim_doc_comment: false, - force_long_help: false, - next_display_order: None, - next_help_heading: None, - 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 => { - self.deprecations.push(Deprecation { - span: name.span(), - id: "id_is_only_for_arg", - version: "4.0.0", - description: format!( - "`#[{}(id)] was allowed by mistake, instead use `#[{}(name)]`", - kind.as_str(), - 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); - } - } - } else if name == "name" { - match kind { - AttrKind::Arg => { - self.deprecations.push(Deprecation { - span: name.span(), - id: "id_is_only_for_arg", - version: "4.0.0", - description: format!( - "`#[{}(name)] was allowed by mistake, instead use `#[{}(id)]` or `#[{}(value_name)]`", - kind.as_str(), - kind.as_str(), - 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); - } - } - } else if name == "value_parser" { - self.value_parser = Some(ValueParser::Explicit(Method::new(name, arg))); - } else if name == "action" { - self.action = Some(Action::Explicit(Method::new(name, arg))); - } else { - if name == "short" || name == "long" { - self.is_positional = false; - } - 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]) -> Result<(), syn::Error> { - for attr in attrs { - if let Some(AttrValue::Call(_)) = &attr.value { - continue; - } - - let actual_attr_kind = *attr.kind.get(); - let kind = match &attr.magic { - Some(MagicAttrName::FromGlobal) => { - if attr.value.is_some() { - let expr = attr.value_or_abort()?; - abort!(expr, "attribute `{}` does not accept a value", attr.name); - } - let ty = self - .kind() - .ty() - .cloned() - .unwrap_or_else(|| Sp::new(Ty::Other, self.kind.span())); - let kind = Sp::new(Kind::FromGlobal(ty), attr.name.clone().span()); - Some(kind) - } - Some(MagicAttrName::Subcommand) if attr.value.is_none() => { - if attr.value.is_some() { - let expr = attr.value_or_abort()?; - abort!(expr, "attribute `{}` does not accept a value", attr.name); - } - let ty = self - .kind() - .ty() - .cloned() - .unwrap_or_else(|| Sp::new(Ty::Other, self.kind.span())); - let kind = Sp::new(Kind::Subcommand(ty), attr.name.clone().span()); - Some(kind) - } - Some(MagicAttrName::ExternalSubcommand) if attr.value.is_none() => { - if attr.value.is_some() { - 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()); - Some(kind) - } - Some(MagicAttrName::Flatten) if attr.value.is_none() => { - if attr.value.is_some() { - let expr = attr.value_or_abort()?; - abort!(expr, "attribute `{}` does not accept a value", attr.name); - } - let ty = self - .kind() - .ty() - .cloned() - .unwrap_or_else(|| Sp::new(Ty::Other, self.kind.span())); - let kind = Sp::new(Kind::Flatten(ty), attr.name.clone().span()); - Some(kind) - } - Some(MagicAttrName::Skip) if actual_attr_kind != AttrKind::Group => { - let expr = attr.value.clone(); - let kind = Sp::new( - Kind::Skip(expr, self.kind.attr_kind()), - attr.name.clone().span(), - ); - Some(kind) - } - _ => None, - }; - - if let Some(kind) = kind { - self.set_kind(kind)?; - } - } - - Ok(()) - } - - 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(); - match (actual_attr_kind, expected_attr_kind) { - (AttrKind::Clap, _) | (AttrKind::StructOpt, _) => { - self.deprecations.push(Deprecation::attribute( - "4.0.0", - actual_attr_kind, - expected_attr_kind, - attr.kind.span(), - )); - } - - (AttrKind::Group, AttrKind::Command) => {} - - _ if attr.kind != expected_attr_kind => { - abort!( - attr.kind.span(), - "Expected `{}` attribute instead of `{}`", - expected_attr_kind.as_str(), - actual_attr_kind.as_str() - ); - } - - _ => {} - } - - if let Some(AttrValue::Call(tokens)) = &attr.value { - // Force raw mode with method call syntax - self.push_method(*attr.kind.get(), attr.name.clone(), quote!(#(#tokens),*)); - continue; - } - - match &attr.magic { - Some(MagicAttrName::Short) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg])?; - - self.push_method( - *attr.kind.get(), - attr.name.clone(), - self.name.clone().translate_char(*self.casing), - ); - } - - Some(MagicAttrName::Long) if attr.value.is_none() => { - 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])?; - - self.deprecations.push(Deprecation { - span: attr.name.span(), - id: "bare_value_parser", - version: "4.0.0", - description: "`#[arg(value_parser)]` is now the default and is no longer needed`".to_owned(), - }); - self.value_parser = Some(ValueParser::Implicit(attr.name.clone())); - } - - Some(MagicAttrName::Action) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg])?; - - self.deprecations.push(Deprecation { - span: attr.name.span(), - id: "bare_action", - version: "4.0.0", - description: "`#[arg(action)]` is now the default and is no longer needed`".to_owned(), - }); - self.action = Some(Action::Implicit(attr.name.clone())); - } - - Some(MagicAttrName::Env) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg])?; - - self.push_method( - *attr.kind.get(), - attr.name.clone(), - self.name.clone().translate(*self.env_casing), - ); - } - - Some(MagicAttrName::ValueEnum) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Arg])?; - - self.is_enum = true - } - - Some(MagicAttrName::VerbatimDocComment) if attr.value.is_none() => { - self.verbatim_doc_comment = true - } - - Some(MagicAttrName::About) if attr.value.is_none() => { - assert_attr_kind(attr, &[AttrKind::Command])?; - - if let Some(method) = - 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])?; - - self.force_long_help = true; - } - - Some(MagicAttrName::LongHelp) if attr.value.is_none() => { - 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])?; - - 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])?; - - 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])?; - - let ty = if let Some(ty) = self.ty.as_ref() { - ty - } else { - abort!( - attr.name.clone(), - "#[arg(default_value_t)] (without an argument) can be used \ - 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 val = if let Some(expr) = &attr.value { - quote!(#expr) - } else { - quote!(<#ty as ::std::default::Default>::default()) - }; - - let val = if attrs - .iter() - .any(|a| a.magic == Some(MagicAttrName::ValueEnum)) - { - quote_spanned!(attr.name.clone().span()=> { - static DEFAULT_VALUE: ::std::sync::OnceLock<String> = ::std::sync::OnceLock::new(); - let s = DEFAULT_VALUE.get_or_init(|| { - let val: #ty = #val; - clap::ValueEnum::to_possible_value(&val).unwrap().get_name().to_owned() - }); - let s: &'static str = &*s; - s - }) - } else { - quote_spanned!(attr.name.clone().span()=> { - static DEFAULT_VALUE: ::std::sync::OnceLock<String> = ::std::sync::OnceLock::new(); - let s = DEFAULT_VALUE.get_or_init(|| { - let val: #ty = #val; - ::std::string::ToString::to_string(&val) - }); - let s: &'static str = &*s; - s - }) - }; - - let raw_ident = Ident::new("default_value", attr.name.clone().span()); - self.methods.push(Method::new(raw_ident, val)); - } - - Some(MagicAttrName::DefaultValuesT) => { - assert_attr_kind(attr, &[AttrKind::Arg])?; - - let ty = if let Some(ty) = self.ty.as_ref() { - ty - } else { - abort!( - attr.name.clone(), - "#[arg(default_values_t)] (without an argument) can be used \ - 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 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\n\n= note: {note}\n\n", - - note = "see \ - https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") - } - let inner_type = inner_type(ty); - - // Use `Borrow<#inner_type>` so we accept `&Vec<#inner_type>` and - // `Vec<#inner_type>`. - let val = if attrs - .iter() - .any(|a| a.magic == Some(MagicAttrName::ValueEnum)) - { - quote_spanned!(attr.name.clone().span()=> { - { - fn iter_to_vals<T>(iterable: impl IntoIterator<Item = T>) -> impl Iterator<Item=String> - where - T: ::std::borrow::Borrow<#inner_type> - { - iterable - .into_iter() - .map(|val| { - clap::ValueEnum::to_possible_value(val.borrow()).unwrap().get_name().to_owned() - }) - } - - static DEFAULT_STRINGS: ::std::sync::OnceLock<Vec<String>> = ::std::sync::OnceLock::new(); - static DEFAULT_VALUES: ::std::sync::OnceLock<Vec<&str>> = ::std::sync::OnceLock::new(); - DEFAULT_VALUES.get_or_init(|| { - DEFAULT_STRINGS.get_or_init(|| iter_to_vals(#expr).collect()).iter().map(::std::string::String::as_str).collect() - }).iter().copied() - } - }) - } else { - quote_spanned!(attr.name.clone().span()=> { - { - fn iter_to_vals<T>(iterable: impl IntoIterator<Item = T>) -> impl Iterator<Item=String> - where - T: ::std::borrow::Borrow<#inner_type> - { - iterable.into_iter().map(|val| val.borrow().to_string()) - } - - static DEFAULT_STRINGS: ::std::sync::OnceLock<Vec<String>> = ::std::sync::OnceLock::new(); - static DEFAULT_VALUES: ::std::sync::OnceLock<Vec<&str>> = ::std::sync::OnceLock::new(); - DEFAULT_VALUES.get_or_init(|| { - DEFAULT_STRINGS.get_or_init(|| iter_to_vals(#expr).collect()).iter().map(::std::string::String::as_str).collect() - }).iter().copied() - } - }) - }; - - self.methods.push(Method::new( - Ident::new("default_values", attr.name.clone().span()), - val, - )); - } - - Some(MagicAttrName::DefaultValueOsT) => { - assert_attr_kind(attr, &[AttrKind::Arg])?; - - let ty = if let Some(ty) = self.ty.as_ref() { - ty - } else { - abort!( - attr.name.clone(), - "#[arg(default_value_os_t)] (without an argument) can be used \ - 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 val = if let Some(expr) = &attr.value { - quote!(#expr) - } else { - quote!(<#ty as ::std::default::Default>::default()) - }; - - let val = if attrs - .iter() - .any(|a| a.magic == Some(MagicAttrName::ValueEnum)) - { - quote_spanned!(attr.name.clone().span()=> { - static DEFAULT_VALUE: ::std::sync::OnceLock<String> = ::std::sync::OnceLock::new(); - let s = DEFAULT_VALUE.get_or_init(|| { - let val: #ty = #val; - clap::ValueEnum::to_possible_value(&val).unwrap().get_name().to_owned() - }); - let s: &'static str = &*s; - s - }) - } else { - quote_spanned!(attr.name.clone().span()=> { - static DEFAULT_VALUE: ::std::sync::OnceLock<::std::ffi::OsString> = ::std::sync::OnceLock::new(); - let s = DEFAULT_VALUE.get_or_init(|| { - let val: #ty = #val; - ::std::ffi::OsString::from(val) - }); - let s: &'static ::std::ffi::OsStr = &*s; - s - }) - }; - - let raw_ident = Ident::new("default_value", attr.name.clone().span()); - self.methods.push(Method::new(raw_ident, val)); - } - - Some(MagicAttrName::DefaultValuesOsT) => { - assert_attr_kind(attr, &[AttrKind::Arg])?; - - let ty = if let Some(ty) = self.ty.as_ref() { - ty - } else { - abort!( - attr.name.clone(), - "#[arg(default_values_os_t)] (without an argument) can be used \ - 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 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\n\n= note: {note}\n\n", - - note = "see \ - https://github.com/clap-rs/clap/blob/master/examples/derive_ref/README.md#magic-attributes") - } - let inner_type = inner_type(ty); - - // Use `Borrow<#inner_type>` so we accept `&Vec<#inner_type>` and - // `Vec<#inner_type>`. - let val = if attrs - .iter() - .any(|a| a.magic == Some(MagicAttrName::ValueEnum)) - { - quote_spanned!(attr.name.clone().span()=> { - { - fn iter_to_vals<T>(iterable: impl IntoIterator<Item = T>) -> impl Iterator<Item=::std::ffi::OsString> - where - T: ::std::borrow::Borrow<#inner_type> - { - iterable - .into_iter() - .map(|val| { - clap::ValueEnum::to_possible_value(val.borrow()).unwrap().get_name().to_owned().into() - }) - } - - static DEFAULT_STRINGS: ::std::sync::OnceLock<Vec<::std::ffi::OsString>> = ::std::sync::OnceLock::new(); - static DEFAULT_VALUES: ::std::sync::OnceLock<Vec<&::std::ffi::OsStr>> = ::std::sync::OnceLock::new(); - DEFAULT_VALUES.get_or_init(|| { - DEFAULT_STRINGS.get_or_init(|| iter_to_vals(#expr).collect()).iter().map(::std::ffi::OsString::as_os_str).collect() - }).iter().copied() - } - }) - } else { - quote_spanned!(attr.name.clone().span()=> { - { - fn iter_to_vals<T>(iterable: impl IntoIterator<Item = T>) -> impl Iterator<Item=::std::ffi::OsString> - where - T: ::std::borrow::Borrow<#inner_type> - { - iterable.into_iter().map(|val| val.borrow().into()) - } - - static DEFAULT_STRINGS: ::std::sync::OnceLock<Vec<::std::ffi::OsString>> = ::std::sync::OnceLock::new(); - static DEFAULT_VALUES: ::std::sync::OnceLock<Vec<&::std::ffi::OsStr>> = ::std::sync::OnceLock::new(); - DEFAULT_VALUES.get_or_init(|| { - DEFAULT_STRINGS.get_or_init(|| iter_to_vals(#expr).collect()).iter().map(::std::ffi::OsString::as_os_str).collect() - }).iter().copied() - } - }) - }; - - self.methods.push(Method::new( - Ident::new("default_values", attr.name.clone().span()), - val, - )); - } - - Some(MagicAttrName::NextDisplayOrder) => { - assert_attr_kind(attr, &[AttrKind::Command])?; - - 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])?; - - 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)?; - } - - Some(MagicAttrName::RenameAllEnv) => { - assert_attr_kind(attr, &[AttrKind::Command, AttrKind::Arg])?; - - let lit = attr.lit_str_or_abort()?; - self.env_casing = CasingStyle::from_lit(lit)?; - } - - Some(MagicAttrName::Skip) if actual_attr_kind == AttrKind::Group => { - self.skip_group = true; - } - - None - // Magic only for the default, otherwise just forward to the builder - | Some(MagicAttrName::Short) - | Some(MagicAttrName::Long) - | Some(MagicAttrName::Env) - | Some(MagicAttrName::About) - | Some(MagicAttrName::LongAbout) - | Some(MagicAttrName::LongHelp) - | Some(MagicAttrName::Author) - | Some(MagicAttrName::Version) - => { - 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()?; - 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()?; - abort!(expr, "attribute `{}` does not accept a value", attr.name); - } - - // Kinds - Some(MagicAttrName::FromGlobal) - | Some(MagicAttrName::Subcommand) - | Some(MagicAttrName::ExternalSubcommand) - | Some(MagicAttrName::Flatten) - | Some(MagicAttrName::Skip) => { - } - } - } - - if self.has_explicit_methods() { - if let Kind::Skip(_, attr) = &*self.kind { - abort!( - self.methods[0].name.span(), - "`{}` cannot be used with `#[{}(skip)]", - self.methods[0].name, - attr.as_str(), - ); - } - if let Kind::FromGlobal(_) = &*self.kind { - abort!( - self.methods[0].name.span(), - "`{}` cannot be used with `#[arg(from_global)]", - self.methods[0].name, - ); - } - } - - Ok(()) - } - - fn push_doc_comment(&mut self, attrs: &[Attribute], short_name: &str, long_name: Option<&str>) { - let lines = extract_doc_comment(attrs); - - if !lines.is_empty() { - let (short_help, long_help) = - format_doc_comment(&lines, !self.verbatim_doc_comment, self.force_long_help); - let short_name = format_ident!("{short_name}"); - let short = Method::new( - short_name, - short_help - .map(|h| quote!(#h)) - .unwrap_or_else(|| quote!(None)), - ); - self.doc_comment.push(short); - if let Some(long_name) = long_name { - let long_name = format_ident!("{long_name}"); - let long = Method::new( - long_name, - long_help - .map(|h| quote!(#h)) - .unwrap_or_else(|| quote!(None)), - ); - self.doc_comment.push(long); - } - } - } - - 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(_)) - | (Kind::Arg(_), Kind::Flatten(_)) - | (Kind::Arg(_), Kind::Skip(_, _)) - | (Kind::Command(_), Kind::Subcommand(_)) - | (Kind::Command(_), Kind::Flatten(_)) - | (Kind::Command(_), Kind::Skip(_, _)) - | (Kind::Command(_), Kind::ExternalSubcommand) - | (Kind::Value, Kind::Skip(_, _)) => { - self.kind = kind; - } - - (_, _) => { - let old = self.kind.name(); - let new = kind.name(); - abort!(kind.span(), "`{new}` cannot be used with `{old}`"); - } - } - Ok(()) - } - - pub fn find_default_method(&self) -> Option<&Method> { - self.methods - .iter() - .find(|m| m.name == "default_value" || m.name == "default_value_os") - } - - /// generate methods from attributes on top of struct or enum - pub fn initial_top_level_methods(&self) -> TokenStream { - let next_display_order = self.next_display_order.as_ref().into_iter(); - let next_help_heading = self.next_help_heading.as_ref().into_iter(); - quote!( - #(#next_display_order)* - #(#next_help_heading)* - ) - } - - pub fn final_top_level_methods(&self) -> TokenStream { - let methods = &self.methods; - let doc_comment = &self.doc_comment; - - quote!( #(#doc_comment)* #(#methods)*) - } - - /// generate methods on top of a field - pub fn field_methods(&self) -> proc_macro2::TokenStream { - let methods = &self.methods; - let doc_comment = &self.doc_comment; - 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)* ) - } - - pub fn next_display_order(&self) -> TokenStream { - let next_display_order = self.next_display_order.as_ref().into_iter(); - quote!( #(#next_display_order)* ) - } - - pub fn next_help_heading(&self) -> TokenStream { - let next_help_heading = self.next_help_heading.as_ref().into_iter(); - quote!( #(#next_help_heading)* ) - } - - pub fn id(&self) -> TokenStream { - self.name.clone().raw() - } - - pub fn cased_name(&self) -> TokenStream { - self.name.clone().translate(*self.casing) - } - - pub fn value_name(&self) -> TokenStream { - self.name.clone().translate(CasingStyle::ScreamingSnake) - } - - pub fn value_parser(&self, field_type: &Type) -> Method { - self.value_parser - .clone() - .map(|p| { - let inner_type = inner_type(field_type); - p.resolve(inner_type) - }) - .unwrap_or_else(|| { - let inner_type = inner_type(field_type); - if let Some(action) = self.action.as_ref() { - let span = action.span(); - default_value_parser(inner_type, span) - } else { - let span = self - .action - .as_ref() - .map(|a| a.span()) - .unwrap_or_else(|| self.kind.span()); - default_value_parser(inner_type, span) - } - }) - } - - pub fn action(&self, field_type: &Type) -> Method { - self.action - .clone() - .map(|p| p.resolve(field_type)) - .unwrap_or_else(|| { - if let Some(value_parser) = self.value_parser.as_ref() { - let span = value_parser.span(); - default_action(field_type, span) - } else { - let span = self - .value_parser - .as_ref() - .map(|a| a.span()) - .unwrap_or_else(|| self.kind.span()); - default_action(field_type, span) - } - }) - } - - pub fn kind(&self) -> Sp<Kind> { - self.kind.clone() - } - - pub fn is_positional(&self) -> bool { - self.is_positional - } - - pub fn casing(&self) -> Sp<CasingStyle> { - self.casing - } - - pub fn env_casing(&self) -> Sp<CasingStyle> { - self.env_casing - } - - pub fn has_explicit_methods(&self) -> bool { - self.methods - .iter() - .any(|m| m.name != "help" && m.name != "long_help") - } - - pub fn skip_group(&self) -> bool { - self.skip_group - } -} - -#[derive(Clone)] -enum ValueParser { - Explicit(Method), - Implicit(Ident), -} - -impl ValueParser { - fn resolve(self, _inner_type: &Type) -> Method { - match self { - Self::Explicit(method) => method, - Self::Implicit(ident) => default_value_parser(_inner_type, ident.span()), - } - } - - fn span(&self) -> Span { - match self { - Self::Explicit(method) => method.name.span(), - Self::Implicit(ident) => ident.span(), - } - } -} - -fn default_value_parser(inner_type: &Type, span: Span) -> Method { - let func = Ident::new("value_parser", span); - Method::new( - func, - quote_spanned! { span=> - clap::value_parser!(#inner_type) - }, - ) -} - -#[derive(Clone)] -pub enum Action { - Explicit(Method), - Implicit(Ident), -} - -impl Action { - pub fn resolve(self, _field_type: &Type) -> Method { - match self { - Self::Explicit(method) => method, - Self::Implicit(ident) => default_action(_field_type, ident.span()), - } - } - - pub fn span(&self) -> Span { - match self { - Self::Explicit(method) => method.name.span(), - Self::Implicit(ident) => ident.span(), - } - } -} - -fn default_action(field_type: &Type, span: Span) -> Method { - let ty = Ty::from_syn_ty(field_type); - let args = match *ty { - Ty::Vec | Ty::OptionVec | Ty::VecVec | Ty::OptionVecVec => { - quote_spanned! { span=> - clap::ArgAction::Append - } - } - Ty::Option | Ty::OptionOption => { - quote_spanned! { span=> - clap::ArgAction::Set - } - } - _ => { - if is_simple_ty(field_type, "bool") { - quote_spanned! { span=> - clap::ArgAction::SetTrue - } - } else { - quote_spanned! { span=> - clap::ArgAction::Set - } - } - } - }; - - let func = Ident::new("action", span); - Method::new(func, args) -} - -#[allow(clippy::large_enum_variant)] -#[derive(Clone)] -pub enum Kind { - Arg(Sp<Ty>), - Command(Sp<Ty>), - Value, - FromGlobal(Sp<Ty>), - Subcommand(Sp<Ty>), - Flatten(Sp<Ty>), - Skip(Option<AttrValue>, AttrKind), - ExternalSubcommand, -} - -impl Kind { - pub fn name(&self) -> &'static str { - match self { - Self::Arg(_) => "arg", - Self::Command(_) => "command", - Self::Value => "value", - Self::FromGlobal(_) => "from_global", - Self::Subcommand(_) => "subcommand", - Self::Flatten(_) => "flatten", - Self::Skip(_, _) => "skip", - Self::ExternalSubcommand => "external_subcommand", - } - } - - pub fn attr_kind(&self) -> AttrKind { - match self { - Self::Arg(_) => AttrKind::Arg, - Self::Command(_) => AttrKind::Command, - Self::Value => AttrKind::Value, - Self::FromGlobal(_) => AttrKind::Arg, - Self::Subcommand(_) => AttrKind::Command, - Self::Flatten(_) => AttrKind::Command, - Self::Skip(_, kind) => *kind, - Self::ExternalSubcommand => AttrKind::Command, - } - } - - pub fn ty(&self) -> Option<&Sp<Ty>> { - match self { - Self::Arg(ty) - | Self::Command(ty) - | Self::Flatten(ty) - | Self::FromGlobal(ty) - | Self::Subcommand(ty) => Some(ty), - Self::Value | Self::Skip(_, _) | Self::ExternalSubcommand => None, - } - } -} - -#[derive(Clone)] -pub struct Method { - name: Ident, - args: TokenStream, -} - -impl Method { - pub fn new(name: Ident, args: TokenStream) -> Self { - Method { name, args } - } - - 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 Ok(None); - } - LitStr::new(&val, ident.span()) - } - Err(_) => { - abort!( - ident, - "cannot derive `{}` from Cargo.toml\n\n= note: {note}\n\n= help: {help}\n\n", - ident, - note = format_args!("`{env_var}` environment variable is not set"), - help = format_args!("use `{ident} = \"...\"` to set {ident} manually") - ); - } - }; - - if ident == "author" { - let edited = process_author_str(&lit.value()); - lit = LitStr::new(&edited, lit.span()); - } - - Ok(Some(Method::new(ident, quote!(#lit)))) - } - - pub(crate) fn args(&self) -> &TokenStream { - &self.args - } -} - -impl ToTokens for Method { - fn to_tokens(&self, ts: &mut proc_macro2::TokenStream) { - let Method { ref name, ref args } = self; - - let tokens = quote!( .#name(#args) ); - - tokens.to_tokens(ts); - } -} - -#[derive(Clone)] -pub struct Deprecation { - pub span: Span, - pub id: &'static str, - pub version: &'static str, - pub description: String, -} - -impl Deprecation { - fn attribute(version: &'static str, old: AttrKind, new: AttrKind, span: Span) -> Self { - Self { - span, - id: "old_attribute", - version, - description: format!( - "Attribute `#[{}(...)]` has been deprecated in favor of `#[{}(...)]`", - old.as_str(), - new.as_str() - ), - } - } -} - -impl ToTokens for Deprecation { - fn to_tokens(&self, ts: &mut proc_macro2::TokenStream) { - let tokens = if cfg!(feature = "deprecated") { - let Deprecation { - span, - id, - version, - description, - } = self; - let span = *span; - let id = Ident::new(id, span); - - quote_spanned!(span=> { - #[deprecated(since = #version, note = #description)] - fn #id() {} - #id(); - }) - } else { - quote!() - }; - - tokens.to_tokens(ts); - } -} - -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()) { - let options = possible_kind - .iter() - .map(|k| format!("`#[{}({})]`", k.as_str(), attr.name)) - .collect::<Vec<_>>(); - abort!( - attr.name, - "Unknown `#[{}({})]` attribute ({} exists)", - attr.kind.as_str(), - attr.name, - options.join(", ") - ); - } - Ok(()) -} - -/// replace all `:` with `, ` when not inside the `<>` -/// -/// `"author1:author2:author3" => "author1, author2, author3"` -/// `"author1 <http://website1.com>:author2" => "author1 <http://website1.com>, author2" -fn process_author_str(author: &str) -> String { - let mut res = String::with_capacity(author.len()); - let mut inside_angle_braces = 0usize; - - for ch in author.chars() { - if inside_angle_braces > 0 && ch == '>' { - inside_angle_braces -= 1; - res.push(ch); - } else if ch == '<' { - inside_angle_braces += 1; - res.push(ch); - } else if inside_angle_braces == 0 && ch == ':' { - res.push_str(", "); - } else { - res.push(ch); - } - } - - res -} - -/// Defines the casing for the attributes long representation. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum CasingStyle { - /// Indicate word boundaries with uppercase letter, excluding the first word. - Camel, - /// Keep all letters lowercase and indicate word boundaries with hyphens. - Kebab, - /// Indicate word boundaries with uppercase letter, including the first word. - Pascal, - /// Keep all letters uppercase and indicate word boundaries with underscores. - ScreamingSnake, - /// Keep all letters lowercase and indicate word boundaries with underscores. - Snake, - /// Keep all letters lowercase and remove word boundaries. - Lower, - /// Keep all letters uppercase and remove word boundaries. - Upper, - /// Use the original attribute name defined in the code. - Verbatim, -} - -impl CasingStyle { - 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()); - - let s = match normalized.as_ref() { - "camel" | "camelcase" => cs(Camel), - "kebab" | "kebabcase" => cs(Kebab), - "pascal" | "pascalcase" => cs(Pascal), - "screamingsnake" | "screamingsnakecase" => cs(ScreamingSnake), - "snake" | "snakecase" => cs(Snake), - "lower" | "lowercase" => cs(Lower), - "upper" | "uppercase" => cs(Upper), - "verbatim" | "verbatimcase" => cs(Verbatim), - s => abort!(name, "unsupported casing: `{s}`"), - }; - Ok(s) - } -} - -#[derive(Clone)] -pub enum Name { - Derived(Ident), - Assigned(TokenStream), -} - -impl Name { - pub fn raw(self) -> TokenStream { - match self { - Name::Assigned(tokens) => tokens, - Name::Derived(ident) => { - let s = ident.unraw().to_string(); - quote_spanned!(ident.span()=> #s) - } - } - } - - pub fn translate(self, style: CasingStyle) -> TokenStream { - use CasingStyle::*; - - match self { - Name::Assigned(tokens) => tokens, - Name::Derived(ident) => { - let s = ident.unraw().to_string(); - let s = match style { - Pascal => s.to_upper_camel_case(), - Kebab => s.to_kebab_case(), - Camel => s.to_lower_camel_case(), - ScreamingSnake => s.to_shouty_snake_case(), - Snake => s.to_snake_case(), - Lower => s.to_snake_case().replace('_', ""), - Upper => s.to_shouty_snake_case().replace('_', ""), - Verbatim => s, - }; - quote_spanned!(ident.span()=> #s) - } - } - } - - pub fn translate_char(self, style: CasingStyle) -> TokenStream { - use CasingStyle::*; - - match self { - Name::Assigned(tokens) => quote!( (#tokens).chars().next().unwrap() ), - Name::Derived(ident) => { - let s = ident.unraw().to_string(); - let s = match style { - Pascal => s.to_upper_camel_case(), - Kebab => s.to_kebab_case(), - Camel => s.to_lower_camel_case(), - ScreamingSnake => s.to_shouty_snake_case(), - Snake => s.to_snake_case(), - Lower => s.to_snake_case(), - Upper => s.to_shouty_snake_case(), - Verbatim => s, - }; - - let s = s.chars().next().unwrap(); - quote_spanned!(ident.span()=> #s) - } - } - } -} diff --git a/vendor/clap_derive/src/lib.rs b/vendor/clap_derive/src/lib.rs deleted file mode 100644 index d3cae9b..0000000 --- a/vendor/clap_derive/src/lib.rs +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>, -// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and -// Ana Hobden (@hoverbear) <operator@hoverbear.org> -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. -// -// This work was derived from Structopt (https://github.com/TeXitoi/structopt) -// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the -// MIT/Apache 2.0 license. - -#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")] -#![doc = include_str!("../README.md")] -#![forbid(unsafe_code)] - -extern crate proc_macro; - -use proc_macro::TokenStream; -use syn::{parse_macro_input, DeriveInput}; -use syn::{Data, DataStruct, Fields}; - -#[macro_use] -mod macros; - -mod attr; -mod derives; -mod dummies; -mod item; -mod utils; - -/// Generates the `ValueEnum` impl. -#[proc_macro_derive(ValueEnum, attributes(clap, value))] -pub fn value_enum(input: TokenStream) -> TokenStream { - let input: DeriveInput = parse_macro_input!(input); - 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. -/// -/// This is far less verbose than defining the `clap::Command` struct manually, -/// receiving an instance of `clap::ArgMatches` from conducting parsing, and then -/// implementing a conversion code to instantiate an instance of the user -/// context struct. -#[proc_macro_derive(Parser, attributes(clap, structopt, command, arg, group))] -pub fn parser(input: TokenStream) -> TokenStream { - let input: DeriveInput = parse_macro_input!(input); - 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))] -pub fn subcommand(input: TokenStream) -> TokenStream { - let input: DeriveInput = parse_macro_input!(input); - 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))] -pub fn args(input: TokenStream) -> TokenStream { - let input: DeriveInput = parse_macro_input!(input); - 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 deleted file mode 100644 index 282048b..0000000 --- a/vendor/clap_derive/src/macros.rs +++ /dev/null @@ -1,21 +0,0 @@ -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 deleted file mode 100644 index 63c6ad1..0000000 --- a/vendor/clap_derive/src/utils/doc_comments.rs +++ /dev/null @@ -1,126 +0,0 @@ -//! The preprocessing we apply to doc comments. -//! -//! #[derive(Parser)] works in terms of "paragraphs". Paragraph is a sequence of -//! non-empty adjacent lines, delimited by sequences of blank (whitespace only) lines. - -use std::iter; - -pub fn extract_doc_comment(attrs: &[syn::Attribute]) -> Vec<String> { - // 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_map(|attr| { - // 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)) - .flat_map(|s| { - let lines = s - .split('\n') - .map(|s| { - // remove one leading space no matter what - let s = s.strip_prefix(' ').unwrap_or(s); - s.to_owned() - }) - .collect::<Vec<_>>(); - lines - }) - .collect(); - - while let Some(true) = lines.last().map(|s| is_blank(s)) { - lines.pop(); - } - - lines -} - -pub fn format_doc_comment( - lines: &[String], - preprocess: bool, - force_long: bool, -) -> (Option<String>, Option<String>) { - if let Some(first_blank) = lines.iter().position(|s| is_blank(s)) { - let (short, long) = if preprocess { - let paragraphs = split_paragraphs(lines); - let short = paragraphs[0].clone(); - let long = paragraphs.join("\n\n"); - (remove_period(short), long) - } else { - let short = lines[..first_blank].join("\n"); - let long = lines.join("\n"); - (short, long) - }; - - (Some(short), Some(long)) - } else { - let (short, long) = if preprocess { - let short = merge_lines(lines); - let long = force_long.then(|| short.clone()); - let short = remove_period(short); - (short, long) - } else { - let short = lines.join("\n"); - let long = force_long.then(|| short.clone()); - (short, long) - }; - - (Some(short), long) - } -} - -fn split_paragraphs(lines: &[String]) -> Vec<String> { - let mut last_line = 0; - iter::from_fn(|| { - let slice = &lines[last_line..]; - let start = slice.iter().position(|s| !is_blank(s)).unwrap_or(0); - - let slice = &slice[start..]; - let len = slice - .iter() - .position(|s| is_blank(s)) - .unwrap_or(slice.len()); - - last_line += start + len; - - if len != 0 { - Some(merge_lines(&slice[..len])) - } else { - None - } - }) - .collect() -} - -fn remove_period(mut s: String) -> String { - if s.ends_with('.') && !s.ends_with("..") { - s.pop(); - } - s -} - -fn is_blank(s: &str) -> bool { - s.trim().is_empty() -} - -fn merge_lines(lines: impl IntoIterator<Item = impl AsRef<str>>) -> String { - lines - .into_iter() - .map(|s| s.as_ref().trim().to_owned()) - .collect::<Vec<_>>() - .join(" ") -} diff --git a/vendor/clap_derive/src/utils/error.rs b/vendor/clap_derive/src/utils/error.rs deleted file mode 100644 index 276e349..0000000 --- a/vendor/clap_derive/src/utils/error.rs +++ /dev/null @@ -1,22 +0,0 @@ -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 deleted file mode 100644 index 13e6e71..0000000 --- a/vendor/clap_derive/src/utils/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -pub mod error; - -mod doc_comments; -mod spanned; -mod ty; - -pub use doc_comments::extract_doc_comment; -pub use doc_comments::format_doc_comment; - -pub use self::{ - spanned::Sp, - ty::{inner_type, is_simple_ty, sub_type, subty_if_name, Ty}, -}; diff --git a/vendor/clap_derive/src/utils/spanned.rs b/vendor/clap_derive/src/utils/spanned.rs deleted file mode 100644 index 339a654..0000000 --- a/vendor/clap_derive/src/utils/spanned.rs +++ /dev/null @@ -1,89 +0,0 @@ -use proc_macro2::{Ident, Span, TokenStream}; -use quote::ToTokens; -use syn::LitStr; - -use std::ops::{Deref, DerefMut}; - -/// An entity with a span attached. -#[derive(Debug, Copy, Clone)] -pub struct Sp<T> { - val: T, - span: Span, -} - -impl<T> Sp<T> { - pub fn new(val: T, span: Span) -> Self { - Sp { val, span } - } - - pub fn get(&self) -> &T { - &self.val - } - - pub fn span(&self) -> Span { - self.span - } -} - -impl<T> Deref for Sp<T> { - type Target = T; - - fn deref(&self) -> &T { - &self.val - } -} - -impl<T> DerefMut for Sp<T> { - fn deref_mut(&mut self) -> &mut T { - &mut self.val - } -} - -impl From<Ident> for Sp<String> { - fn from(ident: Ident) -> Self { - Sp { - val: ident.to_string(), - span: ident.span(), - } - } -} - -impl From<LitStr> for Sp<String> { - fn from(lit: LitStr) -> Self { - Sp { - val: lit.value(), - span: lit.span(), - } - } -} - -impl<'a> From<Sp<&'a str>> for Sp<String> { - fn from(sp: Sp<&'a str>) -> Self { - Sp::new(sp.val.into(), sp.span) - } -} - -impl<U, T: PartialEq<U>> PartialEq<U> for Sp<T> { - fn eq(&self, other: &U) -> bool { - self.val == *other - } -} - -impl<T: AsRef<str>> AsRef<str> for Sp<T> { - fn as_ref(&self) -> &str { - self.val.as_ref() - } -} - -impl<T: ToTokens> ToTokens for Sp<T> { - fn to_tokens(&self, stream: &mut TokenStream) { - // this is the simplest way out of correct ones to change span on - // arbitrary token tree I could come up with - let tt = self.val.to_token_stream().into_iter().map(|mut tt| { - tt.set_span(self.span); - tt - }); - - stream.extend(tt); - } -} diff --git a/vendor/clap_derive/src/utils/ty.rs b/vendor/clap_derive/src/utils/ty.rs deleted file mode 100644 index 9349bc2..0000000 --- a/vendor/clap_derive/src/utils/ty.rs +++ /dev/null @@ -1,165 +0,0 @@ -//! Special types handling - -use super::spanned::Sp; - -use syn::{ - spanned::Spanned, GenericArgument, Path, PathArguments, PathArguments::AngleBracketed, - PathSegment, Type, TypePath, -}; - -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum Ty { - Unit, - Vec, - VecVec, - Option, - OptionOption, - OptionVec, - OptionVecVec, - Other, -} - -impl Ty { - pub fn from_syn_ty(ty: &syn::Type) -> Sp<Self> { - use self::Ty::*; - let t = |kind| Sp::new(kind, ty.span()); - - if is_unit_ty(ty) { - t(Unit) - } else if let Some(vt) = get_vec_ty(ty, Vec, VecVec) { - t(vt) - } else if let Some(subty) = subty_if_name(ty, "Option") { - if is_generic_ty(subty, "Option") { - t(OptionOption) - } else if let Some(vt) = get_vec_ty(subty, OptionVec, OptionVecVec) { - t(vt) - } else { - t(Option) - } - } else { - t(Other) - } - } - - pub fn as_str(&self) -> &'static str { - match self { - Self::Unit => "()", - Self::Vec => "Vec<T>", - Self::Option => "Option<T>", - Self::OptionOption => "Option<Option<T>>", - Self::OptionVec => "Option<Vec<T>>", - Self::VecVec => "Vec<Vec<T>>", - Self::OptionVecVec => "Option<Vec<Vec<T>>>", - Self::Other => "...other...", - } - } -} - -pub fn inner_type(field_ty: &syn::Type) -> &syn::Type { - let ty = Ty::from_syn_ty(field_ty); - match *ty { - Ty::Vec | Ty::Option => sub_type(field_ty).unwrap_or(field_ty), - Ty::OptionOption | Ty::OptionVec | Ty::VecVec => { - sub_type(field_ty).and_then(sub_type).unwrap_or(field_ty) - } - Ty::OptionVecVec => sub_type(field_ty) - .and_then(sub_type) - .and_then(sub_type) - .unwrap_or(field_ty), - _ => field_ty, - } -} - -pub fn sub_type(ty: &syn::Type) -> Option<&syn::Type> { - subty_if(ty, |_| true) -} - -fn only_last_segment(mut ty: &syn::Type) -> Option<&PathSegment> { - while let syn::Type::Group(syn::TypeGroup { elem, .. }) = ty { - ty = elem; - } - match ty { - Type::Path(TypePath { - qself: None, - path: - Path { - leading_colon: None, - segments, - }, - }) => only_one(segments.iter()), - - _ => None, - } -} - -fn subty_if<F>(ty: &syn::Type, f: F) -> Option<&syn::Type> -where - F: FnOnce(&PathSegment) -> bool, -{ - only_last_segment(ty) - .filter(|segment| f(segment)) - .and_then(|segment| { - if let AngleBracketed(args) = &segment.arguments { - only_one(args.args.iter()).and_then(|genneric| { - if let GenericArgument::Type(ty) = genneric { - Some(ty) - } else { - None - } - }) - } else { - None - } - }) -} - -pub fn subty_if_name<'a>(ty: &'a syn::Type, name: &str) -> Option<&'a syn::Type> { - subty_if(ty, |seg| seg.ident == name) -} - -pub fn is_simple_ty(ty: &syn::Type, name: &str) -> bool { - only_last_segment(ty) - .map(|segment| { - if let PathArguments::None = segment.arguments { - segment.ident == name - } else { - false - } - }) - .unwrap_or(false) -} - -fn is_generic_ty(ty: &syn::Type, name: &str) -> bool { - subty_if_name(ty, name).is_some() -} - -fn is_unit_ty(ty: &syn::Type) -> bool { - if let syn::Type::Tuple(tuple) = ty { - tuple.elems.is_empty() - } else { - false - } -} - -fn only_one<I, T>(mut iter: I) -> Option<T> -where - I: Iterator<Item = T>, -{ - iter.next().filter(|_| iter.next().is_none()) -} - -#[cfg(feature = "unstable-v5")] -fn get_vec_ty(ty: &Type, vec_ty: Ty, vecvec_ty: Ty) -> Option<Ty> { - subty_if_name(ty, "Vec").map(|subty| { - if is_generic_ty(subty, "Vec") { - vecvec_ty - } else { - vec_ty - } - }) -} - -#[cfg(not(feature = "unstable-v5"))] -fn get_vec_ty(ty: &Type, vec_ty: Ty, _vecvec_ty: Ty) -> Option<Ty> { - is_generic_ty(ty, "Vec").then_some(vec_ty) -} |