1#![doc = include_str!("../README.md")]
16#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
17#![cfg_attr(docsrs, feature(doc_auto_cfg))]
18#![forbid(unsafe_code)]
19#![warn(missing_docs)]
20#![warn(clippy::print_stderr)]
21#![warn(clippy::print_stdout)]
22
23use proc_macro::TokenStream;
24use syn::{parse_macro_input, DeriveInput};
25use syn::{Data, DataStruct, Fields};
26
27#[macro_use]
28mod macros;
29
30mod attr;
31mod derives;
32mod dummies;
33mod item;
34mod utils;
35
36#[proc_macro_derive(ValueEnum, attributes(clap, value))]
38pub fn value_enum(input: TokenStream) -> TokenStream {
39 let input: DeriveInput = parse_macro_input!(input);
40 derives::derive_value_enum(&input)
41 .unwrap_or_else(|err| {
42 let dummy = dummies::value_enum(&input.ident);
43 to_compile_error(err, dummy)
44 })
45 .into()
46}
47
48#[proc_macro_derive(Parser, attributes(clap, structopt, command, arg, group))]
55pub fn parser(input: TokenStream) -> TokenStream {
56 let input: DeriveInput = parse_macro_input!(input);
57 derives::derive_parser(&input)
58 .unwrap_or_else(|err| {
59 let specific_dummy = match input.data {
60 Data::Struct(DataStruct {
61 fields: Fields::Named(ref _fields),
62 ..
63 }) => Some(dummies::args(&input.ident)),
64 Data::Struct(DataStruct {
65 fields: Fields::Unit,
66 ..
67 }) => Some(dummies::args(&input.ident)),
68 Data::Enum(_) => Some(dummies::subcommand(&input.ident)),
69 _ => None,
70 };
71 let dummy = specific_dummy
72 .map(|specific_dummy| {
73 let parser_dummy = dummies::parser(&input.ident);
74 quote::quote! {
75 #parser_dummy
76 #specific_dummy
77 }
78 })
79 .unwrap_or_else(|| quote::quote!());
80 to_compile_error(err, dummy)
81 })
82 .into()
83}
84
85#[proc_macro_derive(Subcommand, attributes(clap, command, arg, group))]
87pub fn subcommand(input: TokenStream) -> TokenStream {
88 let input: DeriveInput = parse_macro_input!(input);
89 derives::derive_subcommand(&input)
90 .unwrap_or_else(|err| {
91 let dummy = dummies::subcommand(&input.ident);
92 to_compile_error(err, dummy)
93 })
94 .into()
95}
96
97#[proc_macro_derive(Args, attributes(clap, command, arg, group))]
99pub fn args(input: TokenStream) -> TokenStream {
100 let input: DeriveInput = parse_macro_input!(input);
101 derives::derive_args(&input)
102 .unwrap_or_else(|err| {
103 let dummy = dummies::args(&input.ident);
104 to_compile_error(err, dummy)
105 })
106 .into()
107}
108
109fn to_compile_error(
110 error: syn::Error,
111 dummy: proc_macro2::TokenStream,
112) -> proc_macro2::TokenStream {
113 let compile_errors = error.to_compile_error();
114 quote::quote!(
115 #dummy
116 #compile_errors
117 )
118}