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_full_source_unit(
61 &mut self,
62 _ctx: &LintContext<'ast, '_>,
63 _ast: &'ast ast::SourceUnit<'ast>,
64 ) {
65 }
66}
67
68pub struct EarlyLintVisitor<'a, 's, 'ast> {
70 pub ctx: &'a LintContext<'s, 'a>,
71 pub passes: &'a mut [Box<dyn EarlyLintPass<'ast> + 's>],
72}
73
74impl<'a, 's, 'ast> EarlyLintVisitor<'a, 's, 'ast>
75where
76 's: 'ast,
77{
78 pub fn new(
79 ctx: &'a LintContext<'s, 'a>,
80 passes: &'a mut [Box<dyn EarlyLintPass<'ast> + 's>],
81 ) -> Self {
82 Self { ctx, passes }
83 }
84
85 pub fn post_source_unit(&mut self, ast: &'ast ast::SourceUnit<'ast>) {
88 for pass in self.passes.iter_mut() {
89 pass.check_full_source_unit(self.ctx, ast);
90 }
91 }
92}
93
94impl<'s, 'ast> Visit<'ast> for EarlyLintVisitor<'_, 's, 'ast>
95where
96 's: 'ast,
97{
98 type BreakValue = Never;
99
100 fn visit_doc_comment(&mut self, cmnt: &'ast ast::DocComment) -> ControlFlow<Self::BreakValue> {
101 for pass in self.passes.iter_mut() {
102 pass.check_doc_comment(self.ctx, cmnt)
103 }
104 self.walk_doc_comment(cmnt)
105 }
106
107 fn visit_expr(&mut self, expr: &'ast ast::Expr<'ast>) -> ControlFlow<Self::BreakValue> {
108 for pass in self.passes.iter_mut() {
109 pass.check_expr(self.ctx, expr)
110 }
111 self.walk_expr(expr)
112 }
113
114 fn visit_variable_definition(
115 &mut self,
116 var: &'ast ast::VariableDefinition<'ast>,
117 ) -> ControlFlow<Self::BreakValue> {
118 for pass in self.passes.iter_mut() {
119 pass.check_variable_definition(self.ctx, var)
120 }
121 self.walk_variable_definition(var)
122 }
123
124 fn visit_item_struct(
125 &mut self,
126 strukt: &'ast ast::ItemStruct<'ast>,
127 ) -> ControlFlow<Self::BreakValue> {
128 for pass in self.passes.iter_mut() {
129 pass.check_item_struct(self.ctx, strukt)
130 }
131 self.walk_item_struct(strukt)
132 }
133
134 fn visit_item_function(
135 &mut self,
136 func: &'ast ast::ItemFunction<'ast>,
137 ) -> ControlFlow<Self::BreakValue> {
138 for pass in self.passes.iter_mut() {
139 pass.check_item_function(self.ctx, func)
140 }
141 self.walk_item_function(func)
142 }
143
144 fn visit_import_directive(
145 &mut self,
146 import: &'ast ast::ImportDirective<'ast>,
147 ) -> ControlFlow<Self::BreakValue> {
148 for pass in self.passes.iter_mut() {
149 pass.check_import_directive(self.ctx, import);
150 }
151 self.walk_import_directive(import)
152 }
153
154 fn visit_using_directive(
155 &mut self,
156 using: &'ast ast::UsingDirective<'ast>,
157 ) -> ControlFlow<Self::BreakValue> {
158 for pass in self.passes.iter_mut() {
159 pass.check_using_directive(self.ctx, using);
160 }
161 self.walk_using_directive(using)
162 }
163
164 fn visit_item_contract(
165 &mut self,
166 contract: &'ast ast::ItemContract<'ast>,
167 ) -> ControlFlow<Self::BreakValue> {
168 for pass in self.passes.iter_mut() {
169 pass.check_item_contract(self.ctx, contract);
170 }
171 self.walk_item_contract(contract)
172 }
173
174 }