Skip to content

Commit 73501da

Browse files
committed
Add expr_visitor util
1 parent 1c4dd8d commit 73501da

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

clippy_utils/src/visitors.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,51 @@ use rustc_lint::LateContext;
66
use rustc_middle::hir::map::Map;
77
use std::ops::ControlFlow;
88

9+
/// Convenience method for creating a `Visitor` with just `visit_expr` overridden and nested
10+
/// bodies (i.e. closures) are visited.
11+
/// If the callback returns `true`, the expr just provided to the callback is walked.
12+
#[must_use]
13+
pub fn expr_visitor<'tcx>(cx: &LateContext<'tcx>, f: impl FnMut(&'tcx Expr<'tcx>) -> bool) -> impl Visitor<'tcx> {
14+
struct V<'tcx, F> {
15+
hir: Map<'tcx>,
16+
f: F,
17+
}
18+
impl<'tcx, F: FnMut(&'tcx Expr<'tcx>) -> bool> Visitor<'tcx> for V<'tcx, F> {
19+
type Map = Map<'tcx>;
20+
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
21+
NestedVisitorMap::OnlyBodies(self.hir)
22+
}
23+
24+
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
25+
if (self.f)(expr) {
26+
walk_expr(self, expr);
27+
}
28+
}
29+
}
30+
V { hir: cx.tcx.hir(), f }
31+
}
32+
33+
/// Convenience method for creating a `Visitor` with just `visit_expr` overridden and nested
34+
/// bodies (i.e. closures) are not visited.
35+
/// If the callback returns `true`, the expr just provided to the callback is walked.
36+
#[must_use]
37+
pub fn expr_visitor_no_bodies<'tcx>(f: impl FnMut(&'tcx Expr<'tcx>) -> bool) -> impl Visitor<'tcx> {
38+
struct V<F>(F);
39+
impl<'tcx, F: FnMut(&'tcx Expr<'tcx>) -> bool> Visitor<'tcx> for V<F> {
40+
type Map = intravisit::ErasedMap<'tcx>;
41+
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
42+
NestedVisitorMap::None
43+
}
44+
45+
fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
46+
if (self.0)(e) {
47+
walk_expr(self, e);
48+
}
49+
}
50+
}
51+
V(f)
52+
}
53+
954
/// returns `true` if expr contains match expr desugared from try
1055
fn contains_try(expr: &hir::Expr<'_>) -> bool {
1156
struct TryFinder {

0 commit comments

Comments
 (0)