From 35026ac4748e379e296c47444f60f7817ba16e5d Mon Sep 17 00:00:00 2001 From: Thomas Braun Date: Fri, 6 Dec 2024 21:02:26 -0500 Subject: [PATCH] fix(macros): integration test passes --- macros/blueprint-proc-macro/src/job.rs | 55 ++++++++++++++----- .../src/special_impls/evm.rs | 2 +- .../src/special_impls/tangle.rs | 34 ++++++++---- 3 files changed, 66 insertions(+), 25 deletions(-) diff --git a/macros/blueprint-proc-macro/src/job.rs b/macros/blueprint-proc-macro/src/job.rs index fc289ddf..3a2c9ddd 100644 --- a/macros/blueprint-proc-macro/src/job.rs +++ b/macros/blueprint-proc-macro/src/job.rs @@ -230,21 +230,21 @@ pub(crate) fn generate_event_workflow_tokenstream( // convert the listener var, which is just a struct name, to an ident let listener = listener_meta.listener.to_token_stream(); + // Raw events have no pre-processor, therefore their inputs are passed directly into the job function + // and NOT as job params + let is_raw = listener_meta.is_raw(); + // Generate the variable that we are passing as the context into EventListener::create(&mut ctx) // We assume the first supplied event handler arg is the context we are injecting into the event listener // Then, pass that into the EventFlowWrapper let fn_name_ident = &input.sig.ident; let static_ctx_get_override = quote! { CTX.get().unwrap() }; - let mut ordered_inputs = - get_fn_call_ordered(param_types, params, Some(static_ctx_get_override))?; + let (ctx_pos_in_ordered_inputs, mut ordered_inputs) = + get_fn_call_ordered(param_types, params, Some(static_ctx_get_override), is_raw)?; let asyncness = get_asyncness(input); let call_id_static_name = get_current_call_id_field_name(input); - // Raw events have no pre-processor, therefore their inputs are passed directly into the job function - // and NOT as job params - let is_raw = listener_meta.is_raw(); - // TODO: task 001: find better way to identify which ident is the raw event // for now, we assume the raw event is always listed first if is_raw { @@ -257,7 +257,12 @@ pub(crate) fn generate_event_workflow_tokenstream( // If is_raw, assume the actual context is the second param quote! { ctx. #field_in_self .clone() } }) - .ok_or_else(|| syn::Error::new(Span::call_site(), "Must specify a context"))?; + .ok_or_else(|| { + syn::Error::new( + Span::call_site(), + "Must specify a context (field_in_self_getter)", + ) + })?; let autogen_struct_name = quote! { #struct_name }; @@ -295,6 +300,7 @@ pub(crate) fn generate_event_workflow_tokenstream( &call_id_static_name, &asyncness, &return_type, + ctx_pos_in_ordered_inputs, )?, ListenerType::Evm => get_evm_job_processor_wrapper( @@ -312,7 +318,7 @@ pub(crate) fn generate_event_workflow_tokenstream( quote! { move |param0| async move { - let res = #fn_name_ident (#(#ordered_inputs)*) #asyncness; + let res = #fn_name_ident (#(#ordered_inputs),*) #asyncness; #job_processor_call_return } } @@ -568,7 +574,8 @@ pub fn get_fn_call_ordered( param_types: &IndexMap, params_from_job_args: &[Ident], replacement_for_self: Option, -) -> syn::Result> { + is_raw: bool, +) -> syn::Result<(usize, Vec)> { let (event_handler_args, _) = get_event_handler_args(param_types, params_from_job_args)?; let additional_var_indexes: Vec = @@ -583,6 +590,8 @@ pub fn get_fn_call_ordered( // This has all params let mut job_var_idx = 0; + let mut non_job_var_count = 0; + let mut ctx_pos = None; let this = replacement_for_self.unwrap_or_else(|| quote! { self }); let ret = param_types .iter() @@ -595,7 +604,7 @@ pub fn get_fn_call_ordered( if is_job_var { let ident = format_ident!("param{job_var_idx}"); job_var_idx += 1; - return quote! { #ident, }; + return quote! { #ident }; } let (is_ref, is_ref_mut) = match ty { @@ -603,17 +612,35 @@ pub fn get_fn_call_ordered( _ => (false, false), }; + if non_job_var_count == 0 { + // Assume first non-job var is the context + ctx_pos = Some(pos_in_all_args); + } + + non_job_var_count += 1; + if is_ref && is_ref_mut { - quote! { &mut #this .#ident, } + quote! { &mut #this .#ident } } else if is_ref { - quote! { &#this .#ident, } + quote! { &#this .#ident } } else { - quote! { #this .#ident.clone(), } + quote! { #this .#ident.clone() } } }) .collect::>(); - Ok(ret) + if is_raw { + ctx_pos = Some(1); // Raw events have only two events: 0 = the raw event, 1 = the context + } + + let ctx_pos = ctx_pos.ok_or_else(|| { + syn::Error::new( + Span::call_site(), + "Could not find the context in the function signature", + ) + })?; + + Ok((ctx_pos, ret)) } fn get_asyncness(input: &ItemFn) -> proc_macro2::TokenStream { diff --git a/macros/blueprint-proc-macro/src/special_impls/evm.rs b/macros/blueprint-proc-macro/src/special_impls/evm.rs index f89e3393..1f34992f 100644 --- a/macros/blueprint-proc-macro/src/special_impls/evm.rs +++ b/macros/blueprint-proc-macro/src/special_impls/evm.rs @@ -124,7 +124,7 @@ pub(crate) fn get_evm_job_processor_wrapper( quote! { let inputs = param0; #(#params_tokens)* - let res = #fn_name_ident (#(#ordered_inputs)*) #asyncness; + let res = #fn_name_ident (#(#ordered_inputs),*) #asyncness; } }; diff --git a/macros/blueprint-proc-macro/src/special_impls/tangle.rs b/macros/blueprint-proc-macro/src/special_impls/tangle.rs index 7c52a888..b913512a 100644 --- a/macros/blueprint-proc-macro/src/special_impls/tangle.rs +++ b/macros/blueprint-proc-macro/src/special_impls/tangle.rs @@ -79,9 +79,10 @@ pub(crate) fn get_tangle_job_processor_wrapper( event_listeners: &EventListenerArgs, ordered_inputs: &mut Vec, fn_name_ident: &Ident, - call_id_static_name: &Ident, + _call_id_static_name: &Ident, asyncness: &TokenStream, return_type: &Type, + ctx_post_in_ordered_inputs: usize, ) -> syn::Result { let params = declared_params_to_field_types(job_params, param_map)?; let params_tokens = event_listeners.get_param_name_tokenstream(¶ms); @@ -91,37 +92,50 @@ pub(crate) fn get_tangle_job_processor_wrapper( const PARAMETER_COUNT: usize = #parameter_count; }; + // let non_job_param_map = get_non_job_arguments(param_map, job_params); + + let injected_context = ordered_inputs[ctx_post_in_ordered_inputs].clone(); + let call_id_injector = quote! { + let mut injected_context = #injected_context; + if let Some(call_id) = tangle_event.call_id { + injected_context.set_call_id(call_id); + } + }; + + ordered_inputs[ctx_post_in_ordered_inputs] = quote! { injected_context }; + let job_processor_call = if params_tokens.is_empty() { let second_param = ordered_inputs .pop() .ok_or_else(|| syn::Error::new(Span::call_site(), "Context type required"))?; quote! { + #call_id_injector // If no args are specified, assume this job has no parameters and thus takes in the raw event - let res = #fn_name_ident (param0, #second_param) #asyncness; + let res = #fn_name_ident (tangle_event, #second_param) #asyncness; } } else { quote! { #parameter_count_const - if param0.args.len() != PARAMETER_COUNT { + if tangle_event.args.len() != PARAMETER_COUNT { return Err( - ::gadget_sdk::Error::BadArgumentDecoding(format!("Parameter count mismatch, got `{}`, expected `{PARAMETER_COUNT}`", param0.args.len())) + ::gadget_sdk::Error::BadArgumentDecoding(format!("Parameter count mismatch, got `{}`, expected `{PARAMETER_COUNT}`", tangle_event.args.len())) ); } - let mut args = param0.args.into_iter(); + let mut args = tangle_event.args.clone().into_iter(); #(#params_tokens)* - let res = #fn_name_ident (#(#ordered_inputs)*) #asyncness; + + #call_id_injector + + let res = #fn_name_ident (#(#ordered_inputs),*) #asyncness; } }; let job_processor_call_return = get_return_type_wrapper(return_type); Ok(quote! { - move |param0: gadget_sdk::event_listener::tangle::TangleEvent<_, _>| async move { - if let Some(call_id) = param0.call_id { - #call_id_static_name.store(call_id, std::sync::atomic::Ordering::Relaxed); - } + move |tangle_event: gadget_sdk::event_listener::tangle::TangleEvent<_, _>| async move { #job_processor_call #job_processor_call_return