]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/disallowed_type.rs
Rollup merge of #88713 - falk-hueffner:int-log10-documentation-fixes, r=scottmcm
[rust.git] / src / tools / clippy / clippy_lints / src / disallowed_type.rs
1 use clippy_utils::diagnostics::span_lint;
2
3 use rustc_data_structures::fx::FxHashSet;
4 use rustc_hir::{
5     def::Res, def_id::DefId, Item, ItemKind, PolyTraitRef, PrimTy, TraitBoundModifier, Ty, TyKind, UseKind,
6 };
7 use rustc_lint::{LateContext, LateLintPass};
8 use rustc_session::{declare_tool_lint, impl_lint_pass};
9 use rustc_span::{Span, Symbol};
10
11 declare_clippy_lint! {
12     /// ### What it does
13     /// Denies the configured types in clippy.toml.
14     ///
15     /// ### Why is this bad?
16     /// Some types are undesirable in certain contexts.
17     ///
18     /// ### Example:
19     /// An example clippy.toml configuration:
20     /// ```toml
21     /// # clippy.toml
22     /// disallowed-types = ["std::collections::BTreeMap"]
23     /// ```
24     ///
25     /// ```rust,ignore
26     /// use std::collections::BTreeMap;
27     /// // or its use
28     /// let x = std::collections::BTreeMap::new();
29     /// ```
30     /// Use instead:
31     /// ```rust,ignore
32     /// // A similar type that is allowed by the config
33     /// use std::collections::HashMap;
34     /// ```
35     pub DISALLOWED_TYPE,
36     nursery,
37     "use of a disallowed type"
38 }
39 #[derive(Clone, Debug)]
40 pub struct DisallowedType {
41     disallowed: FxHashSet<Vec<Symbol>>,
42     def_ids: FxHashSet<DefId>,
43     prim_tys: FxHashSet<PrimTy>,
44 }
45
46 impl DisallowedType {
47     pub fn new(disallowed: &FxHashSet<String>) -> Self {
48         Self {
49             disallowed: disallowed
50                 .iter()
51                 .map(|s| s.split("::").map(Symbol::intern).collect::<Vec<_>>())
52                 .collect(),
53             def_ids: FxHashSet::default(),
54             prim_tys: FxHashSet::default(),
55         }
56     }
57
58     fn check_res_emit(&self, cx: &LateContext<'_>, res: &Res, span: Span) {
59         match res {
60             Res::Def(_, did) => {
61                 if self.def_ids.contains(did) {
62                     emit(cx, &cx.tcx.def_path_str(*did), span);
63                 }
64             },
65             Res::PrimTy(prim) => {
66                 if self.prim_tys.contains(prim) {
67                     emit(cx, prim.name_str(), span);
68                 }
69             },
70             _ => {},
71         }
72     }
73 }
74
75 impl_lint_pass!(DisallowedType => [DISALLOWED_TYPE]);
76
77 impl<'tcx> LateLintPass<'tcx> for DisallowedType {
78     fn check_crate(&mut self, cx: &LateContext<'_>) {
79         for path in &self.disallowed {
80             let segs = path.iter().map(ToString::to_string).collect::<Vec<_>>();
81             match clippy_utils::path_to_res(cx, &segs.iter().map(String::as_str).collect::<Vec<_>>()) {
82                 Res::Def(_, id) => {
83                     self.def_ids.insert(id);
84                 },
85                 Res::PrimTy(ty) => {
86                     self.prim_tys.insert(ty);
87                 },
88                 _ => {},
89             }
90         }
91     }
92
93     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
94         if let ItemKind::Use(path, UseKind::Single) = &item.kind {
95             self.check_res_emit(cx, &path.res, item.span);
96         }
97     }
98
99     fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
100         if let TyKind::Path(path) = &ty.kind {
101             self.check_res_emit(cx, &cx.qpath_res(path, ty.hir_id), ty.span);
102         }
103     }
104
105     fn check_poly_trait_ref(&mut self, cx: &LateContext<'tcx>, poly: &'tcx PolyTraitRef<'tcx>, _: TraitBoundModifier) {
106         self.check_res_emit(cx, &poly.trait_ref.path.res, poly.trait_ref.path.span);
107     }
108 }
109
110 fn emit(cx: &LateContext<'_>, name: &str, span: Span) {
111     span_lint(
112         cx,
113         DISALLOWED_TYPE,
114         span,
115         &format!("`{}` is not allowed according to config", name),
116     );
117 }