forge_lint/linter/
early.rs1use super::LintContext;
2use solar::{
3 ast::{self as ast, visit::Visit},
4 interface::data_structures::Never,
5};
6use std::ops::ControlFlow;
7
8pub trait EarlyLintPass<'ast>: Send + Sync {
11 fn check_expr(&mut self, _ctx: &LintContext, _expr: &'ast ast::Expr<'ast>) {}
12 fn check_item_struct(&mut self, _ctx: &LintContext, _struct: &'ast ast::ItemStruct<'ast>) {}
13 fn check_item_function(&mut self, _ctx: &LintContext, _func: &'ast ast::ItemFunction<'ast>) {}
14 fn check_variable_definition(
15 &mut self,
16 _ctx: &LintContext,
17 _var: &'ast ast::VariableDefinition<'ast>,
18 ) {
19 }
20 fn check_import_directive(
21 &mut self,
22 _ctx: &LintContext,
23 _import: &'ast ast::ImportDirective<'ast>,
24 ) {
25 }
26 fn check_using_directive(
27 &mut self,
28 _ctx: &LintContext,
29 _using: &'ast ast::UsingDirective<'ast>,
30 ) {
31 }
32 fn check_item_contract(
33 &mut self,
34 _ctx: &LintContext,
35 _contract: &'ast ast::ItemContract<'ast>,
36 ) {
37 }
38 fn check_doc_comment(&mut self, _ctx: &LintContext, _cmnt: &'ast ast::DocComment) {}
39 fn check_item(&mut self, _ctx: &LintContext, _item: &'ast ast::Item<'ast>) {}
40 fn check_stmt(&mut self, _ctx: &LintContext, _stmt: &'ast ast::Stmt<'ast>) {}
41 fn check_path(&mut self, _ctx: &LintContext, _path: &'ast ast::PathSlice) {}
42 fn check_ty(&mut self, _ctx: &LintContext, _ty: &'ast ast::Type<'ast>) {}
43
44 fn check_full_source_unit(
64 &mut self,
65 _ctx: &LintContext<'ast, '_>,
66 _ast: &'ast ast::SourceUnit<'ast>,
67 ) {
68 }
69}
70
71pub struct EarlyLintVisitor<'a, 's, 'ast> {
73 pub ctx: &'a LintContext<'s, 'a>,
74 pub passes: &'a mut [Box<dyn EarlyLintPass<'ast> + 's>],
75}
76
77impl<'a, 's, 'ast> EarlyLintVisitor<'a, 's, 'ast>
78where
79 's: 'ast,
80{
81 pub fn new(
82 ctx: &'a LintContext<'s, 'a>,
83 passes: &'a mut [Box<dyn EarlyLintPass<'ast> + 's>],
84 ) -> Self {
85 Self { ctx, passes }
86 }
87
88 pub fn post_source_unit(&mut self, ast: &'ast ast::SourceUnit<'ast>) {
91 for pass in self.passes.iter_mut() {
92 pass.check_full_source_unit(self.ctx, ast);
93 }
94 }
95}
96
97impl<'s, 'ast> Visit<'ast> for EarlyLintVisitor<'_, 's, 'ast>
98where
99 's: 'ast,
100{
101 type BreakValue = Never;
102
103 fn visit_doc_comment(&mut self, cmnt: &'ast ast::DocComment) -> ControlFlow<Self::BreakValue> {
104 for pass in self.passes.iter_mut() {
105 pass.check_doc_comment(self.ctx, cmnt)
106 }
107 self.walk_doc_comment(cmnt)
108 }
109
110 fn visit_expr(&mut self, expr: &'ast ast::Expr<'ast>) -> ControlFlow<Self::BreakValue> {
111 for pass in self.passes.iter_mut() {
112 pass.check_expr(self.ctx, expr)
113 }
114 self.walk_expr(expr)
115 }
116
117 fn visit_variable_definition(
118 &mut self,
119 var: &'ast ast::VariableDefinition<'ast>,
120 ) -> ControlFlow<Self::BreakValue> {
121 for pass in self.passes.iter_mut() {
122 pass.check_variable_definition(self.ctx, var)
123 }
124 self.walk_variable_definition(var)
125 }
126
127 fn visit_item_struct(
128 &mut self,
129 strukt: &'ast ast::ItemStruct<'ast>,
130 ) -> ControlFlow<Self::BreakValue> {
131 for pass in self.passes.iter_mut() {
132 pass.check_item_struct(self.ctx, strukt)
133 }
134 self.walk_item_struct(strukt)
135 }
136
137 fn visit_item_function(
138 &mut self,
139 func: &'ast ast::ItemFunction<'ast>,
140 ) -> ControlFlow<Self::BreakValue> {
141 for pass in self.passes.iter_mut() {
142 pass.check_item_function(self.ctx, func)
143 }
144 self.walk_item_function(func)
145 }
146
147 fn visit_import_directive(
148 &mut self,
149 import: &'ast ast::ImportDirective<'ast>,
150 ) -> ControlFlow<Self::BreakValue> {
151 for pass in self.passes.iter_mut() {
152 pass.check_import_directive(self.ctx, import);
153 }
154 self.walk_import_directive(import)
155 }
156
157 fn visit_using_directive(
158 &mut self,
159 using: &'ast ast::UsingDirective<'ast>,
160 ) -> ControlFlow<Self::BreakValue> {
161 for pass in self.passes.iter_mut() {
162 pass.check_using_directive(self.ctx, using);
163 }
164 self.walk_using_directive(using)
165 }
166
167 fn visit_item_contract(
168 &mut self,
169 contract: &'ast ast::ItemContract<'ast>,
170 ) -> ControlFlow<Self::BreakValue> {
171 for pass in self.passes.iter_mut() {
172 pass.check_item_contract(self.ctx, contract);
173 }
174 self.walk_item_contract(contract)
175 }
176
177 fn visit_item(&mut self, item: &'ast ast::Item<'ast>) -> ControlFlow<Self::BreakValue> {
178 for pass in self.passes.iter_mut() {
179 pass.check_item(self.ctx, item)
180 }
181 self.walk_item(item)
182 }
183
184 fn visit_stmt(&mut self, stmt: &'ast ast::Stmt<'ast>) -> ControlFlow<Self::BreakValue> {
185 for pass in self.passes.iter_mut() {
186 pass.check_stmt(self.ctx, stmt)
187 }
188 self.walk_stmt(stmt)
189 }
190
191 fn visit_path(&mut self, path: &'ast ast::PathSlice) -> ControlFlow<Self::BreakValue> {
192 for pass in self.passes.iter_mut() {
193 pass.check_path(self.ctx, path)
194 }
195 self.walk_path(path)
196 }
197
198 fn visit_ty(&mut self, ty: &'ast ast::Type<'ast>) -> ControlFlow<Self::BreakValue> {
199 for pass in self.passes.iter_mut() {
200 pass.check_ty(self.ctx, ty)
201 }
202 self.walk_ty(ty)
203 }
204}