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