Skip to content

Commit 95de4dc

Browse files
committed
Auto merge of #8701 - xFrednet:0000-clippy-print-hir-attr, r=flip1995
Rework `#[clippy::dump]` attribute for debugging Hey `@rust-lang/clippy,` this adds a new `#[clippy::print_hir]` attribute that prints the node to the console using `{:#?}`. Personally, I use print debugging quite a lot while working on Clippy, and this is a simple shortcut that also works in the playground (Once this has been synced). The question is now, if we want to have this attribute. Are there any concerns? I think it's similar to our `#[clippy::author]` attribute. I haven't added a test, as the `.stdout` file would require updates with every HIR change inside rustc. Here are some examples, for the current implementation <details> <summary>`do_something(&map);`</summary> ```rs Expr { hir_id: HirId { owner: DefId(0:7 ~ aaa[995b]::main), local_id: 21, }, kind: Call( Expr { hir_id: HirId { owner: DefId(0:7 ~ aaa[995b]::main), local_id: 17, }, kind: Path( Resolved( None, Path { span: tests/ui/aaa.rs:23:5: 23:17 (#0), res: Def( Fn, DefId(0:6 ~ aaa[995b]::do_something), ), segments: [ PathSegment { ident: do_something#0, hir_id: Some( HirId { owner: DefId(0:7 ~ aaa[995b]::main), local_id: 16, }, ), res: Some( Err, ), args: None, infer_args: true, }, ], }, ), ), span: tests/ui/aaa.rs:23:5: 23:17 (#0), }, [ Expr { hir_id: HirId { owner: DefId(0:7 ~ aaa[995b]::main), local_id: 20, }, kind: AddrOf( Ref, Not, Expr { hir_id: HirId { owner: DefId(0:7 ~ aaa[995b]::main), local_id: 19, }, kind: Path( Resolved( None, Path { span: tests/ui/aaa.rs:23:19: 23:22 (#0), res: Local( HirId { owner: DefId(0:7 ~ aaa[995b]::main), local_id: 15, }, ), segments: [ PathSegment { ident: map#0, hir_id: Some( HirId { owner: DefId(0:7 ~ aaa[995b]::main), local_id: 18, }, ), res: Some( Local( HirId { owner: DefId(0:7 ~ aaa[995b]::main), local_id: 15, }, ), ), args: None, infer_args: true, }, ], }, ), ), span: tests/ui/aaa.rs:23:19: 23:22 (#0), }, ), span: tests/ui/aaa.rs:23:18: 23:22 (#0), }, ], ), span: tests/ui/aaa.rs:23:5: 23:23 (#0), } ``` </details> <details> <summary>`use std::collections::HashMap;`</summary> ```rs Item { ident: HashMap#0, def_id: DefId(0:5 ~ aaa[995b]::{misc#1}), kind: Use( Path { span: tests/ui/aaa.rs:8:5: 8:30 (#0), res: Def( Struct, DefId(1:1294 ~ std[928b]::collections::hash::map::HashMap), ), segments: [ PathSegment { ident: std#0, hir_id: Some( HirId { owner: DefId(0:5 ~ aaa[995b]::{misc#1}), local_id: 1, }, ), res: Some( Def( Mod, DefId(1:0 ~ std[928b]), ), ), args: None, infer_args: false, }, PathSegment { ident: collections#0, hir_id: Some( HirId { owner: DefId(0:5 ~ aaa[995b]::{misc#1}), local_id: 2, }, ), res: Some( Def( Mod, DefId(1:1193 ~ std[928b]::collections), ), ), args: None, infer_args: false, }, PathSegment { ident: HashMap#0, hir_id: Some( HirId { owner: DefId(0:5 ~ aaa[995b]::{misc#1}), local_id: 3, }, ), res: Some( Err, ), args: None, infer_args: false, }, ], }, Single, ), vis: Spanned { node: Inherited, span: tests/ui/aaa.rs:8:1: 8:1 (#0), }, span: tests/ui/aaa.rs:8:1: 8:31 (#0), } ``` </details> <details> <summary>`"100"`</summary> ```rs Expr { hir_id: HirId { owner: DefId(0:7 ~ aaa[995b]::main), local_id: 27, }, kind: Lit( Spanned { node: Str( "100", Cooked, ), span: tests/ui/aaa.rs:28:9: 28:14 (#0), }, ), span: tests/ui/aaa.rs:28:9: 28:14 (#0), } ``` </details> --- changelog: Added `[clippy::print_hir]` to inspect rustc's internal representation
2 parents e5ebece + ccedc64 commit 95de4dc

File tree

6 files changed

+72
-558
lines changed

6 files changed

+72
-558
lines changed

clippy_lints/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
502502
{
503503
store.register_early_pass(|| Box::new(utils::internal_lints::ClippyLintsInternal));
504504
store.register_early_pass(|| Box::new(utils::internal_lints::ProduceIce));
505-
store.register_late_pass(|| Box::new(utils::inspector::DeepCodeInspector));
506505
store.register_late_pass(|| Box::new(utils::internal_lints::CollapsibleCalls));
507506
store.register_late_pass(|| Box::new(utils::internal_lints::CompilerLintFunctions::new()));
508507
store.register_late_pass(|| Box::new(utils::internal_lints::IfChainStyle));
@@ -514,6 +513,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
514513
store.register_late_pass(|| Box::new(utils::internal_lints::MsrvAttrImpl));
515514
}
516515

516+
store.register_late_pass(|| Box::new(utils::dump_hir::DumpHir));
517517
store.register_late_pass(|| Box::new(utils::author::Author));
518518
store.register_late_pass(|| Box::new(await_holding_invalid::AwaitHolding));
519519
store.register_late_pass(|| Box::new(serde_api::SerdeApi));

clippy_lints/src/utils/dump_hir.rs

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use clippy_utils::get_attr;
2+
use rustc_hir as hir;
3+
use rustc_lint::{LateContext, LateLintPass, LintContext};
4+
use rustc_session::{declare_lint_pass, declare_tool_lint};
5+
6+
declare_clippy_lint! {
7+
/// ### What it does
8+
/// It formats the attached node with `{:#?}` and writes the result to the
9+
/// standard output. This is intended for debugging.
10+
///
11+
/// ### Examples
12+
/// ```rs
13+
/// #[clippy::dump]
14+
/// use std::mem;
15+
///
16+
/// #[clippy::dump]
17+
/// fn foo(input: u32) -> u64 {
18+
/// input as u64
19+
/// }
20+
/// ```
21+
pub DUMP_HIR,
22+
internal_warn,
23+
"helper to dump info about code"
24+
}
25+
26+
declare_lint_pass!(DumpHir => [DUMP_HIR]);
27+
28+
impl<'tcx> LateLintPass<'tcx> for DumpHir {
29+
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
30+
if has_attr(cx, item.hir_id()) {
31+
println!("{item:#?}");
32+
}
33+
}
34+
35+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
36+
if has_attr(cx, expr.hir_id) {
37+
println!("{expr:#?}");
38+
}
39+
}
40+
41+
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) {
42+
match stmt.kind {
43+
hir::StmtKind::Expr(e) | hir::StmtKind::Semi(e) if has_attr(cx, e.hir_id) => return,
44+
_ => {},
45+
}
46+
if has_attr(cx, stmt.hir_id) {
47+
println!("{stmt:#?}");
48+
}
49+
}
50+
}
51+
52+
fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
53+
let attrs = cx.tcx.hir().attrs(hir_id);
54+
get_attr(cx.sess(), attrs, "dump").count() > 0
55+
}

0 commit comments

Comments
 (0)