1#[macro_export]
18macro_rules! declare_forge_lint {
19 ($id:ident, $severity:expr, $str_id:expr, $desc:expr) => {
20 pub static $id: SolLint = SolLint {
22 id: $str_id,
23 severity: $severity,
24 description: $desc,
25 help: concat!("https://getfoundry.sh/forge/linting/", $str_id),
26 };
27 };
28}
29
30#[macro_export]
45macro_rules! register_lints {
46 ( @declare_structs $( ($pass_id:ident, $pass_type:ident, ($($lint:expr),* $(,)?)) ),* $(,)? ) => {
48 $(
49 #[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
50 pub struct $pass_id;
51
52 impl $pass_id {
53 const LINTS: &'static [SolLint] = &[$($lint),*];
55
56 register_lints!(@early_impl $pass_id, $pass_type);
57 register_lints!(@late_impl $pass_id, $pass_type);
58 register_lints!(@project_impl $pass_id, $pass_type);
59 }
60 )*
61 };
62
63 ( @declare_consts $( ($pass_id:ident, $pass_type:ident, ($($lint:expr),* $(,)?)) ),* $(,)? ) => {
65 pub const REGISTERED_LINTS: &[SolLint] = &[
66 $(
67 $($lint,)*
68 )*
69 ];
70 };
71
72 ( @declare_funcs $( ($pass_id:ident, $pass_type:ident, $lints:tt) ),* $(,)? ) => {
74 pub fn create_early_lint_passes<'ast>() -> Vec<(Box<dyn EarlyLintPass<'ast>>, &'static [SolLint])> {
75 [
76 $(
77 register_lints!(@early_create $pass_id, $pass_type),
78 )*
79 ]
80 .into_iter()
81 .flatten()
82 .collect()
83 }
84
85 pub fn create_late_lint_passes<'hir>() -> Vec<(Box<dyn LateLintPass<'hir>>, &'static [SolLint])> {
86 [
87 $(
88 register_lints!(@late_create $pass_id, $pass_type),
89 )*
90 ]
91 .into_iter()
92 .flatten()
93 .collect()
94 }
95
96 pub fn create_project_lint_passes<'ast>() -> Vec<(Box<dyn $crate::linter::ProjectLintPass<'ast>>, &'static [SolLint])> {
97 [
98 $(
99 register_lints!(@project_create $pass_id, $pass_type),
100 )*
101 ]
102 .into_iter()
103 .flatten()
104 .collect()
105 }
106 };
107
108 (@early_impl $_pass_id:ident, late) => {};
110 (@early_impl $_pass_id:ident, project) => {};
111 (@early_impl $pass_id:ident, $other:ident) => {
112 pub fn as_early_lint_pass<'a>() -> Box<dyn EarlyLintPass<'a>> {
113 Box::new(Self::default())
114 }
115 };
116
117 (@late_impl $_pass_id:ident, early) => {};
118 (@late_impl $_pass_id:ident, project) => {};
119 (@late_impl $pass_id:ident, $other:ident) => {
120 pub fn as_late_lint_pass<'hir>() -> Box<dyn LateLintPass<'hir>> {
121 Box::new(Self::default())
122 }
123 };
124
125 (@project_impl $_pass_id:ident, early) => {};
126 (@project_impl $_pass_id:ident, late) => {};
127 (@project_impl $_pass_id:ident, both) => {};
128 (@project_impl $pass_id:ident, $other:ident) => {
129 pub fn as_project_lint_pass<'ast>() -> Box<dyn $crate::linter::ProjectLintPass<'ast>> {
130 Box::new(Self::default())
131 }
132 };
133
134 (@early_create $_pass_id:ident, late) => { None };
135 (@early_create $_pass_id:ident, project) => { None };
136 (@early_create $pass_id:ident, $_other:ident) => {
137 Some(($pass_id::as_early_lint_pass(), $pass_id::LINTS))
138 };
139
140 (@late_create $_pass_id:ident, early) => { None };
141 (@late_create $_pass_id:ident, project) => { None };
142 (@late_create $pass_id:ident, $_other:ident) => {
143 Some(($pass_id::as_late_lint_pass(), $pass_id::LINTS))
144 };
145
146 (@project_create $_pass_id:ident, early) => { None };
147 (@project_create $_pass_id:ident, late) => { None };
148 (@project_create $_pass_id:ident, both) => { None };
149 (@project_create $pass_id:ident, $_other:ident) => {
150 Some(($pass_id::as_project_lint_pass(), $pass_id::LINTS))
151 };
152
153 ( $($tokens:tt)* ) => {
155 register_lints! { @declare_structs $($tokens)* }
156 register_lints! { @declare_consts $($tokens)* }
157 register_lints! { @declare_funcs $($tokens)* }
158 };
159}