1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
mod construct; extern crate proc_macro; use proc_macro::TokenStream; use syn::{ parse2, parse_quote, parse_macro_input, DeriveInput, Ident, Expr, }; use quote::quote; use crate::construct::DefaultValue; #[proc_macro_derive(ConstructorMacro, attributes(default))] pub fn constructor_macro(item: TokenStream) -> TokenStream { let input = parse_macro_input!(item as DeriveInput); let DeriveInput { ref ident, .. } = input; match input.data { syn::Data::Struct(ref struct_data) => { let tokens = match struct_data.fields { syn::Fields::Unit => { quote! { impl ::core::default::Default for #ident { fn default() -> Self { #ident } } #[macro_export] macro_rules! #ident { () => {{ #ident }}; } } }, syn::Fields::Named(ref fields_named) => { let defaults = fields_named.named.iter().map(|field| { let ident = field.ident.as_ref().unwrap(); let mut default_value: (&Ident, Expr) = (ident, parse_quote! { ::core::default::Default::default() }); for attr in field.attrs.iter() { if attr.path.is_ident("default") { let tts = attr.tts.clone(); let attr: syn::Result<DefaultValue> = parse2(tts); if let Ok(attr) = attr { let value = attr.value; default_value = (&ident, value); } } } default_value }); let (fields, values): (Vec<_>, Vec<_>) = defaults.unzip(); quote! { impl ::core::default::Default for #ident { fn default() -> Self { #ident { #(#fields: #values),* } } } #[macro_export] macro_rules! #ident { ( $( $field: ident : $value: expr, )* ) => {{ #ident { $( $field : $value, )* ..::core::default::Default::default() } }}; ( $( $field: ident : $value: expr ),* ) => {{ #ident! { $( $field : $value, )* } }}; } } }, _ => panic!("Tuple structs not supported"), }; tokens.into() } _ => panic!("Must be a struct"), } }