]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
1 | //! lint on `use`ing all variants of an enum |
2 | ||
3 | use rustc::hir::*; | |
abe05a73 | 4 | use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; |
ea8adc8c XL |
5 | use syntax::ast::NodeId; |
6 | use syntax::codemap::Span; | |
7 | use utils::span_lint; | |
8 | ||
9 | /// **What it does:** Checks for `use Enum::*`. | |
10 | /// | |
11 | /// **Why is this bad?** It is usually better style to use the prefixed name of | |
12 | /// an enumeration variant, rather than importing variants. | |
13 | /// | |
14 | /// **Known problems:** Old-style enumerations that prefix the variants are | |
15 | /// still around. | |
16 | /// | |
17 | /// **Example:** | |
18 | /// ```rust | |
19 | /// use std::cmp::Ordering::*; | |
20 | /// ``` | |
21 | declare_lint! { | |
22 | pub ENUM_GLOB_USE, | |
23 | Allow, | |
24 | "use items that import all variants of an enum" | |
25 | } | |
26 | ||
27 | pub struct EnumGlobUse; | |
28 | ||
29 | impl LintPass for EnumGlobUse { | |
30 | fn get_lints(&self) -> LintArray { | |
31 | lint_array!(ENUM_GLOB_USE) | |
32 | } | |
33 | } | |
34 | ||
35 | impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse { | |
36 | fn check_mod(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod, _: Span, _: NodeId) { | |
37 | // only check top level `use` statements | |
38 | for item in &m.item_ids { | |
39 | self.lint_item(cx, cx.tcx.hir.expect_item(item.id)); | |
40 | } | |
41 | } | |
42 | } | |
43 | ||
44 | impl EnumGlobUse { | |
45 | fn lint_item(&self, cx: &LateContext, item: &Item) { | |
46 | if item.vis == Visibility::Public { | |
47 | return; // re-exports are fine | |
48 | } | |
49 | if let ItemUse(ref path, UseKind::Glob) = item.node { | |
50 | // FIXME: ask jseyfried why the qpath.def for `use std::cmp::Ordering::*;` | |
51 | // extracted through `ItemUse(ref qpath, UseKind::Glob)` is a `Mod` and not an | |
52 | // `Enum` | |
53 | // if let Def::Enum(_) = path.def { | |
54 | if path.segments | |
55 | .last() | |
56 | .and_then(|seg| seg.name.as_str().chars().next()) | |
57 | .map_or(false, char::is_uppercase) | |
58 | { | |
59 | span_lint(cx, ENUM_GLOB_USE, item.span, "don't use glob imports for enum variants"); | |
60 | } | |
61 | } | |
62 | } | |
63 | } |