1use proc_macro2::TokenStream;
12use quote::quote;
13use quote::quote_spanned;
14use syn::{Data, DeriveInput, Fields, Ident, Variant, spanned::Spanned};
15
16use crate::item::{Item, Kind, Name};
17
18pub(crate) fn derive_value_enum(input: &DeriveInput) -> Result<TokenStream, syn::Error> {
19 let ident = &input.ident;
20
21 match input.data {
22 Data::Enum(ref e) => {
23 let name = Name::Derived(ident.clone());
24 let item = Item::from_value_enum(input, name)?;
25 let mut variants = Vec::new();
26 for variant in &e.variants {
27 let item =
28 Item::from_value_enum_variant(variant, item.casing(), item.env_casing())?;
29 variants.push((variant, item));
30 }
31 gen_for_enum(&item, ident, &variants)
32 }
33 _ => {
let span = proc_macro2::Span::call_site();
{
return Err({
#[allow(unused_imports)]
use crate::utils::error::*;
let msg =
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`#[derive(ValueEnum)]` only supports enums"))
});
span.EXPECTED_Span_OR_ToTokens(msg)
});
}
}abort_call_site!("`#[derive(ValueEnum)]` only supports enums"),
34 }
35}
36
37pub(crate) fn gen_for_enum(
38 item: &Item,
39 item_name: &Ident,
40 variants: &[(&Variant, Item)],
41) -> Result<TokenStream, syn::Error> {
42 if !#[allow(non_exhaustive_omitted_patterns)] match &*item.kind() {
Kind::Value => true,
_ => false,
}matches!(&*item.kind(), Kind::Value) {
43 {
return Err({
#[allow(unused_imports)]
use crate::utils::error::*;
let msg =
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` cannot be used with `#[value]`",
item.kind().name()))
});
item.kind().span().EXPECTED_Span_OR_ToTokens(msg)
});
}abort! { item.kind().span(),
44 "`{}` cannot be used with `#[value]`",
45 item.kind().name(),
46 }
47 }
48
49 let lits = lits(variants)?;
50 let value_variants = gen_value_variants(&lits);
51 let to_possible_value = gen_to_possible_value(item, &lits);
52
53 Ok({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "dead_code");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "unreachable_code");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "unused_variables");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "unused_braces");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s,
"unused_qualifications");
::quote::__private::push_comma(&mut _s);
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "style");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "complexity");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "pedantic");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "restriction");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "perf");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "deprecated");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "nursery");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "cargo");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"suspicious_else_formatting");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "almost_swapped");
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "redundant_locals");
::quote::__private::push_comma(&mut _s);
_s
});
_s
});
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "automatically_derived");
_s
});
::quote::__private::push_ident(&mut _s, "impl");
::quote::__private::push_ident(&mut _s, "clap");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ValueEnum");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&item_name, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&value_variants, &mut _s);
::quote::ToTokens::to_tokens(&to_possible_value, &mut _s);
_s
});
_s
}quote! {
54 #[allow(
55 dead_code,
56 unreachable_code,
57 unused_variables,
58 unused_braces,
59 unused_qualifications,
60 )]
61 #[allow(
62 clippy::style,
63 clippy::complexity,
64 clippy::pedantic,
65 clippy::restriction,
66 clippy::perf,
67 clippy::deprecated,
68 clippy::nursery,
69 clippy::cargo,
70 clippy::suspicious_else_formatting,
71 clippy::almost_swapped,
72 clippy::redundant_locals,
73 )]
74 #[automatically_derived]
75 impl clap::ValueEnum for #item_name {
76 #value_variants
77 #to_possible_value
78 }
79 })
80}
81
82fn lits(variants: &[(&Variant, Item)]) -> Result<Vec<(TokenStream, Ident)>, syn::Error> {
83 let mut genned = Vec::new();
84 for (variant, item) in variants {
85 if let Kind::Skip(_, _) = &*item.kind() {
86 continue;
87 }
88 if !#[allow(non_exhaustive_omitted_patterns)] match variant.fields {
Fields::Unit => true,
_ => false,
}matches!(variant.fields, Fields::Unit) {
89 {
return Err({
#[allow(unused_imports)]
use crate::utils::error::*;
let msg =
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`#[derive(ValueEnum)]` only supports unit variants. Non-unit variants must be skipped"))
});
variant.span().EXPECTED_Span_OR_ToTokens(msg)
});
};abort!(
90 variant.span(),
91 "`#[derive(ValueEnum)]` only supports unit variants. Non-unit variants must be skipped"
92 );
93 }
94 let fields = item.field_methods();
95 let deprecations = item.deprecations();
96 let name = item.cased_name();
97 genned.push((
98 {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(variant.span()).__into_span();
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::ToTokens::to_tokens(&deprecations, &mut _s);
::quote::__private::push_ident_spanned(&mut _s, _span, "clap");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "builder");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span,
"PossibleValue");
::quote::__private::push_colon2_spanned(&mut _s, _span);
::quote::__private::push_ident_spanned(&mut _s, _span, "new");
::quote::__private::push_group_spanned(&mut _s, _span,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
let _: ::quote::__private::Span =
::quote::__private::get_span(_span).__into_span();
::quote::ToTokens::to_tokens(&name, &mut _s);
_s
});
::quote::ToTokens::to_tokens(&fields, &mut _s);
_s
});
_s
}quote_spanned! { variant.span()=> {
99 #deprecations
100 clap::builder::PossibleValue::new(#name)
101 #fields
102 }},
103 variant.ident.clone(),
104 ));
105 }
106 Ok(genned)
107}
108
109fn gen_value_variants(lits: &[(TokenStream, Ident)]) -> TokenStream {
110 let lit = lits.iter().map(|l| &l.1).collect::<Vec<_>>();
111
112 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "value_variants");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'a");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'a");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "Self");
_s
});
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let mut _first = true;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut lit, i) = lit.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let lit =
match lit.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
if !_first { ::quote::__private::push_comma(&mut _s); }
_first = false;
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&lit, &mut _s);
}
}
_s
});
_s
});
_s
}quote! {
113 fn value_variants<'a>() -> &'a [Self]{
114 &[#(Self::#lit),*]
115 }
116 }
117}
118
119fn gen_to_possible_value(item: &Item, lits: &[(TokenStream, Ident)]) -> TokenStream {
120 let (lit, variant): (Vec<TokenStream>, Vec<Ident>) = lits.iter().cloned().unzip();
121
122 let deprecations = item.deprecations();
123
124 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "to_possible_value");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'a");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "clap");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "PossibleValue");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&deprecations, &mut _s);
::quote::__private::push_ident(&mut _s, "match");
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut variant, i) = variant.quote_into_iter();
let has_iter = has_iter | i;
#[allow(unused_mut)]
let (mut lit, i) = lit.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let variant =
match variant.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
let lit =
match lit.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&variant, &mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_ident(&mut _s, "Some");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&lit, &mut _s);
_s
});
::quote::__private::push_comma(&mut _s);
}
}
::quote::__private::push_underscore(&mut _s);
::quote::__private::push_fat_arrow(&mut _s);
::quote::__private::push_ident(&mut _s, "None");
_s
});
_s
});
_s
}quote! {
125 fn to_possible_value<'a>(&self) -> ::std::option::Option<clap::builder::PossibleValue> {
126 #deprecations
127 match self {
128 #(Self::#variant => Some(#lit),)*
129 _ => None
130 }
131 }
132 }
133}