diff --git a/rust/psibase_macros/psibase-macros-lib/src/service_macro/actions.rs b/rust/psibase_macros/psibase-macros-lib/src/service_macro/actions.rs index 03a20ac40..7310ef8f6 100644 --- a/rust/psibase_macros/psibase-macros-lib/src/service_macro/actions.rs +++ b/rust/psibase_macros/psibase-macros-lib/src/service_macro/actions.rs @@ -1,7 +1,7 @@ use darling::FromMeta; use proc_macro_error::abort; use quote::{quote, ToTokens}; -use syn::{AttrStyle, FnArg, ItemFn, Pat, ReturnType}; +use syn::{AttrStyle, Attribute, FnArg, Ident, Item, ItemFn, Pat, ReturnType}; #[derive(Debug, FromMeta)] #[darling(default)] @@ -189,10 +189,48 @@ pub fn process_action_schema( } } -pub fn add_check_init(f: &mut ItemFn) { +pub struct PreAction { + pub exists: bool, + pub fn_name: Option, +} + +impl Default for PreAction { + fn default() -> Self { + Self { + exists: false, + fn_name: None, + } + } +} + +fn is_pre_action_attr(attr: &Attribute) -> bool { + if let AttrStyle::Outer = attr.style { + if attr.meta.path().is_ident("pre_action") { + return true; + } + } + false +} + +pub fn check_for_pre_action(pre_action_info: &mut PreAction, items: &mut Vec) { + for (_item_index, item) in items.iter_mut().enumerate() { + if let Item::Fn(f) = item { + if f.attrs.iter().any(is_pre_action_attr) { + pre_action_info.exists = true; + pre_action_info.fn_name = Some(f.sig.ident.clone()); + if let Some(pre_action_pos) = f.attrs.iter().position(is_pre_action_attr) { + f.attrs.remove(pre_action_pos); + } + } + } + } +} + +pub fn add_pre_action_call(pre_action_info: &PreAction, f: &mut ItemFn) { // println!("adding check_init to {}", f.sig.ident.to_string()); + let fn_name = pre_action_info.fn_name.clone(); let new_line_ts = quote! { - check_init(); + #fn_name(); }; let new_line = syn::parse2(new_line_ts).unwrap(); f.block.stmts.insert(0, new_line); diff --git a/rust/psibase_macros/psibase-macros-lib/src/service_macro/mod.rs b/rust/psibase_macros/psibase-macros-lib/src/service_macro/mod.rs index c8ad3f672..de39c5887 100644 --- a/rust/psibase_macros/psibase-macros-lib/src/service_macro/mod.rs +++ b/rust/psibase_macros/psibase-macros-lib/src/service_macro/mod.rs @@ -5,7 +5,8 @@ mod graphql; mod tables; use actions::{ - add_check_init, process_action_args, process_action_callers, process_action_schema, Options, + add_pre_action_call, check_for_pre_action, process_action_args, process_action_callers, + process_action_schema, Options, PreAction, }; use darling::ast::NestedMeta; use darling::{Error, FromMeta}; @@ -32,6 +33,7 @@ pub fn service_macro_impl(attr: TokenStream, item: TokenStream) -> TokenStream { return TokenStream::from(Error::from(e).write_errors()); } }; + // println!("attr_args: {:#?}", attr_args); let mut options: Options = match Options::from_list(&attr_args) { Ok(val) => val, @@ -88,12 +90,14 @@ fn process_mod( let event_structs_mod = proc_macro2::TokenStream::from_str(&options.event_structs).unwrap(); let wrapper = proc_macro2::TokenStream::from_str(&options.wrapper).unwrap(); let structs = proc_macro2::TokenStream::from_str(&options.structs).unwrap(); + let mut pre_action_info: PreAction = PreAction::default(); if let Some((_, items)) = &mut impl_mod.content { let mut table_structs: HashMap> = HashMap::new(); let mut action_fns: Vec = Vec::new(); let mut non_action_fns: Vec = Vec::new(); let mut event_fns: HashMap> = HashMap::new(); + check_for_pre_action(&mut pre_action_info, items); for (item_index, item) in items.iter_mut().enumerate() { if let Item::Struct(s) = item { if s.attrs.iter().any(is_table_attr) { @@ -175,7 +179,7 @@ fn process_mod( let mut invoke_args = quote! {}; let mut invoke_struct_args = quote! {}; if has_check_init { - add_check_init(f); + add_pre_action_call(&pre_action_info, f); // println!( // "1 : 1st line of {} is {:#?}", // f.sig.ident.to_string(),