1#[macro_export]
2#[doc(hidden)]
3macro_rules! _declare_params {
4 () => {
5 const PARAMS: &[$crate::RuleParam] = &[];
6 };
7 ($($pname:ident : $ptype:tt = $default:tt),+ $(,)?) => {
8 const PARAMS: &[$crate::RuleParam] = &[
9 $($crate::_param!($pname : $ptype = $default)),+
10 ];
11 };
12}
13
14#[macro_export]
15#[doc(hidden)]
16macro_rules! _param {
17 ($pname:ident : i64 = $default:expr) => {
18 $crate::RuleParam {
19 name: stringify!($pname),
20 param_type: $crate::ParamType::Int,
21 default: $crate::ParamDefault::Int($default),
22 }
23 };
24 ($pname:ident : [String] = [$($val:expr),* $(,)?]) => {
25 $crate::RuleParam {
26 name: stringify!($pname),
27 param_type: $crate::ParamType::StringArray,
28 default: $crate::ParamDefault::StringArray(&[$($val),*]),
29 }
30 };
31}
32
33#[macro_export]
35macro_rules! example_tests {
36 ($examples:expr, $check_fn:ident) => {
37 #[$crate::_private::gtest]
38 fn examples() -> $crate::_private::TestResult {
39 for (i, ex) in $examples.iter().enumerate() {
40 $crate::_private::scoped_trace!("example[{i}] {:?}:\n{}", ex.label, ex.code);
41 let violations = run(ex.code);
42 if ex.pass {
43 $crate::_private::verify_true!(violations.is_empty())?;
44 } else {
45 $crate::_private::verify_false!(violations.is_empty())?;
46 }
47 }
48
49 Ok(())
50 }
51 };
52}
53
54#[macro_export]
55macro_rules! tidy_test {
56 ($check_fn:ident, { $($body:tt)* }) => {
57 #[cfg(test)]
58 mod tests {
59 use super::*;
60 fn run(source: &str) -> Vec<$crate::Violation> {
61 $crate::check_source(source, $check_fn)
62 }
63 $($body)*
64 }
65 };
66}
67
68#[macro_export]
69macro_rules! tidy_ast_test {
70 ($check_fn:ident, { $($body:tt)* }) => {
71 #[cfg(test)]
72 mod tests {
73 use super::*;
74 fn run(source: &str) -> Vec<$crate::Violation> {
75 $crate::check_source_ast(source, $check_fn)
76 }
77 $($body)*
78 }
79 };
80}
81
82#[macro_export]
83macro_rules! tidy_toml_test {
84 ($check_fn:ident, { $($body:tt)* }) => {
85 #[cfg(test)]
86 mod tests {
87 use super::*;
88 fn run(source: &str) -> Vec<$crate::Violation> {
89 $crate::check_source_toml(source, $check_fn)
90 }
91 $($body)*
92 }
93 };
94}
95
96#[macro_export]
97macro_rules! tidy_workspace_test {
98 ($check_fn:ident, { $($body:tt)* }) => {
99 #[cfg(test)]
100 mod tests {
101 use super::*;
102 fn run(source: &str) -> Vec<$crate::Violation> {
103 $crate::check_workspace_sources(&[("test.rs", source)], $check_fn)
104 }
105 $($body)*
106 }
107 };
108}
109
110#[macro_export]
111#[doc(hidden)]
112macro_rules! _rule_info {
113 ($name:expr, $desc:expr, $just:expr, $sev:ident, $params:expr) => {
114 $crate::RuleInfo {
115 name: $name,
116 description: $desc,
117 justification: $just,
118 severity: $crate::Severity::$sev,
119 examples: EXAMPLES,
120 params: $params,
121 }
122 };
123}
124
125#[macro_export]
126#[doc(hidden)]
127macro_rules! _submit_line_rule {
128 ($name:ident, $desc:expr, $just:expr, $sev:ident, $params:expr, $fix:expr) => {
129 paste::paste! {
130 inventory::submit! {
131 $crate::Rule {
132 info: $crate::_rule_info!(concat!("rust_", stringify!($name)), $desc, $just, $sev, $params),
133 check: $crate::RuleCheck::RustLine([<check_ $name>]),
134 fix: $fix,
135 }
136 }
137 }
138 };
139}
140
141#[macro_export]
142#[doc(hidden)]
143macro_rules! _submit_ast_rule {
144 ($name:ident, $desc:expr, $just:expr, $sev:ident, $params:expr, $fix:expr) => {
145 paste::paste! {
146 inventory::submit! {
147 $crate::Rule {
148 info: $crate::_rule_info!(concat!("rust_", stringify!($name)), $desc, $just, $sev, $params),
149 check: $crate::RuleCheck::RustAst([<check_ $name>]),
150 fix: $fix,
151 }
152 }
153 }
154 };
155}
156
157#[macro_export]
158#[doc(hidden)]
159macro_rules! _submit_ast_tree_rule {
160 ($name:ident, $desc:expr, $just:expr, $sev:ident, $params:expr, $fix:expr) => {
161 paste::paste! {
162 inventory::submit! {
163 $crate::Rule {
164 info: $crate::_rule_info!(concat!("rust_", stringify!($name)), $desc, $just, $sev, $params),
165 check: $crate::RuleCheck::RustAst([<check_ $name>]),
166 fix: Some($crate::RuleFix::RustAstTree($fix)),
167 }
168 }
169 }
170 };
171}
172
173#[macro_export]
174#[doc(hidden)]
175macro_rules! _submit_workspace_rule {
176 ($name:ident, $desc:expr, $just:expr, $sev:ident, $params:expr) => {
177 paste::paste! {
178 inventory::submit! {
179 $crate::Rule {
180 info: $crate::_rule_info!(concat!("rust_", stringify!($name)), $desc, $just, $sev, $params),
181 check: $crate::RuleCheck::RustWorkspace([<check_ $name>]),
182 fix: None,
183 }
184 }
185 }
186 };
187}
188
189#[macro_export]
190#[doc(hidden)]
191macro_rules! _submit_language_workspace_rule {
192 ($name:ident, $desc:expr, $just:expr, $sev:ident, $params:expr) => {
193 paste::paste! {
194 inventory::submit! {
195 $crate::Rule {
196 info: $crate::_rule_info!(stringify!($name), $desc, $just, $sev, $params),
197 check: $crate::RuleCheck::Workspace([<check_ $name>]),
198 fix: None,
199 }
200 }
201 }
202 };
203}
204
205#[macro_export]
206#[doc(hidden)]
207macro_rules! _submit_toml_rule {
208 ($name:ident, $desc:expr, $just:expr, $sev:ident, $params:expr, $fix:expr) => {
209 paste::paste! {
210 inventory::submit! {
211 $crate::Rule {
212 info: $crate::_rule_info!(stringify!($name), $desc, $just, $sev, $params),
213 check: $crate::RuleCheck::Toml([<check_ $name>]),
214 fix: $fix,
215 }
216 }
217 }
218 };
219}
220
221#[macro_export]
223macro_rules! line_rule {
224 ($name:ident, $desc:expr, $just:expr, $sev:ident, $fix:expr, params { $($params:tt)* } $(,)?) => {
225 $crate::_declare_params!($($params)*);
226 $crate::_submit_line_rule!($name, $desc, $just, $sev, PARAMS, Some($crate::RuleFix::RustLine($fix)));
227 };
228 ($name:ident, $desc:expr, $just:expr, $sev:ident, params { $($params:tt)* } $(,)?) => {
229 $crate::_declare_params!($($params)*);
230 $crate::_submit_line_rule!($name, $desc, $just, $sev, PARAMS, None);
231 };
232 ($name:ident, $desc:expr, $just:expr, params { $($params:tt)* } $(,)?) => {
233 $crate::_declare_params!($($params)*);
234 $crate::_submit_line_rule!($name, $desc, $just, Low, PARAMS, None);
235 };
236 ($name:ident, $desc:expr, $just:expr, $sev:ident, $fix:expr $(,)?) => {
237 $crate::_submit_line_rule!($name, $desc, $just, $sev, &[], Some($crate::RuleFix::RustLine($fix)));
238 };
239 ($name:ident, $desc:expr, $just:expr, $sev:ident $(,)?) => {
240 $crate::_submit_line_rule!($name, $desc, $just, $sev, &[], None);
241 };
242 ($name:ident, $desc:expr, $just:expr $(,)?) => {
243 $crate::_submit_line_rule!($name, $desc, $just, Low, &[], None);
244 };
245}
246
247#[macro_export]
249macro_rules! ast_rule {
250 ($name:ident, $desc:expr, $just:expr, $sev:ident, $fix:expr, params { $($params:tt)* } $(,)?) => {
251 $crate::_declare_params!($($params)*);
252 $crate::_submit_ast_rule!($name, $desc, $just, $sev, PARAMS, Some($crate::RuleFix::RustAst($fix)));
253 };
254 ($name:ident, $desc:expr, $just:expr, $sev:ident, params { $($params:tt)* } $(,)?) => {
255 $crate::_declare_params!($($params)*);
256 $crate::_submit_ast_rule!($name, $desc, $just, $sev, PARAMS, None);
257 };
258 ($name:ident, $desc:expr, $just:expr, params { $($params:tt)* } $(,)?) => {
259 $crate::_declare_params!($($params)*);
260 $crate::_submit_ast_rule!($name, $desc, $just, Low, PARAMS, None);
261 };
262 ($name:ident, $desc:expr, $just:expr, $sev:ident, $fix:expr $(,)?) => {
263 $crate::_submit_ast_rule!($name, $desc, $just, $sev, &[], Some($crate::RuleFix::RustAst($fix)));
264 };
265 ($name:ident, $desc:expr, $just:expr, $sev:ident $(,)?) => {
266 $crate::_submit_ast_rule!($name, $desc, $just, $sev, &[], None);
267 };
268 ($name:ident, $desc:expr, $just:expr $(,)?) => {
269 $crate::_submit_ast_rule!($name, $desc, $just, Low, &[], None);
270 };
271}
272
273#[macro_export]
275macro_rules! ast_tree_rule {
276 ($name:ident, $desc:expr, $just:expr, $sev:ident, $fix:expr, params { $($params:tt)* } $(,)?) => {
277 $crate::_declare_params!($($params)*);
278 $crate::_submit_ast_tree_rule!($name, $desc, $just, $sev, PARAMS, $fix);
279 };
280 ($name:ident, $desc:expr, $just:expr, $sev:ident, $fix:expr $(,)?) => {
281 $crate::_submit_ast_tree_rule!($name, $desc, $just, $sev, &[], $fix);
282 };
283}
284
285#[macro_export]
287macro_rules! workspace_rule {
288 ($name:ident, $desc:expr, $just:expr, $sev:ident, params { $($params:tt)* } $(,)?) => {
289 $crate::_declare_params!($($params)*);
290 $crate::_submit_workspace_rule!($name, $desc, $just, $sev, PARAMS);
291 };
292}
293
294#[macro_export]
296macro_rules! language_workspace_rule {
297 ($name:ident, $desc:expr, $just:expr, $sev:ident, params { $($params:tt)* } $(,)?) => {
298 $crate::_declare_params!($($params)*);
299 $crate::_submit_language_workspace_rule!($name, $desc, $just, $sev, PARAMS);
300 };
301}
302
303#[macro_export]
305macro_rules! toml_rule {
306 ($name:ident, $desc:expr, $just:expr, $sev:ident, $fix:expr, params { $($params:tt)* } $(,)?) => {
307 $crate::_declare_params!($($params)*);
308 $crate::_submit_toml_rule!($name, $desc, $just, $sev, PARAMS, Some($crate::RuleFix::Toml($fix)));
309 };
310 ($name:ident, $desc:expr, $just:expr, $sev:ident, params { $($params:tt)* } $(,)?) => {
311 $crate::_declare_params!($($params)*);
312 $crate::_submit_toml_rule!($name, $desc, $just, $sev, PARAMS, None);
313 };
314 ($name:ident, $desc:expr, $just:expr, $sev:ident, $fix:expr $(,)?) => {
315 $crate::_submit_toml_rule!($name, $desc, $just, $sev, &[], Some($crate::RuleFix::Toml($fix)));
316 };
317 ($name:ident, $desc:expr, $just:expr, $sev:ident $(,)?) => {
318 $crate::_submit_toml_rule!($name, $desc, $just, $sev, &[], None);
319 };
320}
321
322#[macro_export]
324macro_rules! fix_tests {
325 (line, $check_fn:ident, $fix_fn:ident) => {
326 #[$crate::_private::gtest]
327 fn fixes() -> $crate::_private::TestResult {
328 for (i, ex) in EXAMPLES.iter().enumerate() {
329 if ex.pass {
330 continue;
331 }
332 let fixed = $crate::apply_line_fixes(ex.code, $check_fn, $fix_fn);
333 let remaining = run(&fixed);
334 $crate::_private::scoped_trace!("example {i} ({:?})", ex.label);
335 $crate::_private::verify_true!(remaining.is_empty())?;
336 }
337
338 Ok(())
339 }
340 };
341 (ast, $check_fn:ident, $fix_fn:ident) => {
342 #[$crate::_private::gtest]
343 fn fixes() -> $crate::_private::TestResult {
344 for (i, ex) in EXAMPLES.iter().enumerate() {
345 if ex.pass {
346 continue;
347 }
348 let fixed = $crate::apply_ast_fixes(ex.code, $check_fn, $fix_fn);
349 let remaining = run(&fixed);
350 $crate::_private::scoped_trace!("example {i} ({:?})", ex.label);
351 $crate::_private::verify_true!(remaining.is_empty())?;
352 }
353
354 Ok(())
355 }
356 };
357 (ast_tree, $check_fn:ident, $fix_fn:ident) => {
358 #[$crate::_private::gtest]
359 fn fixes() -> $crate::_private::TestResult {
360 for (i, ex) in EXAMPLES.iter().enumerate() {
361 if ex.pass {
362 continue;
363 }
364 let fixed = $crate::apply_ast_tree_fix(ex.code, $check_fn, $fix_fn);
365 let remaining = run(&fixed);
366 $crate::_private::scoped_trace!("example {i} ({:?})", ex.label);
367 $crate::_private::verify_true!(remaining.is_empty())?;
368 }
369
370 Ok(())
371 }
372 };
373}