1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// devela::code::util::structural
//
//! Defines the [`structural_mods!`] macro.
//
/// Defines a standardized module structure for organizing visibility and re-exports.
///
/// This macro generates a set of structural helper modules that centralize export logic
/// according to intended visibility and usage. It reduces boilerplate and enforces a
/// consistent module layout across workspace crates.
///
/// <div class="warning">
///
/// **Usage Constraints:**
/// - Module blocks must be specified in the exact order shown below (all are optional).
/// - This macro defines internal modules with reserved names
/// (`_mods`, `_pub_mods`, `_reexports`, `_crate_internals`, `_workspace_internals`,
/// `_hidden`, and `_all`). Do not define modules with these names in the same scope.
///
/// Violating either rule will result in compilation errors or incorrect aggregation.
/// </div>
///
/// # Generated Modules
///
/// The macro can generate these optional modules:
///
/// - `_mods`: Public items from non-public modules. Items should be `pub`.
/// - `_pub_mods`: Public items from public modules. Items should be `pub` and use `doc(inline)`.
/// - `_reexports`: Public items from other modules, crates, or the std. Items should be `pub`.
/// - `_crate_internals`: Crate-private items (`pub(crate)`) re-exported within the crate.
/// - `_workspace_internals`: Workspace-visible items (`pub`, `doc(hidden)`).
/// - `_hidden`: Public but hidden items (`pub`, `doc(hidden)`).
///
/// An `_all` module is always generated. It aggregates exports from `_mods`, `_pub_mods`,
/// and `_reexports` when present.
///
/// # Usage Patterns
/// ```ignore
/// # use devela::structural_mods
/// # mod some_module {}
/// # mod other_module {}
/// # pub mod public_module { pub(super) mod _all {} }
/// # mod _reexport {}
/// # mod internal_utils {}
/// # mod workspace_tools {}
/// structural_mods! {
/// _mods {
/// pub use super::{some_module::*, other_module::*};
/// }
/// _pub_mods {
/// #[doc(inline)]
/// pub use super::public_module::_all::*;
/// }
/// _pub_mods {
/// pub use super::_reexport::*;
/// }
/// _crate_internals {
/// pub(crate) use super::internal_utils::*;
/// }
/// _workspace_internals {
/// pub use super::workspace_tools::*;
/// }
/// }
/// ```
/// # Notes
/// - Generated modules use `#[allow(unused_imports)]` to avoid warnings caused by
/// intra-crate visibility boundaries.
/// - Each module in the hierarchy must forward its structural exports upward to preserve
/// the intended public API surface.
//
// We use the pattern `$(_mods$($has_mods:lifetime)?)?` where the optional lifetime parameter
// serves as a marker to conditionally include the module in `_all`. The lifetime is never
// actually used, simply allowing us to detect the presence of the module during expansion.
)?
//
// Items inside should be pub & doc(inline).
// Public items from public modules. They bubble up but are hidden in the current module.
$?
//
// Items inside should be pub.
$?
//
// Items inside should be pub(crate).
// They are re-exported from the root of the current crate.
$?
//
// Items inside should be pub & doc(hidden).
// They are publicly re-exported from the root of each crate except for the top crate.
$?
//
// Items inside should be pub & doc(hidden).
// They are publicly re-exported from the root of the crate.
$?
) => ;
}
pub use _structural_mods as structural_mods;