use super::{dummies, from_argmatches, into_app, subcommand};
use proc_macro2::Ident;
use proc_macro_error::abort_call_site;
use quote::quote;
use syn::{self, punctuated, token, Attribute, DataEnum};
pub fn derive_clap(input: &syn::DeriveInput) -> proc_macro2::TokenStream {
use syn::Data::*;
let ident = &input.ident;
match input.data {
Struct(syn::DataStruct {
fields: syn::Fields::Named(ref fields),
..
}) => {
dummies::clap_struct(ident);
gen_for_struct(ident, &fields.named, &input.attrs)
}
Struct(syn::DataStruct {
fields: syn::Fields::Unit,
..
}) => {
dummies::clap_struct(ident);
gen_for_struct(
ident,
&punctuated::Punctuated::<syn::Field, token::Comma>::new(),
&input.attrs,
)
}
Enum(ref e) => {
dummies::clap_enum(ident);
gen_for_enum(ident, &input.attrs, e)
}
_ => abort_call_site!("`#[derive(Clap)]` only supports non-tuple structs and enums"),
}
}
fn gen_for_struct(
name: &syn::Ident,
fields: &punctuated::Punctuated<syn::Field, token::Comma>,
attrs: &[syn::Attribute],
) -> proc_macro2::TokenStream {
let (into_app, attrs) = into_app::gen_for_struct(name, fields, attrs);
let from_arg_matches = from_argmatches::gen_for_struct(name, fields, &attrs);
quote! {
impl ::clap::Clap for #name {}
#into_app
#from_arg_matches
}
}
fn gen_for_enum(name: &Ident, attrs: &[Attribute], e: &DataEnum) -> proc_macro2::TokenStream {
let into_app = into_app::gen_for_enum(name);
let from_arg_matches = from_argmatches::gen_for_enum(name);
let subcommand = subcommand::gen_for_enum(name, attrs, e);
quote! {
impl ::clap::Clap for #name { }
#into_app
#from_arg_matches
#subcommand
}
}