From 7809a8cbfbaf41fcc81de980c903e11f08bd1b12 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Sun, 29 Mar 2026 01:18:25 +0800 Subject: Generate struct names from function names in chain and renderer macros --- mingling_macros/src/chain.rs | 23 +++++------------------ mingling_macros/src/lib.rs | 20 ++++++++++---------- mingling_macros/src/node.rs | 8 ++++++++ mingling_macros/src/renderer.rs | 27 ++++++--------------------- 4 files changed, 29 insertions(+), 49 deletions(-) (limited to 'mingling_macros') diff --git a/mingling_macros/src/chain.rs b/mingling_macros/src/chain.rs index ddedc05..a7be233 100644 --- a/mingling_macros/src/chain.rs +++ b/mingling_macros/src/chain.rs @@ -5,24 +5,11 @@ use proc_macro::TokenStream; use quote::quote; -use syn::parse::{Parse, ParseStream}; use syn::spanned::Spanned; use syn::{ FnArg, Ident, ItemFn, Pat, PatType, ReturnType, Signature, Type, TypePath, parse_macro_input, }; -/// Parses the chain attribute arguments -struct ChainAttribute { - struct_name: Ident, -} - -impl Parse for ChainAttribute { - fn parse(input: ParseStream) -> syn::Result { - let struct_name = input.parse()?; - Ok(ChainAttribute { struct_name }) - } -} - /// Extracts the previous type and parameter name from function arguments fn extract_previous_info(sig: &Signature) -> syn::Result<(Pat, TypePath)> { // The function should have exactly one parameter @@ -72,11 +59,7 @@ fn extract_return_type(sig: &Signature) -> syn::Result { } } -pub fn chain_attr(attr: TokenStream, item: TokenStream) -> TokenStream { - // Parse the attribute arguments - let chain_attr = parse_macro_input!(attr as ChainAttribute); - let struct_name = chain_attr.struct_name; - +pub fn chain_attr(item: TokenStream) -> TokenStream { // Parse the function item let input_fn = parse_macro_input!(item as ItemFn); @@ -113,6 +96,10 @@ pub fn chain_attr(attr: TokenStream, item: TokenStream) -> TokenStream { // 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)* diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs index b32534b..26a7381 100644 --- a/mingling_macros/src/lib.rs +++ b/mingling_macros/src/lib.rs @@ -121,8 +121,8 @@ pub fn r_println(input: TokenStream) -> TokenStream { /// ```ignore /// use mingling_macros::chain; /// -/// #[chain(InitEntry)] -/// pub async fn proc(_: InitBegin) -> mingling::ChainProcess { +/// #[chain] +/// pub async fn init_entry(_: InitBegin) -> mingling::ChainProcess { /// AnyOutput::new::("Init!".to_string().into()).route_chain() /// } /// ``` @@ -138,8 +138,8 @@ pub fn r_println(input: TokenStream) -> TokenStream { /// } /// ``` #[proc_macro_attribute] -pub fn chain(attr: TokenStream, item: TokenStream) -> TokenStream { - chain::chain_attr(attr, item) +pub fn chain(_attr: TokenStream, item: TokenStream) -> TokenStream { + chain::chain_attr(item) } /// Attribute macro for automatically generating structs that implement the `Renderer` trait. @@ -152,8 +152,8 @@ pub fn chain(attr: TokenStream, item: TokenStream) -> TokenStream { /// ```ignore /// use mingling_macros::renderer; /// -/// #[renderer(InitResultRenderer)] -/// fn render(p: InitResult) { +/// #[renderer] +/// fn init_result_render(p: InitResult) { /// let str: String = p.into(); /// r_println!("{}", str); /// } @@ -161,8 +161,8 @@ pub fn chain(attr: TokenStream, item: TokenStream) -> TokenStream { /// /// This generates: /// ```ignore -/// pub struct InitResultRenderer; -/// impl Renderer for InitResultRenderer { +/// pub struct InitResultRender; +/// impl Renderer for InitResultRender { /// type Previous = InitResult; /// /// fn render(p: Self::Previous, r: &mut RenderResult) { @@ -172,8 +172,8 @@ pub fn chain(attr: TokenStream, item: TokenStream) -> TokenStream { /// } /// ``` #[proc_macro_attribute] -pub fn renderer(attr: TokenStream, item: TokenStream) -> TokenStream { - renderer::renderer_attr(attr, item) +pub fn renderer(_attr: TokenStream, item: TokenStream) -> TokenStream { + renderer::renderer_attr(item) } /// Macro for creating a program structure that collects all chains and renderers. diff --git a/mingling_macros/src/node.rs b/mingling_macros/src/node.rs index e56f14b..8cb88d3 100644 --- a/mingling_macros/src/node.rs +++ b/mingling_macros/src/node.rs @@ -28,6 +28,14 @@ pub fn node(input: TokenStream) -> TokenStream { let input_parsed = syn::parse_macro_input!(input as NodeInput); let path_str = input_parsed.path.value(); + // If the input string is empty, return an empty Node + if path_str.is_empty() { + return quote! { + mingling::Node::default() + } + .into(); + } + // Split the path by dots let parts: Vec = path_str .split('.') diff --git a/mingling_macros/src/renderer.rs b/mingling_macros/src/renderer.rs index 14c26df..54a2526 100644 --- a/mingling_macros/src/renderer.rs +++ b/mingling_macros/src/renderer.rs @@ -5,23 +5,8 @@ use proc_macro::TokenStream; use quote::quote; -use syn::parse::{Parse, ParseStream}; use syn::spanned::Spanned; -use syn::{ - FnArg, Ident, ItemFn, Pat, PatType, ReturnType, Signature, Type, TypePath, parse_macro_input, -}; - -/// Parses the renderer attribute arguments -struct RendererAttribute { - struct_name: Ident, -} - -impl Parse for RendererAttribute { - fn parse(input: ParseStream) -> syn::Result { - let struct_name = input.parse()?; - Ok(RendererAttribute { struct_name }) - } -} +use syn::{FnArg, ItemFn, Pat, PatType, ReturnType, Signature, Type, TypePath, parse_macro_input}; /// Extracts the previous type and parameter name from function arguments fn extract_previous_info(sig: &Signature) -> syn::Result<(Pat, TypePath)> { @@ -74,11 +59,7 @@ fn extract_return_type(sig: &Signature) -> syn::Result<()> { } } -pub fn renderer_attr(attr: TokenStream, item: TokenStream) -> TokenStream { - // Parse the attribute arguments - let renderer_attr = parse_macro_input!(attr as RendererAttribute); - let struct_name = renderer_attr.struct_name; - +pub fn renderer_attr(item: TokenStream) -> TokenStream { // Parse the function item let input_fn = parse_macro_input!(item as ItemFn); @@ -115,6 +96,10 @@ pub fn renderer_attr(attr: TokenStream, item: TokenStream) -> TokenStream { // 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 = syn::Ident::new(&pascal_case_name, fn_name.span()); + // Register the renderer in the global list let renderer_entry = quote! { #struct_name => #previous_type, -- cgit