summaryrefslogtreecommitdiff
path: root/macros/cmd_system_macros/src
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-02-04 00:27:16 +0800
committer魏曹先生 <1992414357@qq.com>2026-02-04 00:27:16 +0800
commitd19e5d84ee21502fd3440511d4ffb1ee1f49d3b2 (patch)
treefb8efef6f8e9a26c5b60d4ac220b11d6c6f0775e /macros/cmd_system_macros/src
parent7ee0d3f20c875e7405bb8442c5eb0228d1599a03 (diff)
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
Diffstat (limited to 'macros/cmd_system_macros/src')
-rw-r--r--macros/cmd_system_macros/src/lib.rs92
1 files changed, 92 insertions, 0 deletions
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::<syn::ExprTuple>(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<String, std::any::TypeId> {
+ let mut map = std::collections::HashMap::new();
+ #(#mapping_entries)*
+ map
+ }
+ }
+}