Skip to main content

tx_di_macros/
lib.rs

1//! tx-di-macros — proc_macro 支持
2//!
3//! 提供 `#[derive(Component)]` 宏。
4//! `#[tx_cst]` 和 `#[component]` 是 derive 辅助属性。
5//!
6//! # 模块结构
7//!
8//! - `attr` — 属性解析(`#[component(...)]`、`#[tx_cst(...)]`)
9//! - `classify` — 字段分类(`FieldKind`)
10//! - `codegen` — 代码生成(`impl Component` + linkme 注册条目)
11//! - `type_utils` — 类型检测工具(`Arc<T>`、`Option<T>`、`Arc<dyn Trait>`)
12//! - `name_utils` — 命名转换工具(驼峰 ↔ 蛇形)
13
14mod attr;
15mod classify;
16mod codegen;
17mod intercept_macro;
18mod name_utils;
19mod type_utils;
20
21use proc_macro::TokenStream;
22
23/// `#[derive(Component)]` — 组件 derive 宏
24///
25/// 为结构体自动生成 `Component` trait 实现和 `ComponentMeta` 注册条目。
26///
27/// # 辅助属性
28///
29/// ## `#[component(...)]` — 结构体属性
30///
31/// | 参数 | 说明 |
32/// |------|------|
33/// | `scope = Prototype` | 原型作用域(默认 `Singleton`) |
34/// | `init` | 自定义 inner_init 回调(见下方生命周期表) |
35/// | `app_init` | 自定义 init 回调 |
36/// | `app_async_init` | 自定义 async_init 回调 |
37/// | `app_async_run` | 自定义 async_run 回调 |
38/// | `shutdown` | 自定义 shutdown 回调 |
39/// | `conf` / `conf = "key"` | 配置组件 |
40/// | `as_trait = dyn Trait` | Trait 实现注册 |
41/// | `init_sort = N` | 初始化排序(值越小越先执行,默认 10000) |
42/// | `intercept(T1, T2, ..)` | AOP 拦截器(从容器注入 `Interceptor` 组件,见 `#[intercept]`) |
43///
44/// ## `#[tx_cst(...)]` — 字段属性
45///
46/// | 写法 | 语义 |
47/// |------|------|
48/// | `#[tx_cst(expr)]` | 用表达式赋值 |
49/// | `#[tx_cst(skip)]` | 跳过,使用 Default |
50///
51/// # 生命周期回调
52///
53/// 所有回调都是**可选的**——只有标记对应属性后才需要实现。不标记则使用 trait 默认实现。
54///
55/// 回调函数名与 `#[component(...)]` 属性名**保持一致**,便于记忆:
56///
57/// | `#[component(...)]` | 回调函数签名 | 覆写的 trait 方法 | 阶段 |
58/// |---|---|---|---|
59/// | `init` | `fn init(&mut self, store: &Store) -> RIE<()>` | `inner_init` | build 后、注册前 |
60/// | `app_init` | `fn app_init(comp: Arc<Self>, app: &Arc<App>) -> RIE<()>` | `init` | 同步初始化 |
61/// | `app_async_init` | `fn app_async_init(comp: Arc<Self>, app: &Arc<App>) -> BoxFuture<RIE<()>>` | `async_init` | 异步初始化 |
62/// | `app_async_run` | `fn app_async_run(comp: Arc<Self>, app: &Arc<App>, token: CancellationToken) -> BoxFuture<RIE<()>>` | `async_run` | 后台运行 |
63/// | `shutdown` | `fn shutdown(&self)` | `shutdown` | 优雅关闭 |
64///
65/// > **注意**:宏生成的覆写方法都带有 `#[inline]` 属性。如果回调函数为空或仅含简单逻辑,
66/// > 编译器会直接内联消除调用开销。同时,生成的代码使用 `self::` 前缀调用回调,
67/// > 即使 `init` / `shutdown` 与 trait 方法同名也不会冲突。
68///
69/// # 完整示例
70///
71/// ```ignore
72/// use tx_di_core::{Component, App, Store, RIE, BoxFuture, CancellationToken};
73/// use std::sync::Arc;
74///
75/// #[derive(Component)]
76/// #[component(
77///     init,                    // inner_init 回调
78///     app_init,                // init 回调
79///     app_async_init,          // async_init 回调
80///     app_async_run,           // async_run 回调
81///     shutdown                 // shutdown 回调
82/// )]
83/// pub struct DatabaseService {
84///     pool: Arc<DbPool>,
85/// }
86///
87/// // ── inner_init:build 后立即调用 ──
88/// fn init(&mut self, store: &Store) -> RIE<()> {
89///     // self 可写,可访问 store 做额外注入
90///     Ok(())
91/// }
92///
93/// // ── init:同步初始化阶段 ──
94/// fn app_init(comp: Arc<Self>, app: &Arc<App>) -> RIE<()> {
95///     // comp 是 Arc<Self>,可通过 comp.field 访问成员
96///     tracing::info!("init: pool size = {}", comp.pool.size());
97///     Ok(())
98/// }
99///
100/// // ── async_init:异步初始化阶段 ──
101/// fn app_async_init(comp: Arc<Self>, app: &Arc<App>) -> BoxFuture<RIE<()>> {
102///     Box::pin(async move {
103///         comp.pool.connect().await?;
104///         Ok(())
105///     })
106/// }
107///
108/// // ── async_run:后台长期任务 ──
109/// fn app_async_run(comp: Arc<Self>, app: &Arc<App>, token: CancellationToken) -> BoxFuture<RIE<()>> {
110///     Box::pin(async move {
111///         loop {
112///             tokio::select! {
113///                 _ = token.cancelled() => break,
114///                 _ = comp.pool.health_check() => {},
115///             }
116///         }
117///         Ok(())
118///     })
119/// }
120///
121/// // ── shutdown:优雅关闭 ──
122/// fn shutdown(&self) {
123///     self.pool.close();
124/// }
125/// ```
126#[proc_macro_derive(Component, attributes(component, tx_cst))]
127pub fn derive_component(input: TokenStream) -> TokenStream {
128    codegen::derive_component(input)
129}
130
131/// `#[intercept]` — 标记需要 AOP 拦截的方法
132///
133/// 必须在 `#[component(intercept(...))]` 标记的结构体的 impl 块中使用。
134/// 生成的包裹代码会调用拦截器链的 before/after 回调。
135///
136/// # 参数覆写
137///
138/// 拦截器可通过 `ctx.get_raw_mut::<T>(index)` 修改方法参数,
139/// `#[intercept]` 生成的代码会自动提取被覆写的参数传入业务方法。
140///
141/// # Panics
142///
143/// 如果拦截器的 `before` 返回 `Err`,方法不会执行且 panic。
144#[proc_macro_attribute]
145pub fn intercept(attr: TokenStream, item: TokenStream) -> TokenStream {
146    intercept_macro::intercept_impl(attr, item)
147}