]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/use_self.rs
Merge pull request #1959 from DarkEld3r/1884-borrowed-box-any
[rust.git] / clippy_lints / src / use_self.rs
1 use rustc::lint::{LintArray, LateLintPass, LateContext, LintPass};
2 use rustc::hir::*;
3 use rustc::hir::intravisit::{Visitor, walk_path, NestedVisitorMap};
4 use utils::{span_lint_and_then, in_macro};
5 use syntax::ast::NodeId;
6 use syntax_pos::symbol::keywords::SelfType;
7
8 /// **What it does:** Checks for unnecessary repetition of structure name when a
9 /// replacement with `Self` is applicable.
10 ///
11 /// **Why is this bad?** Unnecessary repetition. Mixed use of `Self` and struct name
12 /// feels inconsistent.
13 ///
14 /// **Known problems:** None.
15 ///
16 /// **Example:**
17 /// ```rust
18 /// struct Foo {}
19 /// impl Foo {
20 ///     fn new() -> Foo {
21 ///         Foo {}
22 ///     }
23 /// }
24 /// ```
25 /// could be
26 /// ```
27 /// struct Foo {}
28 /// impl Foo {
29 ///     fn new() -> Self {
30 ///         Self {}
31 ///     }
32 /// }
33 /// ```
34 declare_lint! {
35     pub USE_SELF,
36     Allow,
37     "Unnecessary structure name repetition whereas `Self` is applicable"
38 }
39
40 #[derive(Copy, Clone, Default)]
41 pub struct UseSelf;
42
43 impl LintPass for UseSelf {
44     fn get_lints(&self) -> LintArray {
45         lint_array!(USE_SELF)
46     }
47 }
48
49 const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
50
51 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf {
52     fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
53         if in_macro(item.span) {
54             return;
55         }
56         if_let_chain!([
57             let ItemImpl(.., ref item_type, ref refs) = item.node,
58             let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node,
59             let PathParameters::AngleBracketedParameters(ref param_data)
60               = item_path.segments.last().expect(SEGMENTS_MSG).parameters,
61             param_data.lifetimes.len() == 0,
62         ], {
63             let visitor = &mut UseSelfVisitor {
64                 item_path: item_path,
65                 cx: cx,
66             };
67             for impl_item_ref in refs {
68                 visitor.visit_impl_item(cx.tcx.hir.impl_item(impl_item_ref.id));
69             }
70         })
71     }
72 }
73
74 struct UseSelfVisitor<'a, 'tcx: 'a> {
75     item_path: &'a Path,
76     cx: &'a LateContext<'a, 'tcx>,
77 }
78
79 impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> {
80     fn visit_path(&mut self, path: &'tcx Path, _id: NodeId) {
81         if self.item_path.def == path.def &&
82            path.segments
83             .last()
84             .expect(SEGMENTS_MSG)
85             .name != SelfType.name() {
86             span_lint_and_then(self.cx, USE_SELF, path.span, "unnecessary structure name repetition", |db| {
87                 db.span_suggestion(path.span, "use the applicable keyword", "Self".to_owned());
88             });
89         }
90
91         walk_path(self, path);
92     }
93
94     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
95         NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir)
96     }
97 }