diff --git a/derive/src/initial.rs b/derive/src/initial.rs index df8935b..2766a1d 100644 --- a/derive/src/initial.rs +++ b/derive/src/initial.rs @@ -1,12 +1,11 @@ use syn::{ - parse_macro_input, - Data::Struct, - DeriveInput, Fields, parse::{ParseStream, Parse}, Token, + parse::{Parse, ParseStream}, + parse_macro_input, Data, DeriveInput, Fields, Token, }; use proc_macro::TokenStream; use quote::quote; -use syn::{Attribute, Expr, LitStr, punctuated::Punctuated}; +use syn::{punctuated::Punctuated, Attribute, Expr, LitStr}; mod kw { syn::custom_keyword!(env); @@ -36,11 +35,12 @@ impl Parse for InitialArg { } impl InitialField { - fn from_attribute(attribute: &Attribute) -> syn::Result { + fn from_attribute(attribute: &Attribute) -> syn::Result { let mut _self = Self::default(); - let args = attribute.parse_args_with(Punctuated::::parse_terminated)?; - + let args = + attribute.parse_args_with(Punctuated::::parse_terminated)?; + for arg in args { match arg { InitialArg::Expr(e) => { @@ -61,7 +61,7 @@ impl InitialField { Ok(_self) } - fn to_expr(self) -> proc_macro2::TokenStream { + fn into_expr(self) -> proc_macro2::TokenStream { let mut default_value = match self.expr { Some(val) => quote!(#val.into()), None => quote!(::core::default::Default::default()), @@ -74,7 +74,8 @@ impl InitialField { .unwrap_or(#default_value) ); } - default_value.into() + + default_value } } @@ -84,10 +85,22 @@ pub fn initial(input: TokenStream) -> TokenStream { let name = input.ident; let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); - let Struct(data) = input.data else { - panic!("Input should be a struct!"); + let function_body = match input.data { + Data::Struct(data) => initial_struct(data), + _ => panic!("Initial derive macro can only be used on structs"), }; + quote!( + impl #impl_generics Initial for #name #ty_generics #where_clause { + fn initial() -> Self { + #function_body + } + } + ) + .into() +} + +fn initial_struct(data: syn::DataStruct) -> proc_macro2::TokenStream { let Fields::Named(fields) = data.fields else { panic!("Fields must be named"); }; @@ -98,22 +111,16 @@ pub fn initial(input: TokenStream) -> TokenStream { for field in fields.named { let ident = field.ident; let field = parse_field_attr(&field.attrs); - let default_value = field.to_expr(); + let default_value = field.into_expr(); defaults.push(quote!(#ident: #default_value)); } - let expanded = quote!( - impl #impl_generics Initial for #name #ty_generics #where_clause { - fn initial() -> Self { - Self { - #(#defaults),* - } - } + quote!( + Self { + #(#defaults),* } - ); - - TokenStream::from(expanded) + ) } fn parse_field_attr(attrs: &[Attribute]) -> InitialField { @@ -124,4 +131,3 @@ fn parse_field_attr(attrs: &[Attribute]) -> InitialField { } InitialField::default() } - diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 69264e3..c8c25fe 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -2,8 +2,8 @@ mod argument; mod attributes; mod flags; mod help; -mod markdown; mod initial; +mod markdown; use argument::{ long_handling, number_handling, parse_argument, parse_arguments_attr, positional_handling, @@ -14,11 +14,7 @@ use help::{help_handling, help_string, version_handling}; use proc_macro::TokenStream; use quote::quote; -use syn::{ - parse_macro_input, - Data::Enum, - DeriveInput, -}; +use syn::{parse_macro_input, Data::Enum, DeriveInput}; #[proc_macro_derive(Initial, attributes(initial))] pub fn initial(input: TokenStream) -> TokenStream { diff --git a/tests/coreutils.rs b/tests/coreutils.rs index 98634d1..f70261b 100644 --- a/tests/coreutils.rs +++ b/tests/coreutils.rs @@ -27,6 +27,3 @@ mod ls; #[path = "coreutils/tail.rs"] mod tail; - -#[path = "coreutils/uniq.rs"] -mod uniq;