Skip to main content

mf_derive/
lib.rs

1//! ModuForge-RS 宏扩展模块
2//!
3//! 提供 #[derive(Node)] 和 #[derive(Mark)] 派生宏,
4//! 支持声明式的节点和标记定义,简化 ModuForge-RS 框架的使用。
5//!
6//! # 功能特性
7//!
8//! - **Node 派生宏**: 自动生成 `to_node()` 方法,将结构体转换为 mf_core::node::Node
9//! - **Mark 派生宏**: 自动生成 `to_mark()` 方法,将结构体转换为 mf_core::mark::Mark
10//! - **编译时验证**: 在编译期检查属性配置和类型兼容性
11//! - **友好错误消息**: 提供详细的编译错误信息和修复建议
12//!
13//! # 设计原则
14//!
15//! 此模块严格遵循 SOLID 设计原则:
16//! - **单一职责原则 (SRP)**: 每个模块只负责一个明确的功能
17//! - **接口隔离原则 (ISP)**: 提供精简、专用的接口
18//! - **开闭原则 (OCP)**: 通过插件系统支持扩展
19//! - **里氏替换原则 (LSP)**: 确保实现类型的可替换性
20
21use proc_macro::TokenStream;
22use quote::quote;
23use syn::{parse_macro_input, DeriveInput};
24
25// 内部模块声明 - proc-macro crate 不能导出这些模块,只能内部使用
26mod command;
27mod common;
28mod converter;
29mod generator;
30mod mark;
31mod node;
32mod parser;
33
34/// 插件状态派生宏
35///
36/// 为结构体实现 Resource trait,用于依赖注入系统。
37/// 这是现有功能,保持不变以确保向后兼容性。
38#[proc_macro_derive(PState)]
39pub fn derive_plugin_state(input: TokenStream) -> TokenStream {
40    let input = parse_macro_input!(input as DeriveInput);
41    let name = input.ident;
42
43    let expanded = quote! {
44        impl Resource for #name {}
45    };
46
47    TokenStream::from(expanded)
48}
49
50/// Node 派生宏
51///
52/// 为结构体生成 `to_node()` 方法,将结构体实例转换为 `mf_core::node::Node`。
53///
54/// # 支持的属性
55///
56/// - `#[node_type = "类型名"]` - 必需,指定节点类型标识符
57/// - `#[marks = "mark1 mark2"]` - 可选,指定支持的标记类型列表
58/// - `#[content = "内容表达式"]` - 可选,指定内容约束表达式
59/// - `#[attr]` - 字段级属性,标记字段作为节点属性
60///
61/// # 示例
62///
63/// ```rust
64/// use mf_derive::Node;
65///
66/// #[derive(Node)]
67/// #[node_type = "project"]
68/// #[marks = "color bold"]
69/// #[content = "text*"]
70/// pub struct ProjectNode {
71///     #[attr]
72///     name: String,
73///     
74///     #[attr]
75///     description: Option<String>,
76/// }
77///
78/// // 使用生成的方法
79/// let project = ProjectNode {
80///     name: "示例项目".to_string(),
81///     description: Some("这是一个示例项目".to_string()),
82/// };
83/// let node = project.to_node();
84/// ```
85///
86/// # 设计原则体现
87///
88/// - **单一职责**: 只负责 Node 相关的派生宏功能
89/// - **开闭原则**: 通过属性配置支持扩展,无需修改代码
90/// - **接口隔离**: 提供专门的 Node 转换接口
91#[proc_macro_derive(
92    Node,
93    attributes(node_type, desc, marks, content, attr, id)
94)]
95pub fn derive_node(input: TokenStream) -> TokenStream {
96    let input = parse_macro_input!(input as DeriveInput);
97
98    // 使用带错误恢复的处理函数,确保友好的编译错误消息
99    let result = node::derive_impl::process_derive_node_with_recovery(input);
100    TokenStream::from(result)
101}
102
103/// Mark 派生宏
104///
105/// 为结构体生成 `to_mark()` 方法,将结构体实例转换为 `mf_core::mark::Mark`。
106///
107/// # 支持的属性
108///
109/// - `#[mark_type = "类型名"]` - 必需,指定标记类型标识符
110/// - `#[attr]` - 字段级属性,标记字段作为标记属性
111///
112/// # 示例
113///
114/// ```rust
115/// use mf_derive::Mark;
116///
117/// #[derive(Mark)]
118/// #[mark_type = "emphasis"]
119/// pub struct EmphasisMark {
120///     #[attr]
121///     level: i32,
122///     
123///     #[attr]
124///     color: Option<String>,
125/// }
126///
127/// // 使用生成的方法
128/// let emphasis = EmphasisMark {
129///     level: 2,
130///     color: Some("red".to_string()),
131/// };
132/// let mark = emphasis.to_mark();
133/// ```
134///
135/// # 设计原则体现
136///
137/// - **单一职责**: 只负责 Mark 相关的派生宏功能
138/// - **里氏替换原则**: 生成的 Mark 实例可完全替换手动创建的实例
139/// - **接口隔离**: 提供专门的 Mark 转换接口
140#[proc_macro_derive(Mark, attributes(mark_type, attr))]
141pub fn derive_mark(input: TokenStream) -> TokenStream {
142    let input = parse_macro_input!(input as DeriveInput);
143
144    // 使用带错误恢复的处理函数,确保友好的编译错误消息
145    let result = mark::derive_impl::process_derive_mark_with_recovery(input);
146    TokenStream::from(result)
147}
148
149#[proc_macro_attribute]
150pub fn impl_command(
151    attr: TokenStream,
152    item: TokenStream,
153) -> TokenStream {
154    command::impl_command(attr, item)
155}