aboutsummaryrefslogtreecommitdiff
path: root/mingling_pathf/src/patterns
diff options
context:
space:
mode:
Diffstat (limited to 'mingling_pathf/src/patterns')
-rw-r--r--mingling_pathf/src/patterns/basic_struct.rs13
-rw-r--r--mingling_pathf/src/patterns/chain.rs10
-rw-r--r--mingling_pathf/src/patterns/completion.rs10
-rw-r--r--mingling_pathf/src/patterns/dispatcher.rs23
-rw-r--r--mingling_pathf/src/patterns/dispatcher_clap.rs71
-rw-r--r--mingling_pathf/src/patterns/group.rs116
-rw-r--r--mingling_pathf/src/patterns/grouped_derive.rs89
-rw-r--r--mingling_pathf/src/patterns/groupped_derive.rs98
-rw-r--r--mingling_pathf/src/patterns/help.rs10
-rw-r--r--mingling_pathf/src/patterns/pack.rs15
-rw-r--r--mingling_pathf/src/patterns/renderer.rs10
11 files changed, 268 insertions, 197 deletions
diff --git a/mingling_pathf/src/patterns/basic_struct.rs b/mingling_pathf/src/patterns/basic_struct.rs
index 09e8e70..9218d65 100644
--- a/mingling_pathf/src/patterns/basic_struct.rs
+++ b/mingling_pathf/src/patterns/basic_struct.rs
@@ -28,20 +28,17 @@ impl AnalyzePattern for BasicStructPattern {
match item {
// Root-level struct
Item::Struct(s) => {
- items.push(AnalyzeItem {
- module: String::new(),
- item_name: s.ident.to_string(),
- });
+ items.push(AnalyzeItem::local(String::new(), s.ident.to_string()));
}
// Struct within inline modules
Item::Mod(item_mod) => {
if let Some((_, nested)) = &item_mod.content {
for n in nested {
if let syn::Item::Struct(s) = n {
- items.push(AnalyzeItem {
- module: item_mod.ident.to_string(),
- item_name: s.ident.to_string(),
- });
+ items.push(AnalyzeItem::local(
+ item_mod.ident.to_string(),
+ s.ident.to_string(),
+ ));
}
}
}
diff --git a/mingling_pathf/src/patterns/chain.rs b/mingling_pathf/src/patterns/chain.rs
index 6393440..2e95db2 100644
--- a/mingling_pathf/src/patterns/chain.rs
+++ b/mingling_pathf/src/patterns/chain.rs
@@ -18,7 +18,7 @@ pub struct ChainPattern;
impl AnalyzePattern for ChainPattern {
fn contains(&self, content: &str) -> bool {
- content.contains("chain]")
+ content.contains("[chain") || content.contains("chain]")
}
fn analyze(&self, content: &str) -> Vec<AnalyzeItem> {
@@ -44,10 +44,10 @@ fn collect_from_item(item: &Item, current_mod: &str, items: &mut Vec<AnalyzeItem
match item {
Item::Fn(f) if has_attr(&f.attrs, "chain") => {
let fn_name = f.sig.ident.to_string();
- items.push(AnalyzeItem {
- module: current_mod.to_string(),
- item_name: internal_name(&fn_name),
- });
+ items.push(AnalyzeItem::local(
+ current_mod.to_string(),
+ internal_name(&fn_name),
+ ));
}
Item::Mod(item_mod) => {
if let Some((_, nested)) = &item_mod.content {
diff --git a/mingling_pathf/src/patterns/completion.rs b/mingling_pathf/src/patterns/completion.rs
index 5427b93..cff62e0 100644
--- a/mingling_pathf/src/patterns/completion.rs
+++ b/mingling_pathf/src/patterns/completion.rs
@@ -13,7 +13,7 @@ pub struct CompletionPattern;
impl AnalyzePattern for CompletionPattern {
fn contains(&self, content: &str) -> bool {
- content.contains("completion(")
+ content.contains("completion(") || content.contains("[completion")
}
fn analyze(&self, content: &str) -> Vec<AnalyzeItem> {
@@ -37,10 +37,10 @@ fn collect_from_item(item: &Item, current_mod: &str, items: &mut Vec<AnalyzeItem
match item {
Item::Fn(f) if has_attr(&f.attrs, "completion") => {
let fn_name = f.sig.ident.to_string();
- items.push(AnalyzeItem {
- module: current_mod.to_string(),
- item_name: internal_name(&fn_name),
- });
+ items.push(AnalyzeItem::local(
+ current_mod.to_string(),
+ internal_name(&fn_name),
+ ));
}
Item::Mod(item_mod) => {
if let Some((_, nested)) = &item_mod.content {
diff --git a/mingling_pathf/src/patterns/dispatcher.rs b/mingling_pathf/src/patterns/dispatcher.rs
index 6796a2c..cedad9f 100644
--- a/mingling_pathf/src/patterns/dispatcher.rs
+++ b/mingling_pathf/src/patterns/dispatcher.rs
@@ -20,10 +20,18 @@ use crate::pattern_analyzer::{AnalyzeItem, AnalyzePattern};
/// - `CMD*` — the dispatcher struct (always)
/// - `__internal_dispatcher_*` — dispatch tree static (when `use_dispatch_tree` is true)
pub struct DispatcherPattern {
+ /// Whether the dispatcher generates a dispatch tree static (`__internal_dispatcher_*`).
pub use_dispatch_tree: bool,
}
impl DispatcherPattern {
+ /// Creates a new `DispatcherPattern`.
+ ///
+ /// # Arguments
+ ///
+ /// * `use_dispatch_tree` — when `true`, the generated dispatcher also produces a
+ /// `__internal_dispatcher_*` static dispatch tree item. Set this based on whether
+ /// your macro invocation includes the `use_dispatch_tree` configuration.
pub fn new(use_dispatch_tree: bool) -> Self {
Self { use_dispatch_tree }
}
@@ -103,27 +111,18 @@ fn extract_all_types(
// Entry type — always
if let Some(ref entry) = entry_struct {
- items.push(AnalyzeItem {
- module: module.to_string(),
- item_name: entry.clone(),
- });
+ items.push(AnalyzeItem::local(module.to_string(), entry.clone()));
}
// CMD type — always
if let Some(ref cmd) = cmd_struct {
- items.push(AnalyzeItem {
- module: module.to_string(),
- item_name: cmd.clone(),
- });
+ items.push(AnalyzeItem::local(module.to_string(), cmd.clone()));
}
// __internal_dispatcher_* — when configured
if use_dispatch_tree {
let internal_name = format!("__internal_dispatcher_{}", snake_case(&cmd_name));
- items.push(AnalyzeItem {
- module: module.to_string(),
- item_name: internal_name,
- });
+ items.push(AnalyzeItem::local(module.to_string(), internal_name));
}
items
diff --git a/mingling_pathf/src/patterns/dispatcher_clap.rs b/mingling_pathf/src/patterns/dispatcher_clap.rs
index 1a86ad5..25a7093 100644
--- a/mingling_pathf/src/patterns/dispatcher_clap.rs
+++ b/mingling_pathf/src/patterns/dispatcher_clap.rs
@@ -29,10 +29,16 @@ use crate::pattern_analyzer::{AnalyzeItem, AnalyzePattern};
/// - `#[dispatcher_clap("greet", CMDGreet, help = true)] struct EntryGreet { ... }`
/// - `#[dispatcher_clap("greet", CMDGreet, error = ErrorGreet, help = true)] struct EntryGreet { ... }`
pub struct DispatcherClapPattern {
+ /// Whether to include the `__internal_dispatcher_*` dispatch tree static in the analysis.
pub use_dispatch_tree: bool,
}
impl DispatcherClapPattern {
+ /// Creates a new `DispatcherClapPattern` with the given configuration.
+ ///
+ /// # Parameters
+ /// - `use_dispatch_tree`: When `true`, enables analysis of the `__internal_dispatcher_*`
+ /// static dispatch tree for each matched command.
pub fn new(use_dispatch_tree: bool) -> Self {
Self { use_dispatch_tree }
}
@@ -55,10 +61,7 @@ impl AnalyzePattern for DispatcherClapPattern {
Item::Struct(s) if has_attr(&s.attrs, "dispatcher_clap") => {
// Entry type (struct name) — always
let entry_name = s.ident.to_string();
- items.push(AnalyzeItem {
- module: String::new(),
- item_name: entry_name.clone(),
- });
+ items.push(AnalyzeItem::local(String::new(), entry_name.clone()));
// Parse the attribute to extract CMD, error, and help info
if let Some(attr) = s.attrs.iter().find(|a| {
@@ -73,18 +76,12 @@ impl AnalyzePattern for DispatcherClapPattern {
// CMD type — always
if let Some(ref cmd) = parsed.cmd_type {
- items.push(AnalyzeItem {
- module: String::new(),
- item_name: cmd.clone(),
- });
+ items.push(AnalyzeItem::local(String::new(), cmd.clone()));
}
// Error type — if error = TypeName
if let Some(ref err) = parsed.error_type {
- items.push(AnalyzeItem {
- module: String::new(),
- item_name: err.clone(),
- });
+ items.push(AnalyzeItem::local(String::new(), err.clone()));
}
// Help internal struct — if help = true
@@ -94,10 +91,7 @@ impl AnalyzePattern for DispatcherClapPattern {
let help_fn = format!("__{}_help", just_fmt::snake_case!(cmd));
let help_struct =
format!("__internal_help_{}", just_fmt::snake_case!(&help_fn));
- items.push(AnalyzeItem {
- module: String::new(),
- item_name: help_struct,
- });
+ items.push(AnalyzeItem::local(String::new(), help_struct));
}
// __internal_dispatcher_* — when configured
@@ -108,10 +102,7 @@ impl AnalyzePattern for DispatcherClapPattern {
"__internal_dispatcher_{}",
just_fmt::snake_case!(cmd_name)
);
- items.push(AnalyzeItem {
- module: String::new(),
- item_name: internal_name,
- });
+ items.push(AnalyzeItem::local(String::new(), internal_name));
}
}
}
@@ -122,10 +113,10 @@ impl AnalyzePattern for DispatcherClapPattern {
&& has_attr(&s.attrs, "dispatcher_clap")
{
let entry_name = s.ident.to_string();
- items.push(AnalyzeItem {
- module: item_mod.ident.to_string(),
- item_name: entry_name.clone(),
- });
+ items.push(AnalyzeItem::local(
+ item_mod.ident.to_string(),
+ entry_name.clone(),
+ ));
if let Some(attr) = s.attrs.iter().find(|a| {
a.path()
@@ -139,17 +130,17 @@ impl AnalyzePattern for DispatcherClapPattern {
let parsed = parse_dispatcher_clap_args(&args_str);
if let Some(ref cmd) = parsed.cmd_type {
- items.push(AnalyzeItem {
- module: item_mod.ident.to_string(),
- item_name: cmd.clone(),
- });
+ items.push(AnalyzeItem::local(
+ item_mod.ident.to_string(),
+ cmd.clone(),
+ ));
}
if let Some(ref err) = parsed.error_type {
- items.push(AnalyzeItem {
- module: item_mod.ident.to_string(),
- item_name: err.clone(),
- });
+ items.push(AnalyzeItem::local(
+ item_mod.ident.to_string(),
+ err.clone(),
+ ));
}
// Help internal struct — same naming rule as root level
@@ -162,10 +153,10 @@ impl AnalyzePattern for DispatcherClapPattern {
"__internal_help_{}",
just_fmt::snake_case!(&help_fn)
);
- items.push(AnalyzeItem {
- module: item_mod.ident.to_string(),
- item_name: help_struct,
- });
+ items.push(AnalyzeItem::local(
+ item_mod.ident.to_string(),
+ help_struct,
+ ));
}
// __internal_dispatcher_* — when configured
@@ -176,10 +167,10 @@ impl AnalyzePattern for DispatcherClapPattern {
"__internal_dispatcher_{}",
just_fmt::snake_case!(cmd_name)
);
- items.push(AnalyzeItem {
- module: item_mod.ident.to_string(),
- item_name: internal_name,
- });
+ items.push(AnalyzeItem::local(
+ item_mod.ident.to_string(),
+ internal_name,
+ ));
}
}
}
diff --git a/mingling_pathf/src/patterns/group.rs b/mingling_pathf/src/patterns/group.rs
index 0e4b50d..0f9ecff 100644
--- a/mingling_pathf/src/patterns/group.rs
+++ b/mingling_pathf/src/patterns/group.rs
@@ -2,7 +2,10 @@
//! extracts the type name or alias defined within them.
//! This is used to track type groups for code generation or analysis.
+use std::collections::HashMap;
+
use syn::Item;
+use syn::UseTree;
use crate::pattern_analyzer::{AnalyzeItem, AnalyzePattern};
@@ -25,6 +28,9 @@ impl AnalyzePattern for GroupPattern {
return Vec::new();
};
+ // Collect `use` imports at the file level
+ let imports = collect_use_imports(&syntax.items);
+
let mut items = Vec::new();
for item in &syntax.items {
@@ -37,15 +43,15 @@ impl AnalyzePattern for GroupPattern {
if macro_name != "group" && macro_name != "group_structural" {
continue;
}
- if let Some(name) = extract_group_name(&m.mac.tokens) {
- items.push(AnalyzeItem {
- module: String::new(),
- item_name: name,
- });
+ if let Some(analyze_item) = extract_group_item(&m.mac.tokens, &imports, "") {
+ items.push(analyze_item);
}
}
Item::Mod(item_mod) => {
if let Some((_, nested)) = &item_mod.content {
+ // Collect `use` imports inside this module
+ let inner_imports = collect_use_imports(nested);
+
for n in nested {
if let Item::Macro(m) = n {
let Some(last) = m.mac.path.segments.last() else {
@@ -55,11 +61,12 @@ impl AnalyzePattern for GroupPattern {
if macro_name != "group" && macro_name != "group_structural" {
continue;
}
- if let Some(name) = extract_group_name(&m.mac.tokens) {
- items.push(AnalyzeItem {
- module: item_mod.ident.to_string(),
- item_name: name,
- });
+ if let Some(analyze_item) = extract_group_item(
+ &m.mac.tokens,
+ &inner_imports,
+ &item_mod.ident.to_string(),
+ ) {
+ items.push(analyze_item);
}
}
}
@@ -73,6 +80,95 @@ impl AnalyzePattern for GroupPattern {
}
}
+/// Extract an `AnalyzeItem` from the macro invocation tokens.
+///
+/// If the name matches a `use` import, resolves to the full foreign path.
+/// For the `Alias = path::Type` form, returns a local item (the alias exists in-crate).
+fn extract_group_item(
+ tokens: &proc_macro2::TokenStream,
+ imports: &HashMap<String, (String, String)>,
+ current_mod: &str,
+) -> Option<AnalyzeItem> {
+ let name = extract_group_name(tokens)?;
+ let is_aliased = has_equals_sign(tokens);
+
+ if is_aliased {
+ // `group!(Alias = path::Type)` — alias lives in-crate
+ Some(AnalyzeItem::local(current_mod.to_string(), name))
+ } else if let Some((module, _)) = imports.get(&name) {
+ // `group!(TypeName)` where TypeName is imported via `use` — foreign
+ Some(AnalyzeItem::foreign(module.clone(), name))
+ } else {
+ // `group!(LocalType)` — local type
+ Some(AnalyzeItem::local(current_mod.to_string(), name))
+ }
+}
+
+/// Collect `use` imports from a list of top-level items.
+///
+/// Returns a map of `short_name → (module_path, short_name)`.
+/// e.g. `use cargo_metadata::CompilerMessage;` → `"CompilerMessage" → ("cargo_metadata", "CompilerMessage")`
+fn collect_use_imports(items: &[syn::Item]) -> HashMap<String, (String, String)> {
+ let mut map = HashMap::new();
+ for item in items {
+ if let Item::Use(use_item) = item {
+ // Only handle non-`pub use` (regular imports)
+ collect_from_use_tree(&use_item.tree, "", &mut map);
+ }
+ }
+ map
+}
+
+/// Recursively traverse a `UseTree` and collect named imports.
+fn collect_from_use_tree(
+ tree: &UseTree,
+ prefix: &str,
+ map: &mut HashMap<String, (String, String)>,
+) {
+ match tree {
+ UseTree::Name(name) => {
+ let module = prefix.to_string();
+ let alias = name.ident.to_string();
+ map.entry(alias).or_insert((module, name.ident.to_string()));
+ }
+ UseTree::Path(use_path) => {
+ let new_prefix = if prefix.is_empty() {
+ use_path.ident.to_string()
+ } else {
+ format!("{}::{}", prefix, use_path.ident)
+ };
+ collect_from_use_tree(&use_path.tree, &new_prefix, map);
+ }
+ UseTree::Rename(rename) => {
+ let module = prefix.to_string();
+ let alias = rename.ident.to_string();
+ map.entry(alias)
+ .or_insert((module, rename.ident.to_string()));
+ }
+ UseTree::Glob(_) => {
+ // `use path::*;` — skip glob imports
+ }
+ UseTree::Group(group) => {
+ for item in &group.items {
+ collect_from_use_tree(item, prefix, map);
+ }
+ }
+ }
+}
+
+/// Check whether the macro tokens contain `=`, indicating aliased form.
+fn has_equals_sign(tokens: &proc_macro2::TokenStream) -> bool {
+ let stream = tokens.clone();
+ for token in stream {
+ if let proc_macro2::TokenTree::Punct(p) = token
+ && p.as_char() == '='
+ {
+ return true;
+ }
+ }
+ false
+}
+
/// Extract the alias / type name from the arguments of `group!`.
///
/// - `group!(ParseIntError)` → `ParseIntError`
diff --git a/mingling_pathf/src/patterns/grouped_derive.rs b/mingling_pathf/src/patterns/grouped_derive.rs
new file mode 100644
index 0000000..56a87f9
--- /dev/null
+++ b/mingling_pathf/src/patterns/grouped_derive.rs
@@ -0,0 +1,89 @@
+//! The `GroupedDerivePattern` matches structs, enums, and unions annotated with
+//! `#[derive(Grouped)]` or `#[derive(GroupedSerialize)]` (or any combination
+//! with other derives). It also recurses into `mod` items to find nested types.
+//! This is used to track grouped items for code generation or analysis.
+
+use syn::Item;
+
+use crate::pattern_analyzer::{AnalyzeItem, AnalyzePattern};
+
+/// Matches `#[derive(Grouped)]` and `#[derive(GroupedSerialize)]`.
+///
+/// Covers the forms:
+/// - `#[derive(Grouped)] struct T { ... }`
+/// - `#[derive(Grouped, Serialize, ...)] struct T { ... }`
+/// - `#[derive(GroupedSerialize)] struct T { ... }`
+pub struct GroupedDerivePattern;
+
+impl AnalyzePattern for GroupedDerivePattern {
+ fn contains(&self, content: &str) -> bool {
+ content.contains("Grouped")
+ }
+
+ 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_grouped_derive(&s.attrs) => {
+ items.push(AnalyzeItem::local(String::new(), s.ident.to_string()));
+ }
+ Item::Enum(e) if has_grouped_derive(&e.attrs) => {
+ items.push(AnalyzeItem::local(String::new(), e.ident.to_string()));
+ }
+ Item::Union(u) if has_grouped_derive(&u.attrs) => {
+ items.push(AnalyzeItem::local(String::new(), 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_grouped_derive(&s.attrs) => {
+ items.push(AnalyzeItem::local(
+ item_mod.ident.to_string(),
+ s.ident.to_string(),
+ ));
+ }
+ Item::Enum(e) if has_grouped_derive(&e.attrs) => {
+ items.push(AnalyzeItem::local(
+ item_mod.ident.to_string(),
+ e.ident.to_string(),
+ ));
+ }
+ _ => {}
+ }
+ }
+ }
+ }
+ _ => {}
+ }
+ }
+
+ items
+ }
+}
+
+fn has_grouped_derive(attrs: &[syn::Attribute]) -> bool {
+ attrs.iter().any(|attr| {
+ if attr.path().is_ident("derive") {
+ // Correctly parse comma-separated paths in #[derive(Grouped, Debug, ...)]
+ attr.parse_args_with(|input: syn::parse::ParseStream| {
+ let paths =
+ syn::punctuated::Punctuated::<syn::Path, syn::Token![,]>::parse_terminated(
+ input,
+ )?;
+ Ok(paths.iter().any(|p| {
+ let name = p.segments.last().unwrap().ident.to_string();
+ name == "Grouped" || name == "GroupedSerialize"
+ }))
+ })
+ .unwrap_or(false)
+ } else {
+ false
+ }
+ })
+}
diff --git a/mingling_pathf/src/patterns/groupped_derive.rs b/mingling_pathf/src/patterns/groupped_derive.rs
deleted file mode 100644
index 91daaef..0000000
--- a/mingling_pathf/src/patterns/groupped_derive.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-//! The `GrouppedDerivePattern` matches structs, enums, and unions annotated with
-//! `#[derive(Groupped)]` or `#[derive(GrouppedSerialize)]` (or any combination
-//! with other derives). It also recurses into `mod` items to find nested types.
-//! This is used to track grouped items for code generation or analysis.
-
-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") {
- // Correctly parse comma-separated paths in #[derive(Groupped, Debug, ...)]
- attr.parse_args_with(|input: syn::parse::ParseStream| {
- let paths =
- syn::punctuated::Punctuated::<syn::Path, syn::Token![,]>::parse_terminated(
- input,
- )?;
- Ok(paths.iter().any(|p| {
- let name = p.segments.last().unwrap().ident.to_string();
- name == "Groupped" || name == "GrouppedSerialize"
- }))
- })
- .unwrap_or(false)
- } else {
- false
- }
- })
-}
diff --git a/mingling_pathf/src/patterns/help.rs b/mingling_pathf/src/patterns/help.rs
index 628f4ac..85793c3 100644
--- a/mingling_pathf/src/patterns/help.rs
+++ b/mingling_pathf/src/patterns/help.rs
@@ -13,7 +13,7 @@ pub struct HelpPattern;
impl AnalyzePattern for HelpPattern {
fn contains(&self, content: &str) -> bool {
- content.contains("help]")
+ content.contains("[help") || content.contains("help]")
}
fn analyze(&self, content: &str) -> Vec<AnalyzeItem> {
@@ -37,10 +37,10 @@ fn collect_from_item(item: &Item, current_mod: &str, items: &mut Vec<AnalyzeItem
match item {
Item::Fn(f) if has_attr(&f.attrs, "help") => {
let fn_name = f.sig.ident.to_string();
- items.push(AnalyzeItem {
- module: current_mod.to_string(),
- item_name: internal_name(&fn_name),
- });
+ items.push(AnalyzeItem::local(
+ current_mod.to_string(),
+ internal_name(&fn_name),
+ ));
}
Item::Mod(item_mod) => {
if let Some((_, nested)) = &item_mod.content {
diff --git a/mingling_pathf/src/patterns/pack.rs b/mingling_pathf/src/patterns/pack.rs
index c80fb65..76597ba 100644
--- a/mingling_pathf/src/patterns/pack.rs
+++ b/mingling_pathf/src/patterns/pack.rs
@@ -18,7 +18,10 @@ pub struct PackPattern;
impl AnalyzePattern for PackPattern {
fn contains(&self, content: &str) -> bool {
- content.contains("pack!") || content.contains("pack_err!")
+ content.contains("pack!")
+ || content.contains("pack_err!")
+ || content.contains("pack_structural!")
+ || content.contains("pack_err_structural!")
}
fn analyze(&self, content: &str) -> Vec<AnalyzeItem> {
@@ -33,10 +36,7 @@ impl AnalyzePattern for PackPattern {
// Top-level macro calls
Item::Macro(m) => {
if let Some(name) = try_extract_pack_name(m) {
- items.push(AnalyzeItem {
- module: String::new(),
- item_name: name,
- });
+ items.push(AnalyzeItem::local(String::new(), name));
}
}
// Macro calls inside inline modules
@@ -46,10 +46,7 @@ impl AnalyzePattern for PackPattern {
if let Item::Macro(m) = n
&& let Some(name) = try_extract_pack_name(m)
{
- items.push(AnalyzeItem {
- module: item_mod.ident.to_string(),
- item_name: name,
- });
+ items.push(AnalyzeItem::local(item_mod.ident.to_string(), name));
}
}
}
diff --git a/mingling_pathf/src/patterns/renderer.rs b/mingling_pathf/src/patterns/renderer.rs
index c2e9ca9..153e603 100644
--- a/mingling_pathf/src/patterns/renderer.rs
+++ b/mingling_pathf/src/patterns/renderer.rs
@@ -13,7 +13,7 @@ pub struct RendererPattern;
impl AnalyzePattern for RendererPattern {
fn contains(&self, content: &str) -> bool {
- content.contains("renderer]")
+ content.contains("[renderer") || content.contains("renderer]")
}
fn analyze(&self, content: &str) -> Vec<AnalyzeItem> {
@@ -37,10 +37,10 @@ fn collect_from_item(item: &Item, current_mod: &str, items: &mut Vec<AnalyzeItem
match item {
Item::Fn(f) if has_attr(&f.attrs, "renderer") => {
let fn_name = f.sig.ident.to_string();
- items.push(AnalyzeItem {
- module: current_mod.to_string(),
- item_name: internal_name(&fn_name),
- });
+ items.push(AnalyzeItem::local(
+ current_mod.to_string(),
+ internal_name(&fn_name),
+ ));
}
Item::Mod(item_mod) => {
if let Some((_, nested)) = &item_mod.content {