From e8ae63988d562969df47ae6d92129974e7fb6980 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Mon, 20 Jul 2026 00:34:21 +0800 Subject: feat(macros): add extension point mechanism for attribute macros Implement an `extensions` module in `mingling_macros` that allows attribute macros to accept extension identifiers (e.g., `routeify`) which are re-dispatched as outer attributes before the core macro logic runs, enabling extensibility without modifying existing macros --- mingling_macros/src/lib.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'mingling_macros/src/lib.rs') diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs index ea33577..c48d14b 100644 --- a/mingling_macros/src/lib.rs +++ b/mingling_macros/src/lib.rs @@ -159,6 +159,10 @@ mod dispatcher_clap; #[cfg(feature = "extra_macros")] mod entry; mod enum_tag; + +/// Extension point mechanism for attribute macros +/// (`#[chain(routeify, ...)]`, `#[renderer(routeify, ...)]`, etc.) +mod extensions; #[cfg(feature = "extra_macros")] mod group_impl; mod grouped; @@ -877,6 +881,11 @@ pub fn dispatcher(input: TokenStream) -> TokenStream { /// - With the `async` feature, async functions are supported; without it, async functions are rejected. #[proc_macro_attribute] pub fn chain(attr: TokenStream, item: TokenStream) -> TokenStream { + // Extension point: if attr contains extension identifiers like `routeify`, + // re-dispatch as #[ext1] #[ext2] #[chain] fn ... + if let Some(redispatch) = extensions::try_redispatch_simple(attr.clone(), &item, "chain") { + return redispatch; + } chain::chain_attr(attr, item) } @@ -944,6 +953,9 @@ pub fn chain(attr: TokenStream, item: TokenStream) -> TokenStream { /// ``` #[proc_macro_attribute] pub fn renderer(attr: TokenStream, item: TokenStream) -> TokenStream { + if let Some(redispatch) = extensions::try_redispatch_simple(attr.clone(), &item, "renderer") { + return redispatch; + } renderer::renderer_attr(attr, item) } @@ -998,6 +1010,9 @@ pub fn renderer(attr: TokenStream, item: TokenStream) -> TokenStream { #[cfg(feature = "comp")] #[proc_macro_attribute] pub fn completion(attr: TokenStream, item: TokenStream) -> TokenStream { + if let Some(redispatch) = extensions::try_redispatch_completion(attr.clone(), &item) { + return redispatch; + } completion::completion_attr(attr, item) } @@ -1251,7 +1266,10 @@ pub fn register_dispatcher(input: TokenStream) -> TokenStream { /// /// [`BasicProgramSetup`]: https://docs.rs/mingling/latest/mingling/setup/struct.BasicProgramSetup.html #[proc_macro_attribute] -pub fn help(_attr: TokenStream, item: TokenStream) -> TokenStream { +pub fn help(attr: TokenStream, item: TokenStream) -> TokenStream { + if let Some(redispatch) = extensions::try_redispatch_simple(attr.clone(), &item, "help") { + return redispatch; + } help::help_attr(item) } -- cgit