refactor(derive): Only pass around what is needed

This commit is contained in:
Ed Page 2022-09-01 13:21:57 -05:00
parent a86cb8a26c
commit a47462123c
4 changed files with 41 additions and 33 deletions

View file

@ -36,7 +36,8 @@ pub fn derive_args(input: &DeriveInput) -> TokenStream {
}) => { }) => {
let name = Name::Derived(ident.clone()); let name = Name::Derived(ident.clone());
let item = Item::from_args_struct(input, name); let item = Item::from_args_struct(input, name);
gen_for_struct(&item, ident, &input.generics, &fields.named) let fields = &fields.named;
gen_for_struct(&item, ident, &input.generics, fields)
} }
Data::Struct(DataStruct { Data::Struct(DataStruct {
fields: Fields::Unit, fields: Fields::Unit,
@ -44,12 +45,8 @@ pub fn derive_args(input: &DeriveInput) -> TokenStream {
}) => { }) => {
let name = Name::Derived(ident.clone()); let name = Name::Derived(ident.clone());
let item = Item::from_args_struct(input, name); let item = Item::from_args_struct(input, name);
gen_for_struct( let fields = &Punctuated::<Field, Comma>::new();
&item, gen_for_struct(&item, ident, &input.generics, fields)
ident,
&input.generics,
&Punctuated::<Field, Comma>::new(),
)
} }
_ => abort_call_site!("`#[derive(Args)]` only supports non-tuple structs"), _ => abort_call_site!("`#[derive(Args)]` only supports non-tuple structs"),
} }

View file

@ -16,9 +16,11 @@ use proc_macro2::TokenStream;
use proc_macro_error::abort_call_site; use proc_macro_error::abort_call_site;
use quote::quote; use quote::quote;
use syn::Ident; use syn::Ident;
use syn::Token;
use syn::Variant;
use syn::{ use syn::{
self, punctuated::Punctuated, token::Comma, Data, DataEnum, DataStruct, DeriveInput, Field, self, punctuated::Punctuated, token::Comma, Data, DataStruct, DeriveInput, Field, Fields,
Fields, Generics, Generics,
}; };
use crate::derives::{args, into_app, subcommand}; use crate::derives::{args, into_app, subcommand};
@ -40,7 +42,8 @@ pub fn derive_parser(input: &DeriveInput) -> TokenStream {
.ok() .ok()
.unwrap_or_default())); .unwrap_or_default()));
let item = Item::from_args_struct(input, name); let item = Item::from_args_struct(input, name);
gen_for_struct(&item, ident, &input.generics, &fields.named) let fields = &fields.named;
gen_for_struct(&item, ident, &input.generics, fields)
} }
Data::Struct(DataStruct { Data::Struct(DataStruct {
fields: Fields::Unit, fields: Fields::Unit,
@ -52,12 +55,8 @@ pub fn derive_parser(input: &DeriveInput) -> TokenStream {
.ok() .ok()
.unwrap_or_default())); .unwrap_or_default()));
let item = Item::from_args_struct(input, name); let item = Item::from_args_struct(input, name);
gen_for_struct( let fields = &Punctuated::<Field, Comma>::new();
&item, gen_for_struct(&item, ident, &input.generics, fields)
ident,
&input.generics,
&Punctuated::<Field, Comma>::new(),
)
} }
Data::Enum(ref e) => { Data::Enum(ref e) => {
dummies::parser_enum(ident); dummies::parser_enum(ident);
@ -66,7 +65,8 @@ pub fn derive_parser(input: &DeriveInput) -> TokenStream {
.ok() .ok()
.unwrap_or_default())); .unwrap_or_default()));
let item = Item::from_subcommand_enum(input, name); let item = Item::from_subcommand_enum(input, name);
gen_for_enum(&item, ident, &input.generics, e) let variants = &e.variants;
gen_for_enum(&item, ident, &input.generics, variants)
} }
_ => abort_call_site!("`#[derive(Parser)]` only supports non-tuple structs and enums"), _ => abort_call_site!("`#[derive(Parser)]` only supports non-tuple structs and enums"),
} }
@ -91,11 +91,16 @@ fn gen_for_struct(
} }
} }
fn gen_for_enum(item: &Item, item_name: &Ident, generics: &Generics, e: &DataEnum) -> TokenStream { fn gen_for_enum(
item: &Item,
item_name: &Ident,
generics: &Generics,
variants: &Punctuated<Variant, Token![,]>,
) -> TokenStream {
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let into_app = into_app::gen_for_enum(item, item_name, generics); let into_app = into_app::gen_for_enum(item, item_name, generics);
let subcommand = subcommand::gen_for_enum(item, item_name, generics, e); let subcommand = subcommand::gen_for_enum(item, item_name, generics, variants);
quote! { quote! {
impl #impl_generics clap::Parser for #item_name #ty_generics #where_clause {} impl #impl_generics clap::Parser for #item_name #ty_generics #where_clause {}

View file

@ -16,8 +16,8 @@ use proc_macro2::{Ident, Span, TokenStream};
use proc_macro_error::{abort, abort_call_site}; use proc_macro_error::{abort, abort_call_site};
use quote::{format_ident, quote, quote_spanned}; use quote::{format_ident, quote, quote_spanned};
use syn::{ use syn::{
punctuated::Punctuated, spanned::Spanned, Data, DataEnum, DeriveInput, FieldsUnnamed, Generics, punctuated::Punctuated, spanned::Spanned, Data, DeriveInput, FieldsUnnamed, Generics, Token,
Token, Variant, Variant,
}; };
use crate::derives::args; use crate::derives::args;
@ -34,7 +34,8 @@ pub fn derive_subcommand(input: &DeriveInput) -> TokenStream {
Data::Enum(ref e) => { Data::Enum(ref e) => {
let name = Name::Derived(ident.clone()); let name = Name::Derived(ident.clone());
let item = Item::from_subcommand_enum(input, name); let item = Item::from_subcommand_enum(input, name);
gen_for_enum(&item, ident, &input.generics, e) let variants = &e.variants;
gen_for_enum(&item, ident, &input.generics, variants)
} }
_ => abort_call_site!("`#[derive(Subcommand)]` only supports enums"), _ => abort_call_site!("`#[derive(Subcommand)]` only supports enums"),
} }
@ -44,16 +45,16 @@ pub fn gen_for_enum(
item: &Item, item: &Item,
item_name: &Ident, item_name: &Ident,
generics: &Generics, generics: &Generics,
e: &DataEnum, variants: &Punctuated<Variant, Token![,]>,
) -> TokenStream { ) -> TokenStream {
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let from_arg_matches = gen_from_arg_matches(&e.variants, item); let from_arg_matches = gen_from_arg_matches(variants, item);
let update_from_arg_matches = gen_update_from_arg_matches(&e.variants, item); let update_from_arg_matches = gen_update_from_arg_matches(variants, item);
let augmentation = gen_augment(&e.variants, item, false); let augmentation = gen_augment(variants, item, false);
let augmentation_update = gen_augment(&e.variants, item, true); let augmentation_update = gen_augment(variants, item, true);
let has_subcommand = gen_has_subcommand(&e.variants, item); let has_subcommand = gen_has_subcommand(variants, item);
quote! { quote! {
#[allow(dead_code, unreachable_code, unused_variables, unused_braces)] #[allow(dead_code, unreachable_code, unused_variables, unused_braces)]

View file

@ -13,8 +13,8 @@ use proc_macro_error::{abort, abort_call_site};
use quote::quote; use quote::quote;
use quote::quote_spanned; use quote::quote_spanned;
use syn::{ use syn::{
punctuated::Punctuated, spanned::Spanned, token::Comma, Data, DataEnum, DeriveInput, Fields, punctuated::Punctuated, spanned::Spanned, token::Comma, Data, DeriveInput, Fields, Ident,
Ident, Variant, Variant,
}; };
use crate::dummies; use crate::dummies;
@ -29,14 +29,19 @@ pub fn derive_value_enum(input: &DeriveInput) -> TokenStream {
Data::Enum(ref e) => { Data::Enum(ref e) => {
let name = Name::Derived(ident.clone()); let name = Name::Derived(ident.clone());
let item = Item::from_value_enum(input, name); let item = Item::from_value_enum(input, name);
gen_for_enum(&item, ident, e) let variants = &e.variants;
gen_for_enum(&item, ident, variants)
} }
_ => abort_call_site!("`#[derive(ValueEnum)]` only supports enums"), _ => abort_call_site!("`#[derive(ValueEnum)]` only supports enums"),
} }
} }
pub fn gen_for_enum(item: &Item, item_name: &Ident, e: &DataEnum) -> TokenStream { pub fn gen_for_enum(
let lits = lits(&e.variants, item); item: &Item,
item_name: &Ident,
variants: &Punctuated<Variant, Comma>,
) -> TokenStream {
let lits = lits(variants, item);
let value_variants = gen_value_variants(&lits); let value_variants = gen_value_variants(&lits);
let to_possible_value = gen_to_possible_value(&lits); let to_possible_value = gen_to_possible_value(&lits);