]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
1 | use rustc::lint::*; |
2 | use syntax::ast::*; | |
3 | use syntax::codemap::Span; | |
83c7162d | 4 | use syntax::symbol::LocalInternedString; |
ea8adc8c XL |
5 | use utils::span_lint; |
6 | ||
7 | /// **What it does:** Checks for imports that remove "unsafe" from an item's | |
8 | /// name. | |
9 | /// | |
10 | /// **Why is this bad?** Renaming makes it less clear which traits and | |
11 | /// structures are unsafe. | |
12 | /// | |
13 | /// **Known problems:** None. | |
14 | /// | |
15 | /// **Example:** | |
16 | /// ```rust,ignore | |
17 | /// use std::cell::{UnsafeCell as TotallySafeCell}; | |
18 | /// | |
19 | /// extern crate crossbeam; | |
20 | /// use crossbeam::{spawn_unsafe as spawn}; | |
21 | /// ``` | |
0531ce1d | 22 | declare_clippy_lint! { |
ea8adc8c | 23 | pub UNSAFE_REMOVED_FROM_NAME, |
0531ce1d | 24 | style, |
ea8adc8c XL |
25 | "`unsafe` removed from API names on import" |
26 | } | |
27 | ||
28 | pub struct UnsafeNameRemoval; | |
29 | ||
30 | impl LintPass for UnsafeNameRemoval { | |
31 | fn get_lints(&self) -> LintArray { | |
32 | lint_array!(UNSAFE_REMOVED_FROM_NAME) | |
33 | } | |
34 | } | |
35 | ||
36 | impl EarlyLintPass for UnsafeNameRemoval { | |
37 | fn check_item(&mut self, cx: &EarlyContext, item: &Item) { | |
2c00a5a8 XL |
38 | if let ItemKind::Use(ref use_tree) = item.node { |
39 | check_use_tree(use_tree, cx, &item.span); | |
40 | } | |
41 | } | |
42 | } | |
43 | ||
44 | fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext, span: &Span) { | |
45 | match use_tree.kind { | |
0531ce1d | 46 | UseTreeKind::Simple(Some(new_name)) => { |
2c00a5a8 XL |
47 | let old_name = use_tree |
48 | .prefix | |
49 | .segments | |
50 | .last() | |
51 | .expect("use paths cannot be empty") | |
83c7162d | 52 | .ident; |
2c00a5a8 XL |
53 | unsafe_to_safe_check(old_name, new_name, cx, span); |
54 | } | |
0531ce1d | 55 | UseTreeKind::Simple(None) | |
2c00a5a8 XL |
56 | UseTreeKind::Glob => {}, |
57 | UseTreeKind::Nested(ref nested_use_tree) => { | |
58 | for &(ref use_tree, _) in nested_use_tree { | |
59 | check_use_tree(use_tree, cx, span); | |
ea8adc8c XL |
60 | } |
61 | } | |
62 | } | |
63 | } | |
64 | ||
65 | fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext, span: &Span) { | |
66 | let old_str = old_name.name.as_str(); | |
67 | let new_str = new_name.name.as_str(); | |
68 | if contains_unsafe(&old_str) && !contains_unsafe(&new_str) { | |
69 | span_lint( | |
70 | cx, | |
71 | UNSAFE_REMOVED_FROM_NAME, | |
72 | *span, | |
73 | &format!("removed \"unsafe\" from the name of `{}` in use as `{}`", old_str, new_str), | |
74 | ); | |
75 | } | |
76 | } | |
77 | ||
83c7162d | 78 | fn contains_unsafe(name: &LocalInternedString) -> bool { |
ea8adc8c XL |
79 | name.contains("Unsafe") || name.contains("unsafe") |
80 | } |