This Rust utility provides a way to determine the module path of a procedural macro invocation. It is particularly useful when writing procedural macros that need to infer their context within a Rust module hierarchy.
- ✅ Detects the module path where the macro is invoked (e.g.,
"crate::task::workflow"
). - ✅ Supports nested modules, both inline (
mod foo {}
) and external (mod foo;
). - ✅ Handles
pub mod
,pub(crate) mod
, andpub(super) mod
declarations correctly. - ✅ Works with procedural macros to automatically infer where they are used.
- ✅ Cross-platform compatibility (handles both
/
and\
in paths).
This module requires Rust nightly because it uses the proc_macro_span
feature.
-
Add the following to
Cargo.toml
:[dependencies] proc-macro2 = "1"
-
In your Rust crate, enable the nightly feature:
#![feature(proc_macro_span)]
This module provides a function get_pseudo_module_path()
that returns the inferred module path as a String
.
mod task {
#[some_macro] // This macro should return "crate::task"
fn example() {}
}
Output:
"crate::task"
pub mod task {
pub mod workflow {
#[some_macro] // Should return "crate::task::workflow"
fn example() {}
}
}
Output:
"crate::task::workflow"
When used inside a procedural macro:
#[proc_macro]
pub fn example_macro(_input: TokenStream) -> TokenStream {
let module_path = get_pseudo_module_path();
println!("Macro invoked in module: {}", module_path);
TokenStream::new()
}
Invoking the macro inside src/workflow.rs
:
workflow::example_macro!();
Output:
Macro invoked in module: "crate::workflow"
It uses proc_macro::Span
to get:
- The file path where the macro was invoked.
- The line number where it was called.
- Scans the source file above the macro call for module declarations (
mod foo {}
). - Tracks nested modules to build a hierarchical path (
crate::task::workflow
). - Supports both inline (
mod foo {}
) and external (mod foo;
) modules.
- Uses the module hierarchy if found (
crate::task::workflow
). - Otherwise, derives the path from the file structure.
- Requires nightly Rust (
proc_macro_span
feature). - Does not handle generated code (e.g., if a macro generates a module).
- Assumes that module paths match the file structure (standard Rust convention).
Pull requests and issues are welcome! Feel free to improve the logic or add more test cases.
This project is licensed under the MIT License.