Skip to content

Commit

Permalink
Auto merge of #8701 - xFrednet:0000-clippy-print-hir-attr, r=flip1995
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Apr 18, 2022
2 parents e5ebece + ccedc64 commit 95de4dc
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 558 deletions.
2 changes: 1 addition & 1 deletion clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
{
store.register_early_pass(|| Box::new(utils::internal_lints::ClippyLintsInternal));
store.register_early_pass(|| Box::new(utils::internal_lints::ProduceIce));
store.register_late_pass(|| Box::new(utils::inspector::DeepCodeInspector));
store.register_late_pass(|| Box::new(utils::internal_lints::CollapsibleCalls));
store.register_late_pass(|| Box::new(utils::internal_lints::CompilerLintFunctions::new()));
store.register_late_pass(|| Box::new(utils::internal_lints::IfChainStyle));
Expand All @@ -514,6 +513,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| Box::new(utils::internal_lints::MsrvAttrImpl));
}

store.register_late_pass(|| Box::new(utils::dump_hir::DumpHir));
store.register_late_pass(|| Box::new(utils::author::Author));
store.register_late_pass(|| Box::new(await_holding_invalid::AwaitHolding));
store.register_late_pass(|| Box::new(serde_api::SerdeApi));
Expand Down
55 changes: 55 additions & 0 deletions clippy_lints/src/utils/dump_hir.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use clippy_utils::get_attr;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
/// ### What it does
/// It formats the attached node with `{:#?}` and writes the result to the
/// standard output. This is intended for debugging.
///
/// ### Examples
/// ```rs
/// #[clippy::dump]
/// use std::mem;
///
/// #[clippy::dump]
/// fn foo(input: u32) -> u64 {
/// input as u64
/// }
/// ```
pub DUMP_HIR,
internal_warn,
"helper to dump info about code"
}

declare_lint_pass!(DumpHir => [DUMP_HIR]);

impl<'tcx> LateLintPass<'tcx> for DumpHir {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
if has_attr(cx, item.hir_id()) {
println!("{item:#?}");
}
}

fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
if has_attr(cx, expr.hir_id) {
println!("{expr:#?}");
}
}

fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx hir::Stmt<'_>) {
match stmt.kind {
hir::StmtKind::Expr(e) | hir::StmtKind::Semi(e) if has_attr(cx, e.hir_id) => return,
_ => {},
}
if has_attr(cx, stmt.hir_id) {
println!("{stmt:#?}");
}
}
}

fn has_attr(cx: &LateContext<'_>, hir_id: hir::HirId) -> bool {
let attrs = cx.tcx.hir().attrs(hir_id);
get_attr(cx.sess(), attrs, "dump").count() > 0
}
Loading

0 comments on commit 95de4dc

Please sign in to comment.