]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/utils/inspector.rs
Rustup to *rustc 1.20.0-nightly (d84693b93 2017-07-09)*
[rust.git] / clippy_lints / src / utils / inspector.rs
1 #![allow(print_stdout, use_debug)]
2
3 //! checks for attributes
4
5 use rustc::lint::*;
6 use rustc::hir;
7 use rustc::hir::print;
8 use syntax::ast::Attribute;
9 use syntax::attr;
10
11 /// **What it does:** Dumps every ast/hir node which has the `#[clippy_dump]` 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_lint! {
27     pub DEEP_CODE_INSPECTION,
28     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.name);
53         match item.vis {
54             hir::Visibility::Public => println!("public"),
55             hir::Visibility::Crate => println!("visible crate wide"),
56             hir::Visibility::Restricted { ref path, .. } => {
57                 println!("visible in module `{}`",
58                          print::to_string(print::NO_ANN, |s| s.print_path(path, false)))
59             },
60             hir::Visibility::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         }
73     }
74     // fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) {
75     // if !has_attr(&item.attrs) {
76     // return;
77     // }
78     // }
79     //
80     // fn check_variant(&mut self, cx: &LateContext<'a, 'tcx>, var: &'tcx hir::Variant, _:
81     // &hir::Generics) {
82     // if !has_attr(&var.node.attrs) {
83     // return;
84     // }
85     // }
86     //
87     // fn check_struct_field(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx hir::StructField) {
88     // if !has_attr(&field.attrs) {
89     // return;
90     // }
91     // }
92     //
93
94     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
95         if !has_attr(&expr.attrs) {
96             return;
97         }
98         print_expr(cx, expr, 0);
99     }
100
101     fn check_arm(&mut self, cx: &LateContext<'a, 'tcx>, arm: &'tcx hir::Arm) {
102         if !has_attr(&arm.attrs) {
103             return;
104         }
105         for pat in &arm.pats {
106             print_pat(cx, pat, 1);
107         }
108         if let Some(ref guard) = arm.guard {
109             println!("guard:");
110             print_expr(cx, guard, 1);
111         }
112         println!("body:");
113         print_expr(cx, &arm.body, 1);
114     }
115
116     fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx hir::Stmt) {
117         if !has_attr(stmt.node.attrs()) {
118             return;
119         }
120         match stmt.node {
121             hir::StmtDecl(ref decl, _) => print_decl(cx, decl),
122             hir::StmtExpr(ref e, _) |
123             hir::StmtSemi(ref e, _) => print_expr(cx, e, 0),
124         }
125     }
126     // fn check_foreign_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ForeignItem) {
127     // if !has_attr(&item.attrs) {
128     // return;
129     // }
130     // }
131     //
132 }
133
134 fn has_attr(attrs: &[Attribute]) -> bool {
135     attr::contains_name(attrs, "clippy_dump")
136 }
137
138 fn print_decl(cx: &LateContext, decl: &hir::Decl) {
139     match decl.node {
140         hir::DeclLocal(ref local) => {
141             println!("local variable of type {}", cx.tables.node_id_to_type(local.id));
142             println!("pattern:");
143             print_pat(cx, &local.pat, 0);
144             if let Some(ref e) = local.init {
145                 println!("init expression:");
146                 print_expr(cx, e, 0);
147             }
148         },
149         hir::DeclItem(_) => println!("item decl"),
150     }
151 }
152
153 fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) {
154     let ind = "  ".repeat(indent);
155     println!("{}+", ind);
156     println!("{}ty: {}", ind, cx.tables.expr_ty(expr));
157     println!("{}adjustments: {:?}", ind, cx.tables.adjustments.get(&expr.id));
158     match expr.node {
159         hir::ExprBox(ref e) => {
160             println!("{}Box", ind);
161             print_expr(cx, e, indent + 1);
162         },
163         hir::ExprArray(ref v) => {
164             println!("{}Array", ind);
165             for e in v {
166                 print_expr(cx, e, indent + 1);
167             }
168         },
169         hir::ExprCall(ref func, ref args) => {
170             println!("{}Call", ind);
171             println!("{}function:", ind);
172             print_expr(cx, func, indent + 1);
173             println!("{}arguments:", ind);
174             for arg in args {
175                 print_expr(cx, arg, indent + 1);
176             }
177         },
178         hir::ExprMethodCall(ref path, _, ref args) => {
179             println!("{}MethodCall", ind);
180             println!("{}method name: {}", ind, path.name);
181             for arg in args {
182                 print_expr(cx, arg, indent + 1);
183             }
184         },
185         hir::ExprTup(ref v) => {
186             println!("{}Tup", ind);
187             for e in v {
188                 print_expr(cx, e, indent + 1);
189             }
190         },
191         hir::ExprBinary(op, ref lhs, ref rhs) => {
192             println!("{}Binary", ind);
193             println!("{}op: {:?}", ind, op.node);
194             println!("{}lhs:", ind);
195             print_expr(cx, lhs, indent + 1);
196             println!("{}rhs:", ind);
197             print_expr(cx, rhs, indent + 1);
198         },
199         hir::ExprUnary(op, ref inner) => {
200             println!("{}Unary", ind);
201             println!("{}op: {:?}", ind, op);
202             print_expr(cx, inner, indent + 1);
203         },
204         hir::ExprLit(ref lit) => {
205             println!("{}Lit", ind);
206             println!("{}{:?}", ind, lit);
207         },
208         hir::ExprCast(ref e, ref target) => {
209             println!("{}Cast", ind);
210             print_expr(cx, e, indent + 1);
211             println!("{}target type: {:?}", ind, target);
212         },
213         hir::ExprType(ref e, ref target) => {
214             println!("{}Type", ind);
215             print_expr(cx, e, indent + 1);
216             println!("{}target type: {:?}", ind, target);
217         },
218         hir::ExprIf(ref e, _, ref els) => {
219             println!("{}If", ind);
220             println!("{}condition:", ind);
221             print_expr(cx, e, indent + 1);
222             if let Some(ref els) = *els {
223                 println!("{}else:", ind);
224                 print_expr(cx, els, indent + 1);
225             }
226         },
227         hir::ExprWhile(ref cond, _, _) => {
228             println!("{}While", ind);
229             println!("{}condition:", ind);
230             print_expr(cx, cond, indent + 1);
231         },
232         hir::ExprLoop(..) => {
233             println!("{}Loop", ind);
234         },
235         hir::ExprMatch(ref cond, _, ref source) => {
236             println!("{}Match", ind);
237             println!("{}condition:", ind);
238             print_expr(cx, cond, indent + 1);
239             println!("{}source: {:?}", ind, source);
240         },
241         hir::ExprClosure(ref clause, _, _, _) => {
242             println!("{}Closure", ind);
243             println!("{}clause: {:?}", ind, clause);
244         },
245         hir::ExprBlock(_) => {
246             println!("{}Block", ind);
247         },
248         hir::ExprAssign(ref lhs, ref rhs) => {
249             println!("{}Assign", ind);
250             println!("{}lhs:", ind);
251             print_expr(cx, lhs, indent + 1);
252             println!("{}rhs:", ind);
253             print_expr(cx, rhs, indent + 1);
254         },
255         hir::ExprAssignOp(ref binop, ref lhs, ref rhs) => {
256             println!("{}AssignOp", ind);
257             println!("{}op: {:?}", ind, binop.node);
258             println!("{}lhs:", ind);
259             print_expr(cx, lhs, indent + 1);
260             println!("{}rhs:", ind);
261             print_expr(cx, rhs, indent + 1);
262         },
263         hir::ExprField(ref e, ref name) => {
264             println!("{}Field", ind);
265             println!("{}field name: {}", ind, name.node);
266             println!("{}struct expr:", ind);
267             print_expr(cx, e, indent + 1);
268         },
269         hir::ExprTupField(ref e, ref idx) => {
270             println!("{}TupField", ind);
271             println!("{}field index: {}", ind, idx.node);
272             println!("{}tuple expr:", ind);
273             print_expr(cx, e, indent + 1);
274         },
275         hir::ExprIndex(ref arr, ref idx) => {
276             println!("{}Index", ind);
277             println!("{}array expr:", ind);
278             print_expr(cx, arr, indent + 1);
279             println!("{}index expr:", ind);
280             print_expr(cx, idx, indent + 1);
281         },
282         hir::ExprPath(hir::QPath::Resolved(ref ty, ref path)) => {
283             println!("{}Resolved Path, {:?}", ind, ty);
284             println!("{}path: {:?}", ind, path);
285         },
286         hir::ExprPath(hir::QPath::TypeRelative(ref ty, ref seg)) => {
287             println!("{}Relative Path, {:?}", ind, ty);
288             println!("{}seg: {:?}", ind, seg);
289         },
290         hir::ExprAddrOf(ref muta, ref e) => {
291             println!("{}AddrOf", ind);
292             println!("mutability: {:?}", muta);
293             print_expr(cx, e, indent + 1);
294         },
295         hir::ExprBreak(_, ref e) => {
296             println!("{}Break", ind);
297             if let Some(ref e) = *e {
298                 print_expr(cx, e, indent + 1);
299             }
300         },
301         hir::ExprAgain(_) => println!("{}Again", ind),
302         hir::ExprRet(ref e) => {
303             println!("{}Ret", ind);
304             if let Some(ref e) = *e {
305                 print_expr(cx, e, indent + 1);
306             }
307         },
308         hir::ExprInlineAsm(_, ref input, ref output) => {
309             println!("{}InlineAsm", ind);
310             println!("{}inputs:", ind);
311             for e in input {
312                 print_expr(cx, e, indent + 1);
313             }
314             println!("{}outputs:", ind);
315             for e in output {
316                 print_expr(cx, e, indent + 1);
317             }
318         },
319         hir::ExprStruct(ref path, ref fields, ref base) => {
320             println!("{}Struct", ind);
321             println!("{}path: {:?}", ind, path);
322             for field in fields {
323                 println!("{}field \"{}\":", ind, field.name.node);
324                 print_expr(cx, &field.expr, indent + 1);
325             }
326             if let Some(ref base) = *base {
327                 println!("{}base:", ind);
328                 print_expr(cx, base, indent + 1);
329             }
330         },
331         hir::ExprRepeat(ref val, body_id) => {
332             println!("{}Repeat", ind);
333             println!("{}value:", ind);
334             print_expr(cx, val, indent + 1);
335             println!("{}repeat count:", ind);
336             print_expr(cx, &cx.tcx.hir.body(body_id).value, indent + 1);
337         },
338     }
339 }
340
341 fn print_item(cx: &LateContext, item: &hir::Item) {
342     let did = cx.tcx.hir.local_def_id(item.id);
343     println!("item `{}`", item.name);
344     match item.vis {
345         hir::Visibility::Public => println!("public"),
346         hir::Visibility::Crate => println!("visible crate wide"),
347         hir::Visibility::Restricted { ref path, .. } => {
348             println!("visible in module `{}`",
349                      print::to_string(print::NO_ANN, |s| s.print_path(path, false)))
350         },
351         hir::Visibility::Inherited => println!("visibility inherited from outer item"),
352     }
353     match item.node {
354         hir::ItemExternCrate(ref _renamed_from) => {
355             if let Some(crate_id) = cx.tcx.sess.cstore.extern_mod_stmt_cnum(item.id) {
356                 let source = cx.tcx.sess.cstore.used_crate_source(crate_id);
357                 if let Some(src) = source.dylib {
358                     println!("extern crate dylib source: {:?}", src.0);
359                 }
360                 if let Some(src) = source.rlib {
361                     println!("extern crate rlib source: {:?}", src.0);
362                 }
363             } else {
364                 println!("weird extern crate without a crate id");
365             }
366         },
367         hir::ItemUse(ref path, ref kind) => println!("{:?}, {:?}", path, kind),
368         hir::ItemStatic(..) => println!("static item of type {:#?}", cx.tcx.type_of(did)),
369         hir::ItemConst(..) => println!("const item of type {:#?}", cx.tcx.type_of(did)),
370         hir::ItemFn(..) => {
371             let item_ty = cx.tcx.type_of(did);
372             println!("function of type {:#?}", item_ty);
373         },
374         hir::ItemMod(..) => println!("module"),
375         hir::ItemForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi),
376         hir::ItemGlobalAsm(ref asm) => println!("global asm: {:?}", asm),
377         hir::ItemTy(..) => {
378             println!("type alias for {:?}", cx.tcx.type_of(did));
379         },
380         hir::ItemEnum(..) => {
381             println!("enum definition of type {:?}", cx.tcx.type_of(did));
382         },
383         hir::ItemStruct(..) => {
384             println!("struct definition of type {:?}", cx.tcx.type_of(did));
385         },
386         hir::ItemUnion(..) => {
387             println!("union definition of type {:?}", cx.tcx.type_of(did));
388         },
389         hir::ItemTrait(..) => {
390             println!("trait decl");
391             if cx.tcx.trait_has_default_impl(did) {
392                 println!("trait has a default impl");
393             } else {
394                 println!("trait has no default impl");
395             }
396         },
397         hir::ItemDefaultImpl(_, ref _trait_ref) => {
398             println!("default impl");
399         },
400         hir::ItemImpl(_, _, _, _, Some(ref _trait_ref), _, _) => {
401             println!("trait impl");
402         },
403         hir::ItemImpl(_, _, _, _, None, _, _) => {
404             println!("impl");
405         },
406     }
407 }
408
409 fn print_pat(cx: &LateContext, pat: &hir::Pat, indent: usize) {
410     let ind = "  ".repeat(indent);
411     println!("{}+", ind);
412     match pat.node {
413         hir::PatKind::Wild => println!("{}Wild", ind),
414         hir::PatKind::Binding(ref mode, _, ref name, ref inner) => {
415             println!("{}Binding", ind);
416             println!("{}mode: {:?}", ind, mode);
417             println!("{}name: {}", ind, name.node);
418             if let Some(ref inner) = *inner {
419                 println!("{}inner:", ind);
420                 print_pat(cx, inner, indent + 1);
421             }
422         },
423         hir::PatKind::Struct(ref path, ref fields, ignore) => {
424             println!("{}Struct", ind);
425             println!("{}name: {}",
426                      ind,
427                      print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)));
428             println!("{}ignore leftover fields: {}", ind, ignore);
429             println!("{}fields:", ind);
430             for field in fields {
431                 println!("{}  field name: {}", ind, field.node.name);
432                 if field.node.is_shorthand {
433                     println!("{}  in shorthand notation", ind);
434                 }
435                 print_pat(cx, &field.node.pat, indent + 1);
436             }
437         },
438         hir::PatKind::TupleStruct(ref path, ref fields, opt_dots_position) => {
439             println!("{}TupleStruct", ind);
440             println!("{}path: {}",
441                      ind,
442                      print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)));
443             if let Some(dot_position) = opt_dots_position {
444                 println!("{}dot position: {}", ind, dot_position);
445             }
446             for field in fields {
447                 print_pat(cx, field, indent + 1);
448             }
449         },
450         hir::PatKind::Path(hir::QPath::Resolved(ref ty, ref path)) => {
451             println!("{}Resolved Path, {:?}", ind, ty);
452             println!("{}path: {:?}", ind, path);
453         },
454         hir::PatKind::Path(hir::QPath::TypeRelative(ref ty, ref seg)) => {
455             println!("{}Relative Path, {:?}", ind, ty);
456             println!("{}seg: {:?}", ind, seg);
457         },
458         hir::PatKind::Tuple(ref pats, opt_dots_position) => {
459             println!("{}Tuple", ind);
460             if let Some(dot_position) = opt_dots_position {
461                 println!("{}dot position: {}", ind, dot_position);
462             }
463             for field in pats {
464                 print_pat(cx, field, indent + 1);
465             }
466         },
467         hir::PatKind::Box(ref inner) => {
468             println!("{}Box", ind);
469             print_pat(cx, inner, indent + 1);
470         },
471         hir::PatKind::Ref(ref inner, ref muta) => {
472             println!("{}Ref", ind);
473             println!("{}mutability: {:?}", ind, muta);
474             print_pat(cx, inner, indent + 1);
475         },
476         hir::PatKind::Lit(ref e) => {
477             println!("{}Lit", ind);
478             print_expr(cx, e, indent + 1);
479         },
480         hir::PatKind::Range(ref l, ref r, ref range_end) => {
481             println!("{}Range", ind);
482             print_expr(cx, l, indent + 1);
483             print_expr(cx, r, indent + 1);
484             match *range_end {
485                 hir::RangeEnd::Included => println!("{} end included", ind),
486                 hir::RangeEnd::Excluded => println!("{} end excluded", ind),
487             }
488         },
489         hir::PatKind::Slice(ref first_pats, ref range, ref last_pats) => {
490             println!("{}Slice [a, b, ..i, y, z]", ind);
491             println!("[a, b]:");
492             for pat in first_pats {
493                 print_pat(cx, pat, indent + 1);
494             }
495             println!("i:");
496             if let Some(ref pat) = *range {
497                 print_pat(cx, pat, indent + 1);
498             }
499             println!("[y, z]:");
500             for pat in last_pats {
501                 print_pat(cx, pat, indent + 1);
502             }
503         },
504     }
505 }