1use solar::{interface::data_structures::Never, sema::hir};
2use std::ops::ControlFlow;
3
4use super::LintContext;
5
6pub trait LateLintPass<'hir>: Send + Sync {
9 fn check_nested_source(
10 &mut self,
11 _ctx: &LintContext,
12 _hir: &'hir hir::Hir<'hir>,
13 _id: hir::SourceId,
14 ) {
15 }
16 fn check_nested_item(
17 &mut self,
18 _ctx: &LintContext,
19 _hir: &'hir hir::Hir<'hir>,
20 _id: &'hir hir::ItemId,
21 ) {
22 }
23 fn check_nested_contract(
24 &mut self,
25 _ctx: &LintContext,
26 _hir: &'hir hir::Hir<'hir>,
27 _id: &'hir hir::ContractId,
28 ) {
29 }
30 fn check_nested_function(
31 &mut self,
32 _ctx: &LintContext,
33 _hir: &'hir hir::Hir<'hir>,
34 _id: &'hir hir::FunctionId,
35 ) {
36 }
37 fn check_nested_var(
38 &mut self,
39 _ctx: &LintContext,
40 _hir: &'hir hir::Hir<'hir>,
41 _id: &'hir hir::VariableId,
42 ) {
43 }
44 fn check_item(
45 &mut self,
46 _ctx: &LintContext,
47 _hir: &'hir hir::Hir<'hir>,
48 _item: hir::Item<'hir, 'hir>,
49 ) {
50 }
51 fn check_contract(
52 &mut self,
53 _ctx: &LintContext,
54 _hir: &'hir hir::Hir<'hir>,
55 _contract: &'hir hir::Contract<'hir>,
56 ) {
57 }
58 fn check_function(
59 &mut self,
60 _ctx: &LintContext,
61 _hir: &'hir hir::Hir<'hir>,
62 _func: &'hir hir::Function<'hir>,
63 ) {
64 }
65 fn check_modifier(
66 &mut self,
67 _ctx: &LintContext,
68 _hir: &'hir hir::Hir<'hir>,
69 _mod: &'hir hir::Modifier<'hir>,
70 ) {
71 }
72 fn check_var(
73 &mut self,
74 _ctx: &LintContext,
75 _hir: &'hir hir::Hir<'hir>,
76 _var: &'hir hir::Variable<'hir>,
77 ) {
78 }
79 fn check_expr(
80 &mut self,
81 _ctx: &LintContext,
82 _hir: &'hir hir::Hir<'hir>,
83 _expr: &'hir hir::Expr<'hir>,
84 ) {
85 }
86 fn check_call_args(
87 &mut self,
88 _ctx: &LintContext,
89 _hir: &'hir hir::Hir<'hir>,
90 _args: &'hir hir::CallArgs<'hir>,
91 ) {
92 }
93 fn check_stmt(
94 &mut self,
95 _ctx: &LintContext,
96 _hir: &'hir hir::Hir<'hir>,
97 _stmt: &'hir hir::Stmt<'hir>,
98 ) {
99 }
100 fn check_ty(
101 &mut self,
102 _ctx: &LintContext,
103 _hir: &'hir hir::Hir<'hir>,
104 _ty: &'hir hir::Type<'hir>,
105 ) {
106 }
107}
108
109pub struct LateLintVisitor<'a, 's, 'hir> {
111 ctx: &'a LintContext<'s, 'a>,
112 passes: &'a mut [Box<dyn LateLintPass<'hir> + 's>],
113 hir: &'hir hir::Hir<'hir>,
114}
115
116impl<'a, 's, 'hir> LateLintVisitor<'a, 's, 'hir>
117where
118 's: 'hir,
119{
120 pub fn new(
121 ctx: &'a LintContext<'s, 'a>,
122 passes: &'a mut [Box<dyn LateLintPass<'hir> + 's>],
123 hir: &'hir hir::Hir<'hir>,
124 ) -> Self {
125 Self { ctx, passes, hir }
126 }
127}
128
129impl<'s, 'hir> hir::Visit<'hir> for LateLintVisitor<'_, 's, 'hir>
130where
131 's: 'hir,
132{
133 type BreakValue = Never;
134
135 fn hir(&self) -> &'hir hir::Hir<'hir> {
136 self.hir
137 }
138
139 fn visit_nested_source(&mut self, id: hir::SourceId) -> ControlFlow<Self::BreakValue> {
140 for pass in self.passes.iter_mut() {
141 pass.check_nested_source(self.ctx, self.hir, id);
142 }
143 self.walk_nested_source(id)
144 }
145
146 fn visit_contract(
147 &mut self,
148 contract: &'hir hir::Contract<'hir>,
149 ) -> ControlFlow<Self::BreakValue> {
150 for pass in self.passes.iter_mut() {
151 pass.check_contract(self.ctx, self.hir, contract);
152 }
153 self.walk_contract(contract)
154 }
155
156 fn visit_function(&mut self, func: &'hir hir::Function<'hir>) -> ControlFlow<Self::BreakValue> {
157 for pass in self.passes.iter_mut() {
158 pass.check_function(self.ctx, self.hir, func);
159 }
160 self.walk_function(func)
161 }
162
163 fn visit_item(&mut self, item: hir::Item<'hir, 'hir>) -> ControlFlow<Self::BreakValue> {
164 for pass in self.passes.iter_mut() {
165 pass.check_item(self.ctx, self.hir, item);
166 }
167 self.walk_item(item)
168 }
169
170 fn visit_var(&mut self, var: &'hir hir::Variable<'hir>) -> ControlFlow<Self::BreakValue> {
171 for pass in self.passes.iter_mut() {
172 pass.check_var(self.ctx, self.hir, var);
173 }
174 self.walk_var(var)
175 }
176
177 fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) -> ControlFlow<Self::BreakValue> {
178 for pass in self.passes.iter_mut() {
179 pass.check_expr(self.ctx, self.hir, expr);
180 }
181 self.walk_expr(expr)
182 }
183
184 fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'hir>) -> ControlFlow<Self::BreakValue> {
185 for pass in self.passes.iter_mut() {
186 pass.check_stmt(self.ctx, self.hir, stmt);
187 }
188 self.walk_stmt(stmt)
189 }
190
191 fn visit_ty(&mut self, ty: &'hir hir::Type<'hir>) -> ControlFlow<Self::BreakValue> {
192 for pass in self.passes.iter_mut() {
193 pass.check_ty(self.ctx, self.hir, ty);
194 }
195 self.walk_ty(ty)
196 }
197}