From d19e5d84ee21502fd3440511d4ffb1ee1f49d3b2 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 4 Feb 2026 00:27:16 +0800 Subject: Refactor build system and implement complete renderer system - Split monolithic build.rs into modular async generators - Add renderer override system with type-safe dispatch - Implement command template macro for consistent command definitions - Add proc-macro crates for command and renderer systems - Reorganize directory structure for better separation of concerns - Update documentation to reflect new architecture --- macros/cmd_system_macros/src/lib.rs | 92 +++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 macros/cmd_system_macros/src/lib.rs (limited to 'macros/cmd_system_macros/src/lib.rs') diff --git a/macros/cmd_system_macros/src/lib.rs b/macros/cmd_system_macros/src/lib.rs new file mode 100644 index 0000000..e585782 --- /dev/null +++ b/macros/cmd_system_macros/src/lib.rs @@ -0,0 +1,92 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{Expr, ItemFn, Lit, Type, parse_macro_input, parse_quote}; + +#[proc_macro_attribute] +pub fn exec(_attr: TokenStream, item: TokenStream) -> TokenStream { + let input_fn = parse_macro_input!(item as ItemFn); + let fn_block = &input_fn.block; + + let mut output_mappings = Vec::new(); + extract_cmd_output_macros(fn_block, &mut output_mappings); + + let mapping_fn = generate_mapping_function(&output_mappings); + + let expanded = quote! { + #input_fn + + #mapping_fn + }; + + TokenStream::from(expanded) +} + +fn extract_cmd_output_macros(block: &syn::Block, mappings: &mut Vec<(String, syn::Type)>) { + use syn::visit::Visit; + + struct CmdOutputVisitor<'a> { + mappings: &'a mut Vec<(String, syn::Type)>, + } + + impl<'a> syn::visit::Visit<'a> for CmdOutputVisitor<'a> { + fn visit_macro(&mut self, mac: &'a syn::Macro) { + if mac.path.is_ident("cmd_output") { + let nested_result = syn::parse2::(mac.tokens.clone()); + if let Ok(nested) = nested_result { + if nested.elems.len() < 2 { + syn::visit::visit_macro(self, mac); + return; + } + + let first_elem = &nested.elems[0]; + let second_elem = &nested.elems[1]; + + let type_path_opt = match first_elem { + Expr::Path(path) => Some(path), + _ => None, + }; + + let lit_str_opt = match second_elem { + Expr::Lit(lit) => match &lit.lit { + Lit::Str(lit_str) => Some(lit_str), + _ => None, + }, + _ => None, + }; + + if let (Some(type_path), Some(lit_str)) = (type_path_opt, lit_str_opt) { + let type_name = lit_str.value(); + if let Some(type_ident) = type_path.path.get_ident() { + let ty: Type = parse_quote!(#type_ident); + self.mappings.push((type_name, ty)); + } + } + } + } + + syn::visit::visit_macro(self, mac); + } + } + + let mut visitor = CmdOutputVisitor { mappings }; + visitor.visit_block(block); +} + +fn generate_mapping_function(mappings: &[(String, syn::Type)]) -> proc_macro2::TokenStream { + let mapping_entries: Vec<_> = mappings + .iter() + .map(|(name, ty)| { + quote! { + map.insert(#name.to_string(), std::any::TypeId::of::<#ty>()); + } + }) + .collect(); + + quote! { + fn get_output_type_mapping() -> std::collections::HashMap { + let mut map = std::collections::HashMap::new(); + #(#mapping_entries)* + map + } + } +} -- cgit