forge_lint/linter/
late.rs

1use solar::{interface::data_structures::Never, sema::hir};
2use std::ops::ControlFlow;
3
4use super::LintContext;
5
6/// Trait for lints that operate on the HIR (High-level Intermediate Representation).
7/// Its methods mirror `hir::visit::Visit`, with the addition of `LintCotext`.
8pub 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
109/// Visitor struct for `LateLintPass`es
110pub 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}