]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/items_after_statements.rs
split clippy into lints, plugin and cargo-clippy
[rust.git] / clippy_lints / src / items_after_statements.rs
1 //! lint when items are used after statements
2
3 use rustc::lint::*;
4 use syntax::ast::*;
5 use utils::in_macro;
6
7 /// **What it does:** This lints checks for items declared after some statement in a block
8 ///
9 /// **Why is this bad?** Items live for the entire scope they are declared in. But statements are
10 /// processed in order. This might cause confusion as it's hard to figure out which item is meant
11 /// in a statement.
12 ///
13 /// **Known problems:** None
14 ///
15 /// **Example:**
16 /// ```rust
17 /// fn foo() {
18 ///     println!("cake");
19 /// }
20 /// fn main() {
21 ///     foo(); // prints "foo"
22 ///     fn foo() {
23 ///         println!("foo");
24 ///     }
25 ///     foo(); // prints "foo"
26 /// }
27 /// ```
28 declare_lint! {
29     pub ITEMS_AFTER_STATEMENTS,
30     Allow,
31     "finds blocks where an item comes after a statement"
32 }
33
34 pub struct ItemsAfterStatements;
35
36 impl LintPass for ItemsAfterStatements {
37     fn get_lints(&self) -> LintArray {
38         lint_array!(ITEMS_AFTER_STATEMENTS)
39     }
40 }
41
42 impl EarlyLintPass for ItemsAfterStatements {
43     fn check_block(&mut self, cx: &EarlyContext, item: &Block) {
44         if in_macro(cx, item.span) {
45             return;
46         }
47         let mut stmts = item.stmts.iter().map(|stmt| &stmt.node);
48         // skip initial items
49         while let Some(&StmtKind::Decl(ref decl, _)) = stmts.next() {
50             if let DeclKind::Local(_) = decl.node {
51                 break;
52             }
53         }
54         // lint on all further items
55         for stmt in stmts {
56             if let StmtKind::Decl(ref decl, _) = *stmt {
57                 if let DeclKind::Item(ref it) = decl.node {
58                     if in_macro(cx, it.span) {
59                         return;
60                     }
61                     cx.struct_span_lint(ITEMS_AFTER_STATEMENTS,
62                                         it.span,
63                                         "adding items after statements is confusing, since items exist from the \
64                                          start of the scope")
65                       .emit();
66                 }
67             }
68         }
69     }
70 }