diff options
Diffstat (limited to 'mingling_macros/src/program_setup.rs')
| -rw-r--r-- | mingling_macros/src/program_setup.rs | 116 |
1 files changed, 0 insertions, 116 deletions
diff --git a/mingling_macros/src/program_setup.rs b/mingling_macros/src/program_setup.rs deleted file mode 100644 index 7fd9d16..0000000 --- a/mingling_macros/src/program_setup.rs +++ /dev/null @@ -1,116 +0,0 @@ -use proc_macro::TokenStream; -use quote::quote; -use syn::spanned::Spanned; -use syn::{FnArg, Ident, ItemFn, Pat, PatType, ReturnType, Signature, Type, parse_macro_input}; - -/// Extracts the program parameter from function arguments -fn extract_program_param(sig: &Signature) -> syn::Result<(Pat, Type)> { - // The function should have exactly one parameter - if sig.inputs.len() != 1 { - return Err(syn::Error::new( - sig.inputs.span(), - "Setup function must have exactly one parameter", - )); - } - - let arg = &sig.inputs[0]; - match arg { - FnArg::Typed(PatType { pat, ty, .. }) => { - // Extract the pattern (parameter name) - let param_pat = (**pat).clone(); - // Extract the type as-is - let param_type = (**ty).clone(); - Ok((param_pat, param_type)) - } - FnArg::Receiver(_) => Err(syn::Error::new( - arg.span(), - "Setup function cannot have self parameter", - )), - } -} - -/// Extracts and validates the return type -fn extract_return_type(sig: &Signature) -> syn::Result<()> { - // Setup functions should return () or have no return type - match &sig.output { - ReturnType::Type(_, ty) => { - // Check if it's () - match &**ty { - Type::Tuple(tuple) if tuple.elems.is_empty() => Ok(()), - _ => Err(syn::Error::new( - ty.span(), - "Setup function must return () or have no return type", - )), - } - } - ReturnType::Default => Ok(()), - } -} - -pub fn setup_attr(attr: TokenStream, item: TokenStream) -> TokenStream { - // #[program_setup] takes no arguments; always use the default program path - let _ = attr; - let program_path = crate::default_program_path(); - - // Parse the function item - let input_fn = parse_macro_input!(item as ItemFn); - - // Validate the function is not async - if input_fn.sig.asyncness.is_some() { - return syn::Error::new(input_fn.sig.span(), "Setup function cannot be async") - .to_compile_error() - .into(); - } - - // Extract the program parameter - let (program_param, program_type) = match extract_program_param(&input_fn.sig) { - Ok(info) => info, - Err(e) => return e.to_compile_error().into(), - }; - - // Validate return type - if let Err(e) = extract_return_type(&input_fn.sig) { - return e.to_compile_error().into(); - } - - // Get the function body - let fn_body = &input_fn.block; - - // Get function attributes (excluding the setup attribute) - let mut fn_attrs = input_fn.attrs.clone(); - - // Remove any #[program_setup(...)] attributes to avoid infinite recursion - fn_attrs.retain(|attr| !attr.path().is_ident("setup")); - - // Get function visibility - let vis = &input_fn.vis; - - // Get function name - let fn_name = &input_fn.sig.ident; - - // Generate struct name from function name using pascal_case - let pascal_case_name = just_fmt::pascal_case!(fn_name.to_string()); - let struct_name = Ident::new(&pascal_case_name, fn_name.span()); - - // Generate the struct and implementation - let expanded = quote! { - #(#fn_attrs)* - #[doc(hidden)] - #vis struct #struct_name; - - impl ::mingling::setup::ProgramSetup<#program_path> for #struct_name { - fn setup(self, program: &mut ::mingling::Program<#program_path>) { - // Call the original function with the actual Program type - #fn_name(program); - } - } - - // Keep the original function for internal use - #(#fn_attrs)* - #vis fn #fn_name(#program_param: #program_type) { - #fn_body - } - }; - - expanded.into() -} |
