]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/unsafe_removed_from_name.rs
Merge pull request #3465 from flip1995/rustfmt
[rust.git] / clippy_lints / src / unsafe_removed_from_name.rs
1 // Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9
10 use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
11 use crate::rustc::{declare_tool_lint, lint_array};
12 use crate::syntax::ast::*;
13 use crate::syntax::source_map::Span;
14 use crate::syntax::symbol::LocalInternedString;
15 use crate::utils::span_lint;
16
17 /// **What it does:** Checks for imports that remove "unsafe" from an item's
18 /// name.
19 ///
20 /// **Why is this bad?** Renaming makes it less clear which traits and
21 /// structures are unsafe.
22 ///
23 /// **Known problems:** None.
24 ///
25 /// **Example:**
26 /// ```rust,ignore
27 /// use std::cell::{UnsafeCell as TotallySafeCell};
28 ///
29 /// extern crate crossbeam;
30 /// use crossbeam::{spawn_unsafe as spawn};
31 /// ```
32 declare_clippy_lint! {
33     pub UNSAFE_REMOVED_FROM_NAME,
34     style,
35     "`unsafe` removed from API names on import"
36 }
37
38 pub struct UnsafeNameRemoval;
39
40 impl LintPass for UnsafeNameRemoval {
41     fn get_lints(&self) -> LintArray {
42         lint_array!(UNSAFE_REMOVED_FROM_NAME)
43     }
44 }
45
46 impl EarlyLintPass for UnsafeNameRemoval {
47     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
48         if let ItemKind::Use(ref use_tree) = item.node {
49             check_use_tree(use_tree, cx, item.span);
50         }
51     }
52 }
53
54 fn check_use_tree(use_tree: &UseTree, cx: &EarlyContext<'_>, span: Span) {
55     match use_tree.kind {
56         UseTreeKind::Simple(Some(new_name), ..) => {
57             let old_name = use_tree
58                 .prefix
59                 .segments
60                 .last()
61                 .expect("use paths cannot be empty")
62                 .ident;
63             unsafe_to_safe_check(old_name, new_name, cx, span);
64         },
65         UseTreeKind::Simple(None, ..) | UseTreeKind::Glob => {},
66         UseTreeKind::Nested(ref nested_use_tree) => {
67             for &(ref use_tree, _) in nested_use_tree {
68                 check_use_tree(use_tree, cx, span);
69             }
70         },
71     }
72 }
73
74 fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext<'_>, span: Span) {
75     let old_str = old_name.name.as_str();
76     let new_str = new_name.name.as_str();
77     if contains_unsafe(&old_str) && !contains_unsafe(&new_str) {
78         span_lint(
79             cx,
80             UNSAFE_REMOVED_FROM_NAME,
81             span,
82             &format!(
83                 "removed \"unsafe\" from the name of `{}` in use as `{}`",
84                 old_str, new_str
85             ),
86         );
87     }
88 }
89
90 fn contains_unsafe(name: &LocalInternedString) -> bool {
91     name.contains("Unsafe") || name.contains("unsafe")
92 }