unistore_macros/lib.rs
1//! unistore-macros - Procedural macros for unistore framework
2//!
3//! 提供 `#[derive(Event)]` 等宏,简化事件和组件定义。
4//!
5//! # 示例
6//!
7//! ```ignore
8//! use unistore::sdk::events::Event;
9//! use unistore_macros::Event;
10//!
11//! #[derive(Clone, Event)]
12//! struct OrderCreated {
13//! order_id: u64,
14//! amount: f64,
15//! }
16//!
17//! // 自定义事件名称
18//! #[derive(Clone, Event)]
19//! #[event(name = "user.logged_in")]
20//! struct UserLoggedIn {
21//! user_id: u64,
22//! }
23//! ```
24
25use proc_macro::TokenStream;
26use quote::quote;
27use syn::{parse_macro_input, DeriveInput, Expr, ExprLit, Lit, Meta};
28
29/// 派生 Event trait 的宏
30///
31/// 自动实现 `unistore::sdk::reactive::Event` trait。
32///
33/// # 属性
34///
35/// - `#[event(name = "custom_name")]` - 自定义事件名称(可选)
36///
37/// # 约束
38///
39/// 使用此宏的类型必须同时 derive `Clone`:
40/// ```ignore
41/// #[derive(Clone, Event)] // Clone 是必须的
42/// struct MyEvent { ... }
43/// ```
44///
45/// # 示例
46///
47/// ## 基本用法(事件名 = 类型名)
48/// ```ignore
49/// #[derive(Clone, Event)]
50/// struct OrderCreated {
51/// order_id: u64,
52/// }
53/// // event_name() 返回 "OrderCreated"
54/// ```
55///
56/// ## 自定义事件名
57/// ```ignore
58/// #[derive(Clone, Event)]
59/// #[event(name = "order.created")]
60/// struct OrderCreated {
61/// order_id: u64,
62/// }
63/// // event_name() 返回 "order.created"
64/// ```
65#[proc_macro_derive(Event, attributes(event))]
66pub fn derive_event(input: TokenStream) -> TokenStream {
67 let input = parse_macro_input!(input as DeriveInput);
68
69 let name = &input.ident;
70 let name_str = name.to_string();
71
72 // 查找 #[event(name = "...")] 属性
73 let custom_name = find_event_name(&input);
74 let event_name = custom_name.unwrap_or(name_str);
75
76 // 生成 impl 代码
77 let expanded = quote! {
78 impl ::unistore::sdk::events::Event for #name {
79 fn event_name() -> &'static str {
80 #event_name
81 }
82 }
83 };
84
85 TokenStream::from(expanded)
86}
87
88/// 从属性中提取自定义事件名
89fn find_event_name(input: &DeriveInput) -> Option<String> {
90 for attr in &input.attrs {
91 if !attr.path().is_ident("event") {
92 continue;
93 }
94
95 // 解析 #[event(name = "...")]
96 if let Ok(nested) = attr
97 .parse_args_with(syn::punctuated::Punctuated::<Meta, syn::Token![,]>::parse_terminated)
98 {
99 for meta in nested {
100 if let Meta::NameValue(nv) = meta {
101 if nv.path.is_ident("name") {
102 if let Expr::Lit(ExprLit {
103 lit: Lit::Str(lit_str),
104 ..
105 }) = &nv.value
106 {
107 return Some(lit_str.value());
108 }
109 }
110 }
111 }
112 }
113 }
114
115 None
116}