From 7981a7ecec4c0656c4d2fdaf72325935ed2f1a28 Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Fri, 30 May 2025 14:53:21 +0300 Subject: [PATCH 1/2] Add optional async_suffix attribute to bisync macro --- bisync_macros/Cargo.toml | 3 +++ bisync_macros/src/lib.rs | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/bisync_macros/Cargo.toml b/bisync_macros/Cargo.toml index 30862af..09cf40f 100644 --- a/bisync_macros/Cargo.toml +++ b/bisync_macros/Cargo.toml @@ -10,3 +10,6 @@ repository = "https://github.com/JM4ier/bisync" proc-macro = true [dependencies] +syn = { version = "2.0", features = ["full", "visit-mut"] } +quote = "1.0" +proc-macro2 = "1.0" diff --git a/bisync_macros/src/lib.rs b/bisync_macros/src/lib.rs index 6bbd70d..2520212 100644 --- a/bisync_macros/src/lib.rs +++ b/bisync_macros/src/lib.rs @@ -1,6 +1,8 @@ //! Do not use this crate directly. use proc_macro::{Group, TokenStream}; +use quote::quote; +use syn::{parse_macro_input, visit_mut::VisitMut, Expr, ItemFn}; #[proc_macro_attribute] pub fn internal_noop(_attr: TokenStream, item: TokenStream) -> TokenStream { @@ -55,3 +57,45 @@ pub fn internal_strip_async(attr: TokenStream, item: TokenStream) -> TokenStream new.into_iter().collect() } + +struct MethodTransformer { + suffix: String, +} + +impl VisitMut for MethodTransformer { + fn visit_expr_mut(&mut self, expr: &mut Expr) { + if let Expr::Await(await_expr) = expr { + if let Expr::MethodCall(method_call) = &mut *await_expr.base { + let new_method_name = format!("{}_{}", method_call.method, self.suffix); + method_call.method = syn::Ident::new(&new_method_name, method_call.method.span()); + } + } + syn::visit_mut::visit_expr_mut(self, expr); + } +} + +#[proc_macro_attribute] +pub fn internal_transform_async(attr: TokenStream, item: TokenStream) -> TokenStream { + let mut input = parse_macro_input!(item as ItemFn); + let attr_str = attr.to_string(); + let suffix = if attr_str.contains("async_suffix") { + let parts: Vec<&str> = attr_str.split('=').map(|s| s.trim()).collect(); + if parts.len() == 2 { + parts[1].trim_matches('"').to_string() + } else { + "".to_string() + } + } else { + "".to_string() + }; + + if !suffix.is_empty() { + let mut transformer = MethodTransformer { suffix }; + transformer.visit_item_fn_mut(&mut input); + } + + let output = quote! { + #input + }; + output.into() +} From f1e678d99f711466d41b554824373df3251f1593 Mon Sep 17 00:00:00 2001 From: okhsunrog Date: Fri, 30 May 2025 15:40:20 +0300 Subject: [PATCH 2/2] use the changed bisync_macro in bisync --- bisync/Cargo.toml | 2 +- bisync/src/lib.rs | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/bisync/Cargo.toml b/bisync/Cargo.toml index 29b0316..ac446a2 100644 --- a/bisync/Cargo.toml +++ b/bisync/Cargo.toml @@ -9,4 +9,4 @@ repository = "https://github.com/JM4ier/bisync" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bisync_macros = "0.2.3" +bisync_macros = { path = "../bisync_macros" } diff --git a/bisync/src/lib.rs b/bisync/src/lib.rs index 960b277..db1204b 100644 --- a/bisync/src/lib.rs +++ b/bisync/src/lib.rs @@ -94,11 +94,13 @@ pub mod asynchronous { pub use ::bisync_macros::internal_delete as only_sync; /// Specialize an item to only be emitted in the asynchronous module pub use ::bisync_macros::internal_noop as only_async; - /// Emit an item in both synchronous and asynchronous code, and adjust asynchronisity depending on location - pub use ::bisync_macros::internal_noop as bisync; + /// Emit an item in both synchronous and asynchronous code. + /// If an `async_suffix = "some_suffix"` attribute is provided *to this macro*, + /// it transforms `method().await` to `method_some_suffix().await`. + /// Otherwise (no `async_suffix` or empty `async_suffix`), it acts like a no-op for the async code structure. + pub use ::bisync_macros::internal_transform_async as bisync; /// true in the synchronous module, otherwise false pub const SYNC: bool = false; /// true in the asynchronous module, otherwise false pub const ASYNC: bool = true; } -