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