]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/utils/inspector.rs
formatting fix
[rust.git] / clippy_lints / src / utils / inspector.rs
1 //! checks for attributes
2
3 use crate::utils::get_attr;
4 use rustc::hir;
5 use rustc::hir::print;
6 use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
7 use rustc::{declare_tool_lint, lint_array};
8 use syntax::ast::Attribute;
9
10 /// **What it does:** Dumps every ast/hir node which has the `#[clippy::dump]`
11 /// attribute
12 ///
13 /// **Example:**
14 /// ```rust
15 /// #[clippy::dump]
16 /// extern crate foo;
17 /// ```
18 ///
19 /// prints
20 ///
21 /// ```
22 /// item `foo`
23 /// visibility inherited from outer item
24 /// extern crate dylib source: "/path/to/foo.so"
25 /// ```
26 declare_clippy_lint! {
27     pub DEEP_CODE_INSPECTION,
28     internal_warn,
29     "helper to dump info about code"
30 }
31
32 pub struct Pass;
33
34 impl LintPass for Pass {
35     fn get_lints(&self) -> LintArray {
36         lint_array!(DEEP_CODE_INSPECTION)
37     }
38 }
39
40 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
41     fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) {
42         if !has_attr(&item.attrs) {
43             return;
44         }
45         print_item(cx, item);
46     }
47
48     fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem) {
49         if !has_attr(&item.attrs) {
50             return;
51         }
52         println!("impl item `{}`", item.ident.name);
53         match item.vis.node {
54             hir::VisibilityKind::Public => println!("public"),
55             hir::VisibilityKind::Crate(_) => println!("visible crate wide"),
56             hir::VisibilityKind::Restricted { ref path, .. } => println!(
57                 "visible in module `{}`",
58                 print::to_string(print::NO_ANN, |s| s.print_path(path, false))
59             ),
60             hir::VisibilityKind::Inherited => println!("visibility inherited from outer item"),
61         }
62         if item.defaultness.is_default() {
63             println!("default");
64         }
65         match item.node {
66             hir::ImplItemKind::Const(_, body_id) => {
67                 println!("associated constant");
68                 print_expr(cx, &cx.tcx.hir().body(body_id).value, 1);
69             },
70             hir::ImplItemKind::Method(..) => println!("method"),
71             hir::ImplItemKind::Type(_) => println!("associated type"),
72             hir::ImplItemKind::Existential(_) => println!("existential type"),
73         }
74     }
75     // fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx
76     // hir::TraitItem) {
77     // if !has_attr(&item.attrs) {
78     // return;
79     // }
80     // }
81     //
82     // fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, var: &'tcx
83     // hir::Variant, _:
84     // &hir::Generics) {
85     // if !has_attr(&var.node.attrs) {
86     // return;
87     // }
88     // }
89     //
90     // fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx
91     // hir::StructField) {
92     // if !has_attr(&field.attrs) {
93     // return;
94     // }
95     // }
96     //
97
98     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
99         if !has_attr(&expr.attrs) {
100             return;
101         }
102         print_expr(cx, expr, 0);
103     }
104
105     fn check_arm(&mut self, cx: &LateContext<'a, 'tcx>, arm: &'tcx hir::Arm) {
106         if !has_attr(&arm.attrs) {
107             return;
108         }
109         for pat in &arm.pats {
110             print_pat(cx, pat, 1);
111         }
112         if let Some(ref guard) = arm.guard {
113             println!("guard:");
114             print_guard(cx, guard, 1);
115         }
116         println!("body:");
117         print_expr(cx, &arm.body, 1);
118     }
119
120     fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx hir::Stmt) {
121         if !has_attr(stmt.node.attrs()) {
122             return;
123         }
124         match stmt.node {
125             hir::StmtKind::Decl(ref decl, _) => print_decl(cx, decl),
126             hir::StmtKind::Expr(ref e, _) | hir::StmtKind::Semi(ref e, _) => print_expr(cx, e, 0),
127         }
128     }
129     // fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx
130     // hir::ForeignItem) {
131     // if !has_attr(&item.attrs) {
132     // return;
133     // }
134     // }
135     //
136 }
137
138 fn has_attr(attrs: &[Attribute]) -> bool {
139     get_attr(attrs, "dump").count() > 0
140 }
141
142 fn print_decl(cx: &LateContext<'_, '_>, decl: &hir::Decl) {
143     match decl.node {
144         hir::DeclKind::Local(ref local) => {
145             println!("local variable of type {}", cx.tables.node_id_to_type(local.hir_id));
146             println!("pattern:");
147             print_pat(cx, &local.pat, 0);
148             if let Some(ref e) = local.init {
149                 println!("init expression:");
150                 print_expr(cx, e, 0);
151             }
152         },
153         hir::DeclKind::Item(_) => println!("item decl"),
154     }
155 }
156
157 #[allow(clippy::similar_names)]
158 fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) {
159     let ind = "  ".repeat(indent);
160     println!("{}+", ind);
161     println!("{}ty: {}", ind, cx.tables.expr_ty(expr));
162     println!("{}adjustments: {:?}", ind, cx.tables.adjustments().get(expr.hir_id));
163     match expr.node {
164         hir::ExprKind::Box(ref e) => {
165             println!("{}Box", ind);
166             print_expr(cx, e, indent + 1);
167         },
168         hir::ExprKind::Array(ref v) => {
169             println!("{}Array", ind);
170             for e in v {
171                 print_expr(cx, e, indent + 1);
172             }
173         },
174         hir::ExprKind::Call(ref func, ref args) => {
175             println!("{}Call", ind);
176             println!("{}function:", ind);
177             print_expr(cx, func, indent + 1);
178             println!("{}arguments:", ind);
179             for arg in args {
180                 print_expr(cx, arg, indent + 1);
181             }
182         },
183         hir::ExprKind::MethodCall(ref path, _, ref args) => {
184             println!("{}MethodCall", ind);
185             println!("{}method name: {}", ind, path.ident.name);
186             for arg in args {
187                 print_expr(cx, arg, indent + 1);
188             }
189         },
190         hir::ExprKind::Tup(ref v) => {
191             println!("{}Tup", ind);
192             for e in v {
193                 print_expr(cx, e, indent + 1);
194             }
195         },
196         hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
197             println!("{}Binary", ind);
198             println!("{}op: {:?}", ind, op.node);
199             println!("{}lhs:", ind);
200             print_expr(cx, lhs, indent + 1);
201             println!("{}rhs:", ind);
202             print_expr(cx, rhs, indent + 1);
203         },
204         hir::ExprKind::Unary(op, ref inner) => {
205             println!("{}Unary", ind);
206             println!("{}op: {:?}", ind, op);
207             print_expr(cx, inner, indent + 1);
208         },
209         hir::ExprKind::Lit(ref lit) => {
210             println!("{}Lit", ind);
211             println!("{}{:?}", ind, lit);
212         },
213         hir::ExprKind::Cast(ref e, ref target) => {
214             println!("{}Cast", ind);
215             print_expr(cx, e, indent + 1);
216             println!("{}target type: {:?}", ind, target);
217         },
218         hir::ExprKind::Type(ref e, ref target) => {
219             println!("{}Type", ind);
220             print_expr(cx, e, indent + 1);
221             println!("{}target type: {:?}", ind, target);
222         },
223         hir::ExprKind::If(ref e, _, ref els) => {
224             println!("{}If", ind);
225             println!("{}condition:", ind);
226             print_expr(cx, e, indent + 1);
227             if let Some(ref els) = *els {
228                 println!("{}else:", ind);
229                 print_expr(cx, els, indent + 1);
230             }
231         },
232         hir::ExprKind::While(ref cond, _, _) => {
233             println!("{}While", ind);
234             println!("{}condition:", ind);
235             print_expr(cx, cond, indent + 1);
236         },
237         hir::ExprKind::Loop(..) => {
238             println!("{}Loop", ind);
239         },
240         hir::ExprKind::Match(ref cond, _, ref source) => {
241             println!("{}Match", ind);
242             println!("{}condition:", ind);
243             print_expr(cx, cond, indent + 1);
244             println!("{}source: {:?}", ind, source);
245         },
246         hir::ExprKind::Closure(ref clause, _, _, _, _) => {
247             println!("{}Closure", ind);
248             println!("{}clause: {:?}", ind, clause);
249         },
250         hir::ExprKind::Yield(ref sub) => {
251             println!("{}Yield", ind);
252             print_expr(cx, sub, indent + 1);
253         },
254         hir::ExprKind::Block(_, _) => {
255             println!("{}Block", ind);
256         },
257         hir::ExprKind::Assign(ref lhs, ref rhs) => {
258             println!("{}Assign", ind);
259             println!("{}lhs:", ind);
260             print_expr(cx, lhs, indent + 1);
261             println!("{}rhs:", ind);
262             print_expr(cx, rhs, indent + 1);
263         },
264         hir::ExprKind::AssignOp(ref binop, ref lhs, ref rhs) => {
265             println!("{}AssignOp", ind);
266             println!("{}op: {:?}", ind, binop.node);
267             println!("{}lhs:", ind);
268             print_expr(cx, lhs, indent + 1);
269             println!("{}rhs:", ind);
270             print_expr(cx, rhs, indent + 1);
271         },
272         hir::ExprKind::Field(ref e, ident) => {
273             println!("{}Field", ind);
274             println!("{}field name: {}", ind, ident.name);
275             println!("{}struct expr:", ind);
276             print_expr(cx, e, indent + 1);
277         },
278         hir::ExprKind::Index(ref arr, ref idx) => {
279             println!("{}Index", ind);
280             println!("{}array expr:", ind);
281             print_expr(cx, arr, indent + 1);
282             println!("{}index expr:", ind);
283             print_expr(cx, idx, indent + 1);
284         },
285         hir::ExprKind::Path(hir::QPath::Resolved(ref ty, ref path)) => {
286             println!("{}Resolved Path, {:?}", ind, ty);
287             println!("{}path: {:?}", ind, path);
288         },
289         hir::ExprKind::Path(hir::QPath::TypeRelative(ref ty, ref seg)) => {
290             println!("{}Relative Path, {:?}", ind, ty);
291             println!("{}seg: {:?}", ind, seg);
292         },
293         hir::ExprKind::AddrOf(ref muta, ref e) => {
294             println!("{}AddrOf", ind);
295             println!("mutability: {:?}", muta);
296             print_expr(cx, e, indent + 1);
297         },
298         hir::ExprKind::Break(_, ref e) => {
299             println!("{}Break", ind);
300             if let Some(ref e) = *e {
301                 print_expr(cx, e, indent + 1);
302             }
303         },
304         hir::ExprKind::Continue(_) => println!("{}Again", ind),
305         hir::ExprKind::Ret(ref e) => {
306             println!("{}Ret", ind);
307             if let Some(ref e) = *e {
308                 print_expr(cx, e, indent + 1);
309             }
310         },
311         hir::ExprKind::InlineAsm(_, ref input, ref output) => {
312             println!("{}InlineAsm", ind);
313             println!("{}inputs:", ind);
314             for e in input {
315                 print_expr(cx, e, indent + 1);
316             }
317             println!("{}outputs:", ind);
318             for e in output {
319                 print_expr(cx, e, indent + 1);
320             }
321         },
322         hir::ExprKind::Struct(ref path, ref fields, ref base) => {
323             println!("{}Struct", ind);
324             println!("{}path: {:?}", ind, path);
325             for field in fields {
326                 println!("{}field \"{}\":", ind, field.ident.name);
327                 print_expr(cx, &field.expr, indent + 1);
328             }
329             if let Some(ref base) = *base {
330                 println!("{}base:", ind);
331                 print_expr(cx, base, indent + 1);
332             }
333         },
334         hir::ExprKind::Repeat(ref val, ref anon_const) => {
335             println!("{}Repeat", ind);
336             println!("{}value:", ind);
337             print_expr(cx, val, indent + 1);
338             println!("{}repeat count:", ind);
339             print_expr(cx, &cx.tcx.hir().body(anon_const.body).value, indent + 1);
340         },
341         hir::ExprKind::Err => {
342             println!("{}Err", ind);
343         },
344     }
345 }
346
347 fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item) {
348     let did = cx.tcx.hir().local_def_id(item.id);
349     println!("item `{}`", item.ident.name);
350     match item.vis.node {
351         hir::VisibilityKind::Public => println!("public"),
352         hir::VisibilityKind::Crate(_) => println!("visible crate wide"),
353         hir::VisibilityKind::Restricted { ref path, .. } => println!(
354             "visible in module `{}`",
355             print::to_string(print::NO_ANN, |s| s.print_path(path, false))
356         ),
357         hir::VisibilityKind::Inherited => println!("visibility inherited from outer item"),
358     }
359     match item.node {
360         hir::ItemKind::ExternCrate(ref _renamed_from) => {
361             let def_id = cx.tcx.hir().local_def_id(item.id);
362             if let Some(crate_id) = cx.tcx.extern_mod_stmt_cnum(def_id) {
363                 let source = cx.tcx.used_crate_source(crate_id);
364                 if let Some(ref src) = source.dylib {
365                     println!("extern crate dylib source: {:?}", src.0);
366                 }
367                 if let Some(ref src) = source.rlib {
368                     println!("extern crate rlib source: {:?}", src.0);
369                 }
370             } else {
371                 println!("weird extern crate without a crate id");
372             }
373         },
374         hir::ItemKind::Use(ref path, ref kind) => println!("{:?}, {:?}", path, kind),
375         hir::ItemKind::Static(..) => println!("static item of type {:#?}", cx.tcx.type_of(did)),
376         hir::ItemKind::Const(..) => println!("const item of type {:#?}", cx.tcx.type_of(did)),
377         hir::ItemKind::Fn(..) => {
378             let item_ty = cx.tcx.type_of(did);
379             println!("function of type {:#?}", item_ty);
380         },
381         hir::ItemKind::Mod(..) => println!("module"),
382         hir::ItemKind::ForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi),
383         hir::ItemKind::GlobalAsm(ref asm) => println!("global asm: {:?}", asm),
384         hir::ItemKind::Ty(..) => {
385             println!("type alias for {:?}", cx.tcx.type_of(did));
386         },
387         hir::ItemKind::Existential(..) => {
388             println!("existential type with real type {:?}", cx.tcx.type_of(did));
389         },
390         hir::ItemKind::Enum(..) => {
391             println!("enum definition of type {:?}", cx.tcx.type_of(did));
392         },
393         hir::ItemKind::Struct(..) => {
394             println!("struct definition of type {:?}", cx.tcx.type_of(did));
395         },
396         hir::ItemKind::Union(..) => {
397             println!("union definition of type {:?}", cx.tcx.type_of(did));
398         },
399         hir::ItemKind::Trait(..) => {
400             println!("trait decl");
401             if cx.tcx.trait_is_auto(did) {
402                 println!("trait is auto");
403             } else {
404                 println!("trait is not auto");
405             }
406         },
407         hir::ItemKind::TraitAlias(..) => {
408             println!("trait alias");
409         },
410         hir::ItemKind::Impl(_, _, _, _, Some(ref _trait_ref), _, _) => {
411             println!("trait impl");
412         },
413         hir::ItemKind::Impl(_, _, _, _, None, _, _) => {
414             println!("impl");
415         },
416     }
417 }
418
419 #[allow(clippy::similar_names)]
420 fn print_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat, indent: usize) {
421     let ind = "  ".repeat(indent);
422     println!("{}+", ind);
423     match pat.node {
424         hir::PatKind::Wild => println!("{}Wild", ind),
425         hir::PatKind::Binding(ref mode, _, ident, ref inner) => {
426             println!("{}Binding", ind);
427             println!("{}mode: {:?}", ind, mode);
428             println!("{}name: {}", ind, ident.name);
429             if let Some(ref inner) = *inner {
430                 println!("{}inner:", ind);
431                 print_pat(cx, inner, indent + 1);
432             }
433         },
434         hir::PatKind::Struct(ref path, ref fields, ignore) => {
435             println!("{}Struct", ind);
436             println!(
437                 "{}name: {}",
438                 ind,
439                 print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))
440             );
441             println!("{}ignore leftover fields: {}", ind, ignore);
442             println!("{}fields:", ind);
443             for field in fields {
444                 println!("{}  field name: {}", ind, field.node.ident.name);
445                 if field.node.is_shorthand {
446                     println!("{}  in shorthand notation", ind);
447                 }
448                 print_pat(cx, &field.node.pat, indent + 1);
449             }
450         },
451         hir::PatKind::TupleStruct(ref path, ref fields, opt_dots_position) => {
452             println!("{}TupleStruct", ind);
453             println!(
454                 "{}path: {}",
455                 ind,
456                 print::to_string(print::NO_ANN, |s| s.print_qpath(path, false))
457             );
458             if let Some(dot_position) = opt_dots_position {
459                 println!("{}dot position: {}", ind, dot_position);
460             }
461             for field in fields {
462                 print_pat(cx, field, indent + 1);
463             }
464         },
465         hir::PatKind::Path(hir::QPath::Resolved(ref ty, ref path)) => {
466             println!("{}Resolved Path, {:?}", ind, ty);
467             println!("{}path: {:?}", ind, path);
468         },
469         hir::PatKind::Path(hir::QPath::TypeRelative(ref ty, ref seg)) => {
470             println!("{}Relative Path, {:?}", ind, ty);
471             println!("{}seg: {:?}", ind, seg);
472         },
473         hir::PatKind::Tuple(ref pats, opt_dots_position) => {
474             println!("{}Tuple", ind);
475             if let Some(dot_position) = opt_dots_position {
476                 println!("{}dot position: {}", ind, dot_position);
477             }
478             for field in pats {
479                 print_pat(cx, field, indent + 1);
480             }
481         },
482         hir::PatKind::Box(ref inner) => {
483             println!("{}Box", ind);
484             print_pat(cx, inner, indent + 1);
485         },
486         hir::PatKind::Ref(ref inner, ref muta) => {
487             println!("{}Ref", ind);
488             println!("{}mutability: {:?}", ind, muta);
489             print_pat(cx, inner, indent + 1);
490         },
491         hir::PatKind::Lit(ref e) => {
492             println!("{}Lit", ind);
493             print_expr(cx, e, indent + 1);
494         },
495         hir::PatKind::Range(ref l, ref r, ref range_end) => {
496             println!("{}Range", ind);
497             print_expr(cx, l, indent + 1);
498             print_expr(cx, r, indent + 1);
499             match *range_end {
500                 hir::RangeEnd::Included => println!("{} end included", ind),
501                 hir::RangeEnd::Excluded => println!("{} end excluded", ind),
502             }
503         },
504         hir::PatKind::Slice(ref first_pats, ref range, ref last_pats) => {
505             println!("{}Slice [a, b, ..i, y, z]", ind);
506             println!("[a, b]:");
507             for pat in first_pats {
508                 print_pat(cx, pat, indent + 1);
509             }
510             println!("i:");
511             if let Some(ref pat) = *range {
512                 print_pat(cx, pat, indent + 1);
513             }
514             println!("[y, z]:");
515             for pat in last_pats {
516                 print_pat(cx, pat, indent + 1);
517             }
518         },
519     }
520 }
521
522 fn print_guard(cx: &LateContext<'_, '_>, guard: &hir::Guard, indent: usize) {
523     let ind = "  ".repeat(indent);
524     println!("{}+", ind);
525     match guard {
526         hir::Guard::If(expr) => {
527             println!("{}If", ind);
528             print_expr(cx, expr, indent + 1);
529         },
530     }
531 }