From d8561b17fc57264b1829c640ffd7d599b654a08c Mon Sep 17 00:00:00 2001 From: Dimitris Zervas Date: Tue, 28 May 2024 08:20:13 +0300 Subject: [PATCH] Kinda getting somewhere with the proc_macro - can't get the enum re-definition to work Signed-off-by: Dimitris Zervas --- packages/cadmium-macros/src/lib.rs | 46 +++++++++++++++++++++++------- packages/cadmium/src/step.rs | 5 ++-- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/packages/cadmium-macros/src/lib.rs b/packages/cadmium-macros/src/lib.rs index 04ff7c8f..981c7e43 100644 --- a/packages/cadmium-macros/src/lib.rs +++ b/packages/cadmium-macros/src/lib.rs @@ -1,21 +1,23 @@ use convert_case::{Case, Casing}; use proc_macro::TokenStream; use quote::quote; +use syn::parse::Parser; use syn::punctuated::Punctuated; use syn::{parse_macro_input, DeriveInput, Ident, MetaNameValue, Token}; use syn::spanned::Spanned; -#[proc_macro_derive(StepDataActions, attributes(step_data))] -pub fn derive_step_data(input: TokenStream) -> TokenStream { - let input = parse_macro_input!(input as DeriveInput); +#[proc_macro_attribute] +pub fn derive_step_data(_args: TokenStream, input: TokenStream) -> TokenStream { + let mut input = parse_macro_input!(input as DeriveInput); let name = &input.ident; - let data = match input.data { - syn::Data::Enum(data) => data, + let data = match &mut input.data { + syn::Data::Enum(ref mut data) => data, _ => panic!("StepData can only be derived for enums"), }; + let mut functions = vec![]; - let variants = data.variants.iter().map(|variant| { + for variant in &mut data.variants { let variant_name = &variant.ident; let mut skip_workbench = false; @@ -64,6 +66,13 @@ pub fn derive_step_data(input: TokenStream) -> TokenStream { .get_mut(workbench_id as usize) .ok_or(anyhow::anyhow!("Could not find workbench"))?; }; + if let syn::Fields::Named(fields) = &mut variant.fields { + let field_exists = fields.named.iter().any(|f| f.ident.as_ref().unwrap() == "workbench_id"); + if !field_exists { + fields.named.push(syn::Field::parse_named.parse2(quote! { workbench_id: crate::IDType }).unwrap()); + } + } + wb_id_def = quote! { workbench_id: crate::IDType, }; wb_id_arg = quote! { workbench_id, }; } @@ -85,6 +94,14 @@ pub fn derive_step_data(input: TokenStream) -> TokenStream { .ok_or(anyhow::anyhow!("Could not find parent"))?; let parent_ = parent_ref_.borrow_mut(); }; + + if let syn::Fields::Named(fields) = &mut variant.fields { + let field_exists = fields.named.iter().any(|f| f.ident.as_ref().unwrap() == &id_arg_name); + if !field_exists { + fields.named.push(syn::Field::parse_named.parse2(quote! { #id_arg_name: crate::IDType }).unwrap()); + } + } + field_id_def = quote! { #id_arg_name: crate::IDType, }; field_id_arg = quote! { #id_arg_name, }; } else if !skip_workbench { @@ -108,8 +125,8 @@ pub fn derive_step_data(input: TokenStream) -> TokenStream { }).into_iter(); let function_args2 = function_args.clone(); - quote! { - pub fn #add_func_name(&mut self, #wb_id_def #field_id_def name: String, #( #function_defs ),*) -> Result { + functions.push(quote! { + pub fn #add_func_name(&mut self, name: String, #( #function_defs ),*) -> Result { #wb_var #field_var let result_id_ = parent_.#add_func_name(#( #function_args ),*)?; @@ -130,12 +147,19 @@ pub fn derive_step_data(input: TokenStream) -> TokenStream { Ok(result_id_) } - } - }); + }); + } let expanded = quote! { + // #[derive(Tsify, Debug, Serialize, Deserialize)] + // #[tsify(into_wasm_abi, from_wasm_abi)] + #input + // enum #name { + // #( #variants ),* + // } + impl crate::Project { - #( #variants )* + #( #functions )* } }; diff --git a/packages/cadmium/src/step.rs b/packages/cadmium/src/step.rs index 4364f52d..5c3032b9 100644 --- a/packages/cadmium/src/step.rs +++ b/packages/cadmium/src/step.rs @@ -1,5 +1,5 @@ -use cadmium_macros::StepDataActions; +use cadmium_macros::{derive_step_data, StepDataActions}; use serde::{Deserialize, Serialize}; use tsify::Tsify; use wasm_bindgen::prelude::*; @@ -25,8 +25,7 @@ pub struct Step { pub(crate) data: StepData, } -#[derive(StepDataActions, Tsify, Debug, Serialize, Deserialize)] -#[tsify(into_wasm_abi, from_wasm_abi)] +#[derive_step_data] pub enum StepData { WorkbenchPoint { point: Point3,