1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{
4 parse_macro_input, Data::Struct, DataStruct, DeriveInput, Fields::Named,
5 FieldsNamed,
6};
7
8#[proc_macro_attribute]
9pub fn verbose(_attr: TokenStream, item: TokenStream) -> TokenStream {
10 let ast = parse_macro_input!(item as DeriveInput);
11 let vis = ast.vis;
12 let name = ast.ident;
13 let attrs = &ast.attrs;
14
15 let Struct(DataStruct {
17 fields:
18 Named(FieldsNamed {
19 ref named,
20 ..
21 }),
22 ..
23 }) = ast.data
24 else {
25 unimplemented!("only works on structs");
26 };
27
28 let builder_fields = named.iter().map(|f| {
30 let name = &f.ident;
31 let ty = &f.ty;
32 let attrs = &f.attrs;
33 let vis = &f.vis;
34
35 quote! {
36 #(#attrs)*
37 #vis #name: #ty
38 }
39 });
40
41 let decorated = quote! {
43 #(#attrs)*
44 #vis struct #name {
45 #[clap(short, long, action = ::clap::ArgAction::Count, global = true)]
51 #vis verbose: u8,
53
54 #(#builder_fields,)*
55 }
56 };
57
58 decorated.into()
59}