From 8848cd0732a7656a2e0913e63d224618082f21df Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 17 Jun 2026 19:41:11 +0200 Subject: feat(engine-macros): improve flexibility of Reflection macro on generic types --- engine-macros/src/reflection.rs | 61 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) (limited to 'engine-macros/src/reflection.rs') diff --git a/engine-macros/src/reflection.rs b/engine-macros/src/reflection.rs index 5d40e0c..2180084 100644 --- a/engine-macros/src/reflection.rs +++ b/engine-macros/src/reflection.rs @@ -1,6 +1,9 @@ +use crate::reflection::options_attr::OptionsAttr; + mod default_value; mod enum_impl; mod field; +mod options_attr; mod struct_impl; mod visibility; @@ -8,9 +11,63 @@ pub fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream { let input = syn::parse2::(input).unwrap(); + let options = get_options(&input); + match input { - syn::Item::Struct(input) => struct_impl::generate(input), - syn::Item::Enum(input) => enum_impl::generate(input), + syn::Item::Struct(input) => struct_impl::generate(input, options), + syn::Item::Enum(input) => enum_impl::generate(input, options), _ => panic!("Invalid input"), } } + +pub fn get_options(input: &syn::Item) -> OptionsAttr +{ + let (attrs, generic_params) = match &input { + syn::Item::Struct(input) => (input.attrs.as_slice(), &input.generics.params), + syn::Item::Enum(input) => (input.attrs.as_slice(), &input.generics.params), + _ => ( + const { &[] }.as_slice(), + &syn::punctuated::Punctuated::::new(), + ), + }; + + if attrs + .iter() + .filter(|attr| attr.path().is_ident("reflection")) + .count() + > 1 + { + panic!("Multiple 'reflection' attributes are not allowed"); + } + + let options = match attrs + .iter() + .find_map(|attr| { + if attr.path().is_ident("reflection") { + return Some(attr.parse_args::()); + } + + None + }) + .transpose() + { + Ok(attr) => attr.unwrap_or_default(), + Err(err) => { + panic!("{err}"); + } + }; + + if options.impl_with_generics.is_empty() && !generic_params.is_empty() { + panic!(concat!( + "Generic types deriving Reflection must specify which ", + "generics to use in the generated impl(s) using the 'reflection' attribute\n", + "For example: #[reflection(impl_with_generics(, ))]" + )); + } + + if !options.impl_with_generics.is_empty() && generic_params.is_empty() { + panic!("Specifying 'impl_with_generics' for non-generic types is not allowed"); + } + + options +} -- cgit v1.2.3-18-g5258