]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/unused_label.rs
Make the lint docstrings more consistent.
[rust.git] / clippy_lints / src / unused_label.rs
1 use rustc::lint::*;
2 use rustc::hir;
3 use rustc::hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn};
4 use std::collections::HashMap;
5 use syntax::ast;
6 use syntax::codemap::Span;
7 use syntax::parse::token::InternedString;
8 use utils::{in_macro, span_lint};
9
10 /// **What it does:** Checks for unused labels.
11 ///
12 /// **Why is this bad?** Maybe the label should be used in which case there is
13 /// an error in the code or it should be removed.
14 ///
15 /// **Known problems:** Hopefully none.
16 ///
17 /// **Example:**
18 /// ```rust,ignore
19 /// fn unused_label() {
20 ///     'label: for i in 1..2 {
21 ///         if i > 4 { continue }
22 ///     }
23 /// ```
24 declare_lint! {
25     pub UNUSED_LABEL,
26     Warn,
27     "unused label"
28 }
29
30 pub struct UnusedLabel;
31
32 #[derive(Default)]
33 struct UnusedLabelVisitor {
34     labels: HashMap<InternedString, Span>,
35 }
36
37 impl UnusedLabelVisitor {
38     pub fn new() -> UnusedLabelVisitor {
39         ::std::default::Default::default()
40     }
41 }
42
43 impl LintPass for UnusedLabel {
44     fn get_lints(&self) -> LintArray {
45         lint_array!(UNUSED_LABEL)
46     }
47 }
48
49 impl LateLintPass for UnusedLabel {
50     fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, body: &hir::Block, span: Span, fn_id: ast::NodeId) {
51         if in_macro(cx, span) {
52             return;
53         }
54
55         let mut v = UnusedLabelVisitor::new();
56         walk_fn(&mut v, kind, decl, body, span, fn_id);
57
58         for (label, span) in v.labels {
59             span_lint(cx, UNUSED_LABEL, span, &format!("unused label `{}`", label));
60         }
61     }
62 }
63
64 impl<'v> Visitor<'v> for UnusedLabelVisitor {
65     fn visit_expr(&mut self, expr: &hir::Expr) {
66         match expr.node {
67             hir::ExprBreak(Some(label)) |
68             hir::ExprAgain(Some(label)) => {
69                 self.labels.remove(&label.node.as_str());
70             }
71             hir::ExprLoop(_, Some(label)) |
72             hir::ExprWhile(_, _, Some(label)) => {
73                 self.labels.insert(label.node.as_str(), expr.span);
74             }
75             _ => (),
76         }
77
78         walk_expr(self, expr);
79     }
80 }