aboutsummaryrefslogtreecommitdiff
path: root/mingling_pathf/src/patterns/groupped_derive.rs
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-06-28 09:06:08 +0800
committer魏曹先生 <1992414357@qq.com>2026-06-28 09:06:08 +0800
commit748c14588cf1c31c8b8d60a9c94349c0173ef607 (patch)
tree4c09bfafd93b629a68f0f78902a33e8dd9ef18d1 /mingling_pathf/src/patterns/groupped_derive.rs
parent50f2d767e2d07685e49fb7deae68d506ea11a79d (diff)
feat(pathf): add build-time type path resolution system
Add `mingling_pathf` sub-crate and `pathf` feature for automatic resolution of Mingling type module paths at build time. Scans source files, identifies macro invocations via pattern matchers, and generates mapping files consumed by `gen_program!()`.
Diffstat (limited to 'mingling_pathf/src/patterns/groupped_derive.rs')
-rw-r--r--mingling_pathf/src/patterns/groupped_derive.rs93
1 files changed, 93 insertions, 0 deletions
diff --git a/mingling_pathf/src/patterns/groupped_derive.rs b/mingling_pathf/src/patterns/groupped_derive.rs
new file mode 100644
index 0000000..9f7301d
--- /dev/null
+++ b/mingling_pathf/src/patterns/groupped_derive.rs
@@ -0,0 +1,93 @@
+use syn::Item;
+
+use crate::pattern_analyzer::{AnalyzeItem, AnalyzePattern};
+
+/// Matches `#[derive(Groupped)]` and `#[derive(GrouppedSerialize)]`.
+///
+/// Covers the forms:
+/// - `#[derive(Groupped)] struct T { ... }`
+/// - `#[derive(Groupped, Serialize, ...)] struct T { ... }`
+/// - `#[derive(GrouppedSerialize)] struct T { ... }`
+pub struct GrouppedDerivePattern;
+
+impl AnalyzePattern for GrouppedDerivePattern {
+ fn contains(&self, content: &str) -> bool {
+ content.contains("Groupped")
+ }
+
+ fn analyze(&self, content: &str) -> Vec<AnalyzeItem> {
+ let Ok(syntax) = syn::parse_file(content) else {
+ return Vec::new();
+ };
+
+ let mut items = Vec::new();
+
+ for item in &syntax.items {
+ match item {
+ Item::Struct(s) => {
+ if has_groupped_derive(&s.attrs) {
+ items.push(AnalyzeItem {
+ module: String::new(),
+ item_name: s.ident.to_string(),
+ });
+ }
+ }
+ Item::Enum(e) => {
+ if has_groupped_derive(&e.attrs) {
+ items.push(AnalyzeItem {
+ module: String::new(),
+ item_name: e.ident.to_string(),
+ });
+ }
+ }
+ Item::Union(u) => {
+ if has_groupped_derive(&u.attrs) {
+ items.push(AnalyzeItem {
+ module: String::new(),
+ item_name: u.ident.to_string(),
+ });
+ }
+ }
+ Item::Mod(item_mod) => {
+ if let Some((_, nested)) = &item_mod.content {
+ for n in nested {
+ match n {
+ Item::Struct(s) if has_groupped_derive(&s.attrs) => {
+ items.push(AnalyzeItem {
+ module: item_mod.ident.to_string(),
+ item_name: s.ident.to_string(),
+ });
+ }
+ Item::Enum(e) if has_groupped_derive(&e.attrs) => {
+ items.push(AnalyzeItem {
+ module: item_mod.ident.to_string(),
+ item_name: e.ident.to_string(),
+ });
+ }
+ _ => {}
+ }
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+
+ items
+ }
+}
+
+fn has_groupped_derive(attrs: &[syn::Attribute]) -> bool {
+ attrs.iter().any(|attr| {
+ if attr.path().is_ident("derive") {
+ attr.parse_args::<syn::MetaList>().ok().is_some_and(|meta| {
+ meta.path.segments.iter().any(|seg| {
+ let name = seg.ident.to_string();
+ name == "Groupped" || name == "GrouppedSerialize"
+ })
+ })
+ } else {
+ false
+ }
+ })
+}