From 218caa410aa38c29984be31a5229b9fa717560ee Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:13 +0200 Subject: Merging upstream version 1.68.2+dfsg1. Signed-off-by: Daniel Baumann --- vendor/clap_derive-3.2.18/src/derives/args.rs | 796 +++++++++++++++++++++ vendor/clap_derive-3.2.18/src/derives/into_app.rs | 119 +++ vendor/clap_derive-3.2.18/src/derives/mod.rs | 23 + vendor/clap_derive-3.2.18/src/derives/parser.rs | 95 +++ .../clap_derive-3.2.18/src/derives/subcommand.rs | 678 ++++++++++++++++++ .../clap_derive-3.2.18/src/derives/value_enum.rs | 124 ++++ 6 files changed, 1835 insertions(+) create mode 100644 vendor/clap_derive-3.2.18/src/derives/args.rs create mode 100644 vendor/clap_derive-3.2.18/src/derives/into_app.rs create mode 100644 vendor/clap_derive-3.2.18/src/derives/mod.rs create mode 100644 vendor/clap_derive-3.2.18/src/derives/parser.rs create mode 100644 vendor/clap_derive-3.2.18/src/derives/subcommand.rs create mode 100644 vendor/clap_derive-3.2.18/src/derives/value_enum.rs (limited to 'vendor/clap_derive-3.2.18/src/derives') diff --git a/vendor/clap_derive-3.2.18/src/derives/args.rs b/vendor/clap_derive-3.2.18/src/derives/args.rs new file mode 100644 index 000000000..4195a0810 --- /dev/null +++ b/vendor/clap_derive-3.2.18/src/derives/args.rs @@ -0,0 +1,796 @@ +// Copyright 2018 Guillaume Pinot (@TeXitoi) , +// Kevin Knapp (@kbknapp) , and +// Ana Hobden (@hoverbear) +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , 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 crate::{ + attrs::{Attrs, Kind, Name, ParserKind, DEFAULT_CASING, DEFAULT_ENV_CASING}, + dummies, + utils::{inner_type, is_simple_ty, sub_type, Sp, Ty}, +}; + +use proc_macro2::{Ident, Span, TokenStream}; +use proc_macro_error::{abort, abort_call_site}; +use quote::{format_ident, quote, quote_spanned}; +use syn::{ + punctuated::Punctuated, spanned::Spanned, token::Comma, Attribute, Data, DataStruct, + DeriveInput, Field, Fields, Generics, Type, +}; + +pub fn derive_args(input: &DeriveInput) -> TokenStream { + let ident = &input.ident; + + dummies::args(ident); + + match input.data { + Data::Struct(DataStruct { + fields: Fields::Named(ref fields), + .. + }) => gen_for_struct(ident, &input.generics, &fields.named, &input.attrs), + Data::Struct(DataStruct { + fields: Fields::Unit, + .. + }) => gen_for_struct( + ident, + &input.generics, + &Punctuated::::new(), + &input.attrs, + ), + _ => abort_call_site!("`#[derive(Args)]` only supports non-tuple structs"), + } +} + +pub fn gen_for_struct( + struct_name: &Ident, + generics: &Generics, + fields: &Punctuated, + attrs: &[Attribute], +) -> TokenStream { + let from_arg_matches = gen_from_arg_matches_for_struct(struct_name, generics, fields, attrs); + + let attrs = Attrs::from_struct( + Span::call_site(), + attrs, + Name::Derived(struct_name.clone()), + Sp::call_site(DEFAULT_CASING), + Sp::call_site(DEFAULT_ENV_CASING), + ); + let app_var = Ident::new("__clap_app", Span::call_site()); + let augmentation = gen_augment(fields, &app_var, &attrs, false); + let augmentation_update = gen_augment(fields, &app_var, &attrs, true); + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + #from_arg_matches + + #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] + #[allow( + clippy::style, + clippy::complexity, + clippy::pedantic, + clippy::restriction, + clippy::perf, + clippy::deprecated, + clippy::nursery, + clippy::cargo, + clippy::suspicious_else_formatting, + )] + #[deny(clippy::correctness)] + impl #impl_generics clap::Args for #struct_name #ty_generics #where_clause { + fn augment_args<'b>(#app_var: clap::Command<'b>) -> clap::Command<'b> { + #augmentation + } + fn augment_args_for_update<'b>(#app_var: clap::Command<'b>) -> clap::Command<'b> { + #augmentation_update + } + } + } +} + +pub fn gen_from_arg_matches_for_struct( + struct_name: &Ident, + generics: &Generics, + fields: &Punctuated, + attrs: &[Attribute], +) -> TokenStream { + let attrs = Attrs::from_struct( + Span::call_site(), + attrs, + Name::Derived(struct_name.clone()), + Sp::call_site(DEFAULT_CASING), + Sp::call_site(DEFAULT_ENV_CASING), + ); + + let constructor = gen_constructor(fields, &attrs); + let updater = gen_updater(fields, &attrs, true); + let raw_deprecated = raw_deprecated(); + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] + #[allow( + clippy::style, + clippy::complexity, + clippy::pedantic, + clippy::restriction, + clippy::perf, + clippy::deprecated, + clippy::nursery, + clippy::cargo, + clippy::suspicious_else_formatting, + )] + #[deny(clippy::correctness)] + impl #impl_generics clap::FromArgMatches for #struct_name #ty_generics #where_clause { + fn from_arg_matches(__clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result { + Self::from_arg_matches_mut(&mut __clap_arg_matches.clone()) + } + + fn from_arg_matches_mut(__clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result { + #raw_deprecated + let v = #struct_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(()) + } + } + } +} + +/// Generate a block of code to add arguments/subcommands corresponding to +/// the `fields` to an cmd. +pub fn gen_augment( + fields: &Punctuated, + app_var: &Ident, + parent_attribute: &Attrs, + override_required: bool, +) -> TokenStream { + let mut subcmds = fields.iter().filter_map(|field| { + let attrs = Attrs::from_field( + field, + parent_attribute.casing(), + parent_attribute.env_casing(), + ); + let kind = attrs.kind(); + if let Kind::Subcommand(ty) = &*kind { + let subcmd_type = match (**ty, sub_type(&field.ty)) { + (Ty::Option, Some(sub_type)) => sub_type, + _ => &field.ty, + }; + let required = if **ty == Ty::Option { + quote!() + } else { + quote_spanned! { kind.span()=> + #[allow(deprecated)] + let #app_var = #app_var.setting( + clap::AppSettings::SubcommandRequiredElseHelp + ); + } + }; + + let span = field.span(); + let ts = if override_required { + quote! { + let #app_var = <#subcmd_type as clap::Subcommand>::augment_subcommands_for_update( #app_var ); + } + } else{ + quote! { + let #app_var = <#subcmd_type as clap::Subcommand>::augment_subcommands( #app_var ); + #required + } + }; + Some((span, ts)) + } else { + None + } + }); + let subcmd = subcmds.next().map(|(_, ts)| ts); + if let Some((span, _)) = subcmds.next() { + abort!( + span, + "multiple subcommand sets are not allowed, that's the second" + ); + } + + let args = fields.iter().filter_map(|field| { + let attrs = Attrs::from_field( + field, + parent_attribute.casing(), + parent_attribute.env_casing(), + ); + let kind = attrs.kind(); + match &*kind { + Kind::Subcommand(_) + | Kind::Skip(_) + | Kind::FromGlobal(_) + | Kind::ExternalSubcommand => None, + Kind::Flatten => { + let ty = &field.ty; + let old_heading_var = format_ident!("__clap_old_heading"); + let next_help_heading = attrs.next_help_heading(); + let next_display_order = attrs.next_display_order(); + if override_required { + Some(quote_spanned! { kind.span()=> + let #old_heading_var = #app_var.get_next_help_heading(); + let #app_var = #app_var #next_help_heading #next_display_order; + let #app_var = <#ty as clap::Args>::augment_args_for_update(#app_var); + let #app_var = #app_var.next_help_heading(#old_heading_var); + }) + } else { + Some(quote_spanned! { kind.span()=> + let #old_heading_var = #app_var.get_next_help_heading(); + let #app_var = #app_var #next_help_heading #next_display_order; + let #app_var = <#ty as clap::Args>::augment_args(#app_var); + let #app_var = #app_var.next_help_heading(#old_heading_var); + }) + } + } + Kind::Arg(ty) => { + let convert_type = inner_type(&field.ty); + + let parser = attrs.parser(&field.ty); + + let value_parser = attrs.value_parser(&field.ty); + let action = attrs.action(&field.ty); + let func = &parser.func; + + let mut occurrences = false; + let mut flag = false; + let validator = match *parser.kind { + _ if attrs.ignore_parser() || attrs.is_enum() => quote!(), + ParserKind::TryFromStr => quote_spanned! { func.span()=> + .validator(|s| { + #func(s) + .map(|_: #convert_type| ()) + }) + }, + ParserKind::TryFromOsStr => quote_spanned! { func.span()=> + .validator_os(|s| #func(s).map(|_: #convert_type| ())) + }, + ParserKind::FromStr | ParserKind::FromOsStr => quote!(), + ParserKind::FromFlag => { + flag = true; + quote!() + } + ParserKind::FromOccurrences => { + occurrences = true; + quote!() + } + }; + let parse_deprecation = match *parser.kind { + _ if !attrs.explicit_parser() || cfg!(not(feature = "deprecated")) => quote!(), + ParserKind::FromStr => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]`")] + fn parse_from_str() { + } + parse_from_str(); + }, + ParserKind::TryFromStr => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]`")] + fn parse_try_from_str() { + } + parse_try_from_str(); + }, + ParserKind::FromOsStr => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser)]` for `PathBuf` or `#[clap(value_parser = ...)]` with a custom `TypedValueParser`")] + fn parse_from_os_str() { + } + parse_from_os_str(); + }, + ParserKind::TryFromOsStr => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(value_parser = ...)]` with a custom `TypedValueParser`")] + fn parse_try_from_os_str() { + } + parse_try_from_os_str(); + }, + ParserKind::FromFlag => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(action = ArgAction::SetTrue)]`")] + fn parse_from_flag() { + } + parse_from_flag(); + }, + ParserKind::FromOccurrences => quote_spanned! { func.span()=> + #[deprecated(since = "3.2.0", note = "Replaced with `#[clap(action = ArgAction::Count)]` with a field type of `u8`")] + fn parse_from_occurrences() { + } + parse_from_occurrences(); + }, + }; + + let value_name = attrs.value_name(); + let possible_values = if attrs.is_enum() && !attrs.ignore_parser() { + gen_value_enum_possible_values(convert_type) + } else { + quote!() + }; + + let implicit_methods = match **ty { + Ty::Option => { + quote_spanned! { ty.span()=> + .takes_value(true) + .value_name(#value_name) + #possible_values + #validator + #value_parser + #action + } + } + + Ty::OptionOption => quote_spanned! { ty.span()=> + .takes_value(true) + .value_name(#value_name) + .min_values(0) + .max_values(1) + .multiple_values(false) + #possible_values + #validator + #value_parser + #action + }, + + Ty::OptionVec => { + if attrs.ignore_parser() { + if attrs.is_positional() { + quote_spanned! { ty.span()=> + .takes_value(true) + .value_name(#value_name) + .multiple_values(true) // action won't be sufficient for getting multiple + #possible_values + #validator + #value_parser + #action + } + } else { + quote_spanned! { ty.span()=> + .takes_value(true) + .value_name(#value_name) + #possible_values + #validator + #value_parser + #action + } + } + } else { + quote_spanned! { ty.span()=> + .takes_value(true) + .value_name(#value_name) + .multiple_occurrences(true) + #possible_values + #validator + #value_parser + #action + } + } + } + + Ty::Vec => { + if attrs.ignore_parser() { + if attrs.is_positional() { + quote_spanned! { ty.span()=> + .takes_value(true) + .value_name(#value_name) + .multiple_values(true) // action won't be sufficient for getting multiple + #possible_values + #validator + #value_parser + #action + } + } else { + quote_spanned! { ty.span()=> + .takes_value(true) + .value_name(#value_name) + #possible_values + #validator + #value_parser + #action + } + } + } else { + quote_spanned! { ty.span()=> + .takes_value(true) + .value_name(#value_name) + .multiple_occurrences(true) + #possible_values + #validator + #value_parser + #action + } + } + } + + Ty::Other if occurrences => quote_spanned! { ty.span()=> + .multiple_occurrences(true) + }, + + Ty::Other if flag => quote_spanned! { ty.span()=> + .takes_value(false) + }, + + Ty::Other => { + let required = attrs.find_default_method().is_none() && !override_required; + // `ArgAction::takes_values` is assuming `ArgAction::default_value` will be + // set though that won't always be true but this should be good enough, + // otherwise we'll report an "arg required" error when unwrapping. + let action_value = action.args(); + quote_spanned! { ty.span()=> + .takes_value(true) + .value_name(#value_name) + .required(#required && #action_value.takes_values()) + #possible_values + #validator + #value_parser + #action + } + } + }; + + let id = attrs.id(); + let explicit_methods = attrs.field_methods(true); + + Some(quote_spanned! { field.span()=> + let #app_var = #app_var.arg({ + #parse_deprecation + + #[allow(deprecated)] + let arg = clap::Arg::new(#id) + #implicit_methods; + + let arg = arg + #explicit_methods; + arg + }); + }) + } + } + }); + + let initial_app_methods = parent_attribute.initial_top_level_methods(); + let final_app_methods = parent_attribute.final_top_level_methods(); + quote! {{ + let #app_var = #app_var #initial_app_methods; + #( #args )* + #subcmd + #app_var #final_app_methods + }} +} + +fn gen_value_enum_possible_values(ty: &Type) -> TokenStream { + quote_spanned! { ty.span()=> + .possible_values(<#ty as clap::ValueEnum>::value_variants().iter().filter_map(clap::ValueEnum::to_possible_value)) + } +} + +pub fn gen_constructor(fields: &Punctuated, parent_attribute: &Attrs) -> TokenStream { + let fields = fields.iter().map(|field| { + let attrs = Attrs::from_field( + field, + parent_attribute.casing(), + parent_attribute.env_casing(), + ); + let field_name = field.ident.as_ref().unwrap(); + let kind = attrs.kind(); + let arg_matches = format_ident!("__clap_arg_matches"); + match &*kind { + Kind::ExternalSubcommand => { + abort! { kind.span(), + "`external_subcommand` can be used only on enum variants" + } + } + 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 + } + } + } + }, + _ => { + quote_spanned! { kind.span()=> + #field_name: { + <#subcmd_type as clap::FromArgMatches>::from_arg_matches_mut(#arg_matches)? + } + } + }, + } + } + + Kind::Flatten => quote_spanned! { kind.span()=> + #field_name: clap::FromArgMatches::from_arg_matches_mut(#arg_matches)? + }, + + Kind::Skip(val) => match val { + None => quote_spanned!(kind.span()=> #field_name: Default::default()), + Some(val) => quote_spanned!(kind.span()=> #field_name: (#val).into()), + }, + + Kind::Arg(ty) | Kind::FromGlobal(ty) => { + gen_parsers(&attrs, ty, field_name, field, None) + } + } + }); + + quote! {{ + #( #fields ),* + }} +} + +pub fn gen_updater( + fields: &Punctuated, + parent_attribute: &Attrs, + use_self: bool, +) -> TokenStream { + let fields = fields.iter().map(|field| { + let attrs = Attrs::from_field( + field, + parent_attribute.casing(), + parent_attribute.env_casing(), + ); + let field_name = field.ident.as_ref().unwrap(); + let kind = attrs.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"); + + match &*kind { + Kind::ExternalSubcommand => { + abort! { kind.span(), + "`external_subcommand` can be used only on enum variants" + } + } + 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 => quote_spanned! { kind.span()=> { + #access + clap::FromArgMatches::update_from_arg_matches_mut(#field_name, #arg_matches)?; + } + }, + + Kind::Skip(_) => quote!(), + + Kind::Arg(ty) | Kind::FromGlobal(ty) => gen_parsers(&attrs, ty, field_name, field, Some(&access)), + } + }); + + quote! { + #( #fields )* + } +} + +fn gen_parsers( + attrs: &Attrs, + ty: &Sp, + field_name: &Ident, + field: &Field, + update: Option<&TokenStream>, +) -> TokenStream { + use self::ParserKind::*; + + let parser = attrs.parser(&field.ty); + let func = &parser.func; + let span = parser.kind.span(); + let convert_type = inner_type(&field.ty); + let id = attrs.id(); + let mut flag = false; + let mut occurrences = false; + let (get_one, get_many, deref, mut parse) = match *parser.kind { + _ if attrs.ignore_parser() => ( + quote_spanned!(span=> remove_one::<#convert_type>), + quote_spanned!(span=> remove_many::<#convert_type>), + quote!(|s| s), + quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(s)), + ), + FromOccurrences => { + occurrences = true; + ( + quote_spanned!(span=> occurrences_of), + quote!(), + quote!(|s| ::std::ops::Deref::deref(s)), + func.clone(), + ) + } + FromFlag => { + flag = true; + ( + quote!(), + quote!(), + quote!(|s| ::std::ops::Deref::deref(s)), + func.clone(), + ) + } + FromStr => ( + quote_spanned!(span=> get_one::), + quote_spanned!(span=> get_many::), + quote!(|s| ::std::ops::Deref::deref(s)), + quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(#func(s))), + ), + TryFromStr => ( + quote_spanned!(span=> get_one::), + quote_spanned!(span=> get_many::), + quote!(|s| ::std::ops::Deref::deref(s)), + quote_spanned!(func.span()=> |s| #func(s).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))), + ), + FromOsStr => ( + quote_spanned!(span=> get_one::<::std::ffi::OsString>), + quote_spanned!(span=> get_many::<::std::ffi::OsString>), + quote!(|s| ::std::ops::Deref::deref(s)), + quote_spanned!(func.span()=> |s| ::std::result::Result::Ok::<_, clap::Error>(#func(s))), + ), + TryFromOsStr => ( + quote_spanned!(span=> get_one::<::std::ffi::OsString>), + quote_spanned!(span=> get_many::<::std::ffi::OsString>), + quote!(|s| ::std::ops::Deref::deref(s)), + quote_spanned!(func.span()=> |s| #func(s).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err)))), + ), + }; + if attrs.is_enum() && !attrs.ignore_parser() { + let ci = attrs.ignore_case(); + + parse = quote_spanned! { convert_type.span()=> + |s| <#convert_type as clap::ValueEnum>::from_str(s, #ci).map_err(|err| clap::Error::raw(clap::ErrorKind::ValueValidation, format!("Invalid value for {}: {}", #id, err))) + } + } + + // 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::Option => { + quote_spanned! { ty.span()=> + #arg_matches.#get_one(#id) + .map(#deref) + .map(#parse) + .transpose()? + } + } + + Ty::OptionOption => quote_spanned! { ty.span()=> + if #arg_matches.contains_id(#id) { + Some( + #arg_matches.#get_one(#id) + .map(#deref) + .map(#parse).transpose()? + ) + } else { + None + } + }, + + Ty::OptionVec => quote_spanned! { ty.span()=> + if #arg_matches.contains_id(#id) { + Some(#arg_matches.#get_many(#id) + .map(|v| v.map(#deref).map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result, clap::Error>>()) + .transpose()? + .unwrap_or_else(Vec::new)) + } else { + None + } + }, + + Ty::Vec => { + quote_spanned! { ty.span()=> + #arg_matches.#get_many(#id) + .map(|v| v.map(#deref).map::<::std::result::Result<#convert_type, clap::Error>, _>(#parse).collect::<::std::result::Result, clap::Error>>()) + .transpose()? + .unwrap_or_else(Vec::new) + } + } + + Ty::Other if occurrences => quote_spanned! { ty.span()=> + #parse( + #arg_matches.#get_one(#id) + ) + }, + + Ty::Other if flag => { + if update.is_some() && is_simple_ty(&field.ty, "bool") { + quote_spanned! { ty.span()=> + *#field_name || #arg_matches.is_present(#id) + } + } else { + quote_spanned! { ty.span()=> + #parse(#arg_matches.is_present(#id)) + } + } + } + + Ty::Other => { + quote_spanned! { ty.span()=> + #arg_matches.#get_one(#id) + .map(#deref) + .ok_or_else(|| clap::Error::raw(clap::ErrorKind::MissingRequiredArgument, format!("The following required argument was not provided: {}", #id))) + .and_then(#parse)? + } + } + }; + + 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 ) + } +} + +#[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` + + } +} diff --git a/vendor/clap_derive-3.2.18/src/derives/into_app.rs b/vendor/clap_derive-3.2.18/src/derives/into_app.rs new file mode 100644 index 000000000..319735753 --- /dev/null +++ b/vendor/clap_derive-3.2.18/src/derives/into_app.rs @@ -0,0 +1,119 @@ +// Copyright 2018 Guillaume Pinot (@TeXitoi) , +// Kevin Knapp (@kbknapp) , and +// Ana Hobden (@hoverbear) +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , 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 proc_macro2::{Span, TokenStream}; +use quote::quote; +use syn::{Attribute, Generics, Ident}; + +use crate::{ + attrs::{Attrs, Name, DEFAULT_CASING, DEFAULT_ENV_CASING}, + utils::Sp, +}; + +pub fn gen_for_struct( + struct_name: &Ident, + generics: &Generics, + attrs: &[Attribute], +) -> TokenStream { + let app_name = env::var("CARGO_PKG_NAME").ok().unwrap_or_default(); + + let attrs = Attrs::from_struct( + Span::call_site(), + attrs, + Name::Assigned(quote!(#app_name)), + Sp::call_site(DEFAULT_CASING), + Sp::call_site(DEFAULT_ENV_CASING), + ); + let name = attrs.cased_name(); + let app_var = Ident::new("__clap_app", Span::call_site()); + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let tokens = quote! { + #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] + #[allow( + clippy::style, + clippy::complexity, + clippy::pedantic, + clippy::restriction, + clippy::perf, + clippy::deprecated, + clippy::nursery, + clippy::cargo, + clippy::suspicious_else_formatting, + )] + #[deny(clippy::correctness)] + #[allow(deprecated)] + impl #impl_generics clap::CommandFactory for #struct_name #ty_generics #where_clause { + fn into_app<'b>() -> clap::Command<'b> { + let #app_var = clap::Command::new(#name); + ::augment_args(#app_var) + } + + fn into_app_for_update<'b>() -> clap::Command<'b> { + let #app_var = clap::Command::new(#name); + ::augment_args_for_update(#app_var) + } + } + }; + + tokens +} + +pub fn gen_for_enum(enum_name: &Ident, generics: &Generics, attrs: &[Attribute]) -> TokenStream { + let app_name = env::var("CARGO_PKG_NAME").ok().unwrap_or_default(); + + let attrs = Attrs::from_struct( + Span::call_site(), + attrs, + Name::Assigned(quote!(#app_name)), + Sp::call_site(DEFAULT_CASING), + Sp::call_site(DEFAULT_ENV_CASING), + ); + let name = attrs.cased_name(); + let app_var = Ident::new("__clap_app", Span::call_site()); + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] + #[allow( + clippy::style, + clippy::complexity, + clippy::pedantic, + clippy::restriction, + clippy::perf, + clippy::deprecated, + clippy::nursery, + clippy::cargo, + clippy::suspicious_else_formatting, + )] + #[deny(clippy::correctness)] + impl #impl_generics clap::CommandFactory for #enum_name #ty_generics #where_clause { + fn into_app<'b>() -> clap::Command<'b> { + #[allow(deprecated)] + let #app_var = clap::Command::new(#name) + .setting(clap::AppSettings::SubcommandRequiredElseHelp); + ::augment_subcommands(#app_var) + } + + fn into_app_for_update<'b>() -> clap::Command<'b> { + let #app_var = clap::Command::new(#name); + ::augment_subcommands_for_update(#app_var) + } + } + } +} diff --git a/vendor/clap_derive-3.2.18/src/derives/mod.rs b/vendor/clap_derive-3.2.18/src/derives/mod.rs new file mode 100644 index 000000000..3deeb91f9 --- /dev/null +++ b/vendor/clap_derive-3.2.18/src/derives/mod.rs @@ -0,0 +1,23 @@ +// Copyright 2018 Guillaume Pinot (@TeXitoi) , +// Kevin Knapp (@kbknapp) , and +// Ana Hobden (@hoverbear) +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , 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-3.2.18/src/derives/parser.rs b/vendor/clap_derive-3.2.18/src/derives/parser.rs new file mode 100644 index 000000000..621430f31 --- /dev/null +++ b/vendor/clap_derive-3.2.18/src/derives/parser.rs @@ -0,0 +1,95 @@ +// Copyright 2018 Guillaume Pinot (@TeXitoi) , +// Kevin Knapp (@kbknapp) , and +// Ana Hobden (@hoverbear) +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , 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 crate::{ + derives::{args, into_app, subcommand}, + dummies, +}; + +use proc_macro2::TokenStream; +use proc_macro_error::abort_call_site; +use quote::quote; +use syn::{ + self, punctuated::Punctuated, token::Comma, Attribute, Data, DataEnum, DataStruct, DeriveInput, + Field, Fields, Generics, Ident, +}; + +pub fn derive_parser(input: &DeriveInput) -> TokenStream { + let ident = &input.ident; + + match input.data { + Data::Struct(DataStruct { + fields: Fields::Named(ref fields), + .. + }) => { + dummies::parser_struct(ident); + gen_for_struct(ident, &input.generics, &fields.named, &input.attrs) + } + Data::Struct(DataStruct { + fields: Fields::Unit, + .. + }) => { + dummies::parser_struct(ident); + gen_for_struct( + ident, + &input.generics, + &Punctuated::::new(), + &input.attrs, + ) + } + Data::Enum(ref e) => { + dummies::parser_enum(ident); + gen_for_enum(ident, &input.generics, &input.attrs, e) + } + _ => abort_call_site!("`#[derive(Parser)]` only supports non-tuple structs and enums"), + } +} + +fn gen_for_struct( + name: &Ident, + generics: &Generics, + fields: &Punctuated, + attrs: &[Attribute], +) -> TokenStream { + let into_app = into_app::gen_for_struct(name, generics, attrs); + let args = args::gen_for_struct(name, generics, fields, attrs); + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + impl #impl_generics clap::Parser for #name #ty_generics #where_clause {} + + #into_app + #args + } +} + +fn gen_for_enum( + name: &Ident, + generics: &Generics, + attrs: &[Attribute], + e: &DataEnum, +) -> TokenStream { + let into_app = into_app::gen_for_enum(name, generics, attrs); + let subcommand = subcommand::gen_for_enum(name, generics, attrs, e); + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + impl #impl_generics clap::Parser for #name #ty_generics #where_clause {} + + #into_app + #subcommand + } +} diff --git a/vendor/clap_derive-3.2.18/src/derives/subcommand.rs b/vendor/clap_derive-3.2.18/src/derives/subcommand.rs new file mode 100644 index 000000000..07bdce5ec --- /dev/null +++ b/vendor/clap_derive-3.2.18/src/derives/subcommand.rs @@ -0,0 +1,678 @@ +// Copyright 2018 Guillaume Pinot (@TeXitoi) , +// Kevin Knapp (@kbknapp) , and +// Ana Hobden (@hoverbear) +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , 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 crate::{ + attrs::{Attrs, Kind, Name, DEFAULT_CASING, DEFAULT_ENV_CASING}, + derives::args, + dummies, + utils::{is_simple_ty, subty_if_name, Sp}, +}; + +use proc_macro2::{Ident, Span, TokenStream}; +use proc_macro_error::{abort, abort_call_site}; +use quote::{format_ident, quote, quote_spanned}; +use syn::{ + punctuated::Punctuated, spanned::Spanned, Attribute, Data, DataEnum, DeriveInput, + FieldsUnnamed, Generics, Token, Variant, +}; + +pub fn derive_subcommand(input: &DeriveInput) -> TokenStream { + let ident = &input.ident; + + dummies::subcommand(ident); + + match input.data { + Data::Enum(ref e) => gen_for_enum(ident, &input.generics, &input.attrs, e), + _ => abort_call_site!("`#[derive(Subcommand)]` only supports enums"), + } +} + +pub fn gen_for_enum( + enum_name: &Ident, + generics: &Generics, + attrs: &[Attribute], + e: &DataEnum, +) -> TokenStream { + let from_arg_matches = gen_from_arg_matches_for_enum(enum_name, generics, attrs, e); + + let attrs = Attrs::from_struct( + Span::call_site(), + attrs, + Name::Derived(enum_name.clone()), + Sp::call_site(DEFAULT_CASING), + Sp::call_site(DEFAULT_ENV_CASING), + ); + let augmentation = gen_augment(&e.variants, &attrs, false); + let augmentation_update = gen_augment(&e.variants, &attrs, true); + let has_subcommand = gen_has_subcommand(&e.variants, &attrs); + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + #from_arg_matches + + #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] + #[allow( + clippy::style, + clippy::complexity, + clippy::pedantic, + clippy::restriction, + clippy::perf, + clippy::deprecated, + clippy::nursery, + clippy::cargo, + clippy::suspicious_else_formatting, + )] + #[deny(clippy::correctness)] + impl #impl_generics clap::Subcommand for #enum_name #ty_generics #where_clause { + fn augment_subcommands <'b>(__clap_app: clap::Command<'b>) -> clap::Command<'b> { + #augmentation + } + fn augment_subcommands_for_update <'b>(__clap_app: clap::Command<'b>) -> clap::Command<'b> { + #augmentation_update + } + fn has_subcommand(__clap_name: &str) -> bool { + #has_subcommand + } + } + } +} + +fn gen_from_arg_matches_for_enum( + name: &Ident, + generics: &Generics, + attrs: &[Attribute], + e: &DataEnum, +) -> TokenStream { + let attrs = Attrs::from_struct( + Span::call_site(), + attrs, + Name::Derived(name.clone()), + Sp::call_site(DEFAULT_CASING), + Sp::call_site(DEFAULT_ENV_CASING), + ); + + let from_arg_matches = gen_from_arg_matches(name, &e.variants, &attrs); + let update_from_arg_matches = gen_update_from_arg_matches(name, &e.variants, &attrs); + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + quote! { + #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] + #[allow( + clippy::style, + clippy::complexity, + clippy::pedantic, + clippy::restriction, + clippy::perf, + clippy::deprecated, + clippy::nursery, + clippy::cargo, + clippy::suspicious_else_formatting, + )] + #[deny(clippy::correctness)] + impl #impl_generics clap::FromArgMatches for #name #ty_generics #where_clause { + fn from_arg_matches(__clap_arg_matches: &clap::ArgMatches) -> ::std::result::Result { + 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 + } + } +} + +fn gen_augment( + variants: &Punctuated, + parent_attribute: &Attrs, + override_required: bool, +) -> TokenStream { + use syn::Fields::*; + + let app_var = Ident::new("__clap_app", Span::call_site()); + + let subcommands: Vec<_> = variants + .iter() + .filter_map(|variant| { + let attrs = Attrs::from_variant( + variant, + parent_attribute.casing(), + parent_attribute.env_casing(), + ); + let kind = attrs.kind(); + + match &*kind { + Kind::Skip(_) => 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` \ + or `Vec`." + ), + }; + let subcommand = match subty_if_name(ty, "Vec") { + Some(subty) => { + if is_simple_ty(subty, "OsString") { + quote_spanned! { kind.span()=> + let #app_var = #app_var.allow_external_subcommands(true).allow_invalid_utf8_for_external_subcommands(true); + } + } else { + quote_spanned! { kind.span()=> + let #app_var = #app_var.allow_external_subcommands(true); + } + } + } + + None => abort!( + ty.span(), + "The type must be `Vec<_>` \ + to be used with `external_subcommand`." + ), + }; + Some(subcommand) + } + + Kind::Flatten => match variant.fields { + Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { + let ty = &unnamed[0]; + let old_heading_var = format_ident!("__clap_old_heading"); + let next_help_heading = attrs.next_help_heading(); + let next_display_order = attrs.next_display_order(); + let subcommand = if override_required { + quote! { + let #old_heading_var = #app_var.get_next_help_heading(); + let #app_var = #app_var #next_help_heading #next_display_order; + let #app_var = <#ty as clap::Subcommand>::augment_subcommands_for_update(#app_var); + let #app_var = #app_var.next_help_heading(#old_heading_var); + } + } else { + quote! { + let #old_heading_var = #app_var.get_next_help_heading(); + let #app_var = #app_var #next_help_heading #next_display_order; + let #app_var = <#ty as clap::Subcommand>::augment_subcommands(#app_var); + let #app_var = #app_var.next_help_heading(#old_heading_var); + } + }; + Some(subcommand) + } + _ => abort!( + variant, + "`flatten` is usable only with single-typed tuple variants" + ), + }, + + Kind::Subcommand(_) => { + let subcommand_var = Ident::new("__clap_subcommand", Span::call_site()); + let arg_block = match variant.fields { + Named(_) => { + abort!(variant, "non single-typed tuple enums are not supported") + } + Unit => quote!( #subcommand_var ), + Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { + let ty = &unnamed[0]; + if override_required { + quote_spanned! { ty.span()=> + { + <#ty as clap::Subcommand>::augment_subcommands_for_update(#subcommand_var) + } + } + } else { + quote_spanned! { ty.span()=> + { + <#ty as clap::Subcommand>::augment_subcommands(#subcommand_var) + } + } + } + } + Unnamed(..) => { + abort!(variant, "non single-typed tuple enums are not supported") + } + }; + + let name = attrs.cased_name(); + let initial_app_methods = attrs.initial_top_level_methods(); + let final_from_attrs = attrs.final_top_level_methods(); + let subcommand = quote! { + let #app_var = #app_var.subcommand({ + let #subcommand_var = clap::Command::new(#name); + let #subcommand_var = #subcommand_var #initial_app_methods; + let #subcommand_var = #arg_block; + #[allow(deprecated)] + let #subcommand_var = #subcommand_var.setting(clap::AppSettings::SubcommandRequiredElseHelp); + #subcommand_var #final_from_attrs + }); + }; + Some(subcommand) + } + + _ => { + let subcommand_var = Ident::new("__clap_subcommand", Span::call_site()); + let sub_augment = match variant.fields { + Named(ref fields) => { + // Defer to `gen_augment` for adding cmd methods + args::gen_augment(&fields.named, &subcommand_var, &attrs, override_required) + } + Unit => { + let arg_block = quote!( #subcommand_var ); + let initial_app_methods = attrs.initial_top_level_methods(); + let final_from_attrs = attrs.final_top_level_methods(); + quote! { + let #subcommand_var = #subcommand_var #initial_app_methods; + let #subcommand_var = #arg_block; + #subcommand_var #final_from_attrs + } + }, + Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { + let ty = &unnamed[0]; + let arg_block = if override_required { + quote_spanned! { ty.span()=> + { + <#ty as clap::Args>::augment_args_for_update(#subcommand_var) + } + } + } else { + quote_spanned! { ty.span()=> + { + <#ty as clap::Args>::augment_args(#subcommand_var) + } + } + }; + let initial_app_methods = attrs.initial_top_level_methods(); + let final_from_attrs = attrs.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 name = attrs.cased_name(); + let subcommand = quote! { + let #app_var = #app_var.subcommand({ + let #subcommand_var = clap::Command::new(#name); + #sub_augment + }); + }; + Some(subcommand) + } + } + }) + .collect(); + + let initial_app_methods = parent_attribute.initial_top_level_methods(); + let final_app_methods = parent_attribute.final_top_level_methods(); + quote! { + let #app_var = #app_var #initial_app_methods; + #( #subcommands )*; + #app_var #final_app_methods + } +} + +fn gen_has_subcommand( + variants: &Punctuated, + parent_attribute: &Attrs, +) -> TokenStream { + use syn::Fields::*; + + let mut ext_subcmd = false; + + let (flatten_variants, variants): (Vec<_>, Vec<_>) = variants + .iter() + .filter_map(|variant| { + let attrs = Attrs::from_variant( + variant, + parent_attribute.casing(), + parent_attribute.env_casing(), + ); + + if let Kind::ExternalSubcommand = &*attrs.kind() { + ext_subcmd = true; + None + } else { + Some((variant, attrs)) + } + }) + .partition(|(_, attrs)| { + let kind = attrs.kind(); + matches!(&*kind, Kind::Flatten) + }); + + let subcommands = variants.iter().map(|(_variant, attrs)| { + let sub_name = attrs.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]; + quote! { + if <#ty as clap::Subcommand>::has_subcommand(__clap_name) { + return true; + } + } + } + _ => abort!( + variant, + "`flatten` is usable only with single-typed tuple variants" + ), + }); + + if ext_subcmd { + quote! { true } + } else { + quote! { + #( #subcommands )* + + #( #child_subcommands )else* + + false + } + } +} + +fn gen_from_arg_matches( + name: &Ident, + variants: &Punctuated, + parent_attribute: &Attrs, +) -> TokenStream { + use syn::Fields::*; + + let mut ext_subcmd = None; + + let subcommand_name_var = format_ident!("__clap_name"); + let sub_arg_matches_var = format_ident!("__clap_arg_matches"); + let (flatten_variants, variants): (Vec<_>, Vec<_>) = variants + .iter() + .filter_map(|variant| { + let attrs = Attrs::from_variant( + variant, + parent_attribute.casing(), + parent_attribute.env_casing(), + ); + + if let Kind::ExternalSubcommand = &*attrs.kind() { + if ext_subcmd.is_some() { + abort!( + attrs.kind().span(), + "Only one variant can be marked with `external_subcommand`, \ + 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` \ + or `Vec`." + ), + }; + + 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` or `Vec` \ + to be used with `external_subcommand`." + ); + } + } + + None => abort!( + ty.span(), + "The type must be either `Vec` or `Vec` \ + to be used with `external_subcommand`." + ), + }; + + ext_subcmd = Some((span, &variant.ident, str_ty)); + None + } else { + Some((variant, attrs)) + } + }) + .partition(|(_, attrs)| { + let kind = attrs.kind(); + matches!(&*kind, Kind::Flatten) + }); + + let subcommands = variants.iter().map(|(variant, attrs)| { + let sub_name = attrs.cased_name(); + let variant_name = &variant.ident; + let constructor_block = match variant.fields { + Named(ref fields) => args::gen_constructor(&fields.named, attrs), + Unit => quote!(), + Unnamed(ref fields) if fields.unnamed.len() == 1 => { + let ty = &fields.unnamed[0]; + quote!( ( <#ty as clap::FromArgMatches>::from_arg_matches_mut(__clap_arg_matches)? ) ) + } + Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident), + }; + + if cfg!(feature = "unstable-v4") { + quote! { + if #sub_name == #subcommand_name_var && !#sub_arg_matches_var.contains_id("") { + return ::std::result::Result::Ok(#name :: #variant_name #constructor_block) + } + } + } else { + quote! { + if #sub_name == #subcommand_name_var { + return ::std::result::Result::Ok(#name :: #variant_name #constructor_block) + } + } + } + }); + let child_subcommands = flatten_variants.iter().map(|(variant, _attrs)| { + let variant_name = &variant.ident; + match variant.fields { + Unnamed(ref fields) if fields.unnamed.len() == 1 => { + let ty = &fields.unnamed[0]; + quote! { + 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(#name :: #variant_name (__clap_res)); + } + } + } + _ => abort!( + variant, + "`flatten` is usable only with single-typed tuple variants" + ), + } + }); + + let wildcard = match ext_subcmd { + Some((span, var_name, str_ty)) => quote_spanned! { span=> + ::std::result::Result::Ok(#name::#var_name( + ::std::iter::once(#str_ty::from(#subcommand_name_var)) + .chain( + #sub_arg_matches_var + .remove_many::<#str_ty>("") + .into_iter().flatten() // `""` isn't present, bug in `unstable-v4` + .map(#str_ty::from) + ) + .collect::<::std::vec::Vec<_>>() + )) + }, + + None => quote! { + ::std::result::Result::Err(clap::Error::raw(clap::ErrorKind::UnrecognizedSubcommand, format!("The subcommand '{}' wasn't recognized", #subcommand_name_var))) + }, + }; + + let raw_deprecated = args::raw_deprecated(); + quote! { + fn from_arg_matches_mut(__clap_arg_matches: &mut clap::ArgMatches) -> ::std::result::Result { + #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::ErrorKind::MissingSubcommand, "A subcommand is required but one was not provided.")) + } + } + } +} + +fn gen_update_from_arg_matches( + name: &Ident, + variants: &Punctuated, + parent_attribute: &Attrs, +) -> TokenStream { + use syn::Fields::*; + + let (flatten, variants): (Vec<_>, Vec<_>) = variants + .iter() + .filter_map(|variant| { + let attrs = Attrs::from_variant( + variant, + parent_attribute.casing(), + parent_attribute.env_casing(), + ); + + match &*attrs.kind() { + // Fallback to `from_arg_matches_mut` + Kind::ExternalSubcommand => None, + _ => Some((variant, attrs)), + } + }) + .partition(|(_, attrs)| { + let kind = attrs.kind(); + matches!(&*kind, Kind::Flatten) + }); + + let subcommands = variants.iter().map(|(variant, attrs)| { + let sub_name = attrs.cased_name(); + let variant_name = &variant.ident; + let (pattern, updater) = match variant.fields { + Named(ref fields) => { + let (fields, update): (Vec<_>, Vec<_>) = fields + .named + .iter() + .map(|field| { + let attrs = Attrs::from_field( + field, + parent_attribute.casing(), + parent_attribute.env_casing(), + ); + let field_name = field.ident.as_ref().unwrap(); + ( + quote!( ref mut #field_name ), + args::gen_updater(&fields.named, &attrs, false), + ) + }) + .unzip(); + (quote!( { #( #fields, )* }), 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) + } + } + }; + + quote! { + #name :: #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 + } + } + }); + + let child_subcommands = flatten.iter().map(|(variant, _attrs)| { + let variant_name = &variant.ident; + match variant.fields { + Unnamed(ref fields) if fields.unnamed.len() == 1 => { + let ty = &fields.unnamed[0]; + quote! { + if <#ty as clap::Subcommand>::has_subcommand(__clap_name) { + if let #name :: #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" + ), + } + }); + + let raw_deprecated = args::raw_deprecated(); + 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 = ::from_arg_matches_mut(__clap_arg_matches)?; + } + } + } + ::std::result::Result::Ok(()) + } + } +} diff --git a/vendor/clap_derive-3.2.18/src/derives/value_enum.rs b/vendor/clap_derive-3.2.18/src/derives/value_enum.rs new file mode 100644 index 000000000..06d514f0e --- /dev/null +++ b/vendor/clap_derive-3.2.18/src/derives/value_enum.rs @@ -0,0 +1,124 @@ +// Copyright 2018 Guillaume Pinot (@TeXitoi) , +// Kevin Knapp (@kbknapp) , and +// Ana Hobden (@hoverbear) +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::{ + attrs::{Attrs, Kind, Name, DEFAULT_CASING, DEFAULT_ENV_CASING}, + dummies, + utils::Sp, +}; + +use proc_macro2::{Span, TokenStream}; +use proc_macro_error::{abort, abort_call_site}; +use quote::quote; +use quote::quote_spanned; +use syn::{ + punctuated::Punctuated, spanned::Spanned, token::Comma, Attribute, Data, DataEnum, DeriveInput, + Fields, Ident, Variant, +}; + +pub fn derive_value_enum(input: &DeriveInput) -> TokenStream { + let ident = &input.ident; + + dummies::value_enum(ident); + + match input.data { + Data::Enum(ref e) => gen_for_enum(ident, &input.attrs, e), + _ => abort_call_site!("`#[derive(ValueEnum)]` only supports enums"), + } +} + +pub fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> TokenStream { + let attrs = Attrs::from_struct( + Span::call_site(), + attrs, + Name::Derived(name.clone()), + Sp::call_site(DEFAULT_CASING), + Sp::call_site(DEFAULT_ENV_CASING), + ); + + let lits = lits(&e.variants, &attrs); + let value_variants = gen_value_variants(&lits); + let to_possible_value = gen_to_possible_value(&lits); + + quote! { + #[allow(dead_code, unreachable_code, unused_variables, unused_braces)] + #[allow( + clippy::style, + clippy::complexity, + clippy::pedantic, + clippy::restriction, + clippy::perf, + clippy::deprecated, + clippy::nursery, + clippy::cargo, + clippy::suspicious_else_formatting, + )] + #[deny(clippy::correctness)] + impl clap::ValueEnum for #name { + #value_variants + #to_possible_value + } + } +} + +fn lits( + variants: &Punctuated, + parent_attribute: &Attrs, +) -> Vec<(TokenStream, Ident)> { + variants + .iter() + .filter_map(|variant| { + let attrs = Attrs::from_value_enum_variant( + variant, + parent_attribute.casing(), + parent_attribute.env_casing(), + ); + if let Kind::Skip(_) = &*attrs.kind() { + None + } else { + if !matches!(variant.fields, Fields::Unit) { + abort!(variant.span(), "`#[derive(ValueEnum)]` only supports unit variants. Non-unit variants must be skipped"); + } + let fields = attrs.field_methods(false); + let name = attrs.cased_name(); + Some(( + quote_spanned! { variant.span()=> + clap::PossibleValue::new(#name) + #fields + }, + variant.ident.clone(), + )) + } + }) + .collect::>() +} + +fn gen_value_variants(lits: &[(TokenStream, Ident)]) -> TokenStream { + let lit = lits.iter().map(|l| &l.1).collect::>(); + + quote! { + fn value_variants<'a>() -> &'a [Self]{ + &[#(Self::#lit),*] + } + } +} + +fn gen_to_possible_value(lits: &[(TokenStream, Ident)]) -> TokenStream { + let (lit, variant): (Vec, Vec) = lits.iter().cloned().unzip(); + + quote! { + fn to_possible_value<'a>(&self) -> ::std::option::Option> { + match self { + #(Self::#variant => Some(#lit),)* + _ => None + } + } + } +} -- cgit v1.2.3