|
1 | 1 | use crate::internal_paths;
|
2 | 2 | use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
3 |
| -use clippy_utils::is_lint_allowed; |
4 |
| -use clippy_utils::macros::root_macro_call_first_node; |
5 | 3 | use rustc_ast::ast::LitKind;
|
6 |
| -use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; |
7 | 4 | use rustc_hir as hir;
|
8 | 5 | use rustc_hir::def::{DefKind, Res};
|
9 |
| -use rustc_hir::hir_id::CRATE_HIR_ID; |
10 |
| -use rustc_hir::intravisit::Visitor; |
11 |
| -use rustc_hir::{ExprKind, HirId, Item, MutTy, Mutability, Path, TyKind}; |
| 6 | +use rustc_hir::{ExprKind, Item, MutTy, Mutability, TyKind}; |
12 | 7 | use rustc_lint::{LateContext, LateLintPass};
|
13 |
| -use rustc_middle::hir::nested_filter; |
14 |
| -use rustc_session::{declare_tool_lint, impl_lint_pass}; |
| 8 | +use rustc_session::{declare_lint_pass, declare_tool_lint}; |
15 | 9 | use rustc_span::source_map::Spanned;
|
| 10 | +use rustc_span::sym; |
16 | 11 | use rustc_span::symbol::Symbol;
|
17 |
| -use rustc_span::{Span, sym}; |
18 |
| - |
19 |
| -declare_tool_lint! { |
20 |
| - /// ### What it does |
21 |
| - /// Ensures every lint is associated to a `LintPass`. |
22 |
| - /// |
23 |
| - /// ### Why is this bad? |
24 |
| - /// The compiler only knows lints via a `LintPass`. Without |
25 |
| - /// putting a lint to a `LintPass::lint_vec()`'s return, the compiler will not |
26 |
| - /// know the name of the lint. |
27 |
| - /// |
28 |
| - /// ### Known problems |
29 |
| - /// Only checks for lints associated using the `declare_lint_pass!` and |
30 |
| - /// `impl_lint_pass!` macros. |
31 |
| - /// |
32 |
| - /// ### Example |
33 |
| - /// ```rust,ignore |
34 |
| - /// declare_lint! { pub LINT_1, ... } |
35 |
| - /// declare_lint! { pub LINT_2, ... } |
36 |
| - /// declare_lint! { pub FORGOTTEN_LINT, ... } |
37 |
| - /// // ... |
38 |
| - /// declare_lint_pass!(Pass => [LINT_1, LINT_2]); |
39 |
| - /// // missing FORGOTTEN_LINT |
40 |
| - /// ``` |
41 |
| - pub clippy::LINT_WITHOUT_LINT_PASS, |
42 |
| - Warn, |
43 |
| - "declaring a lint without associating it in a LintPass", |
44 |
| - report_in_external_macro: true |
45 |
| - |
46 |
| -} |
47 | 12 |
|
48 | 13 | declare_tool_lint! {
|
49 | 14 | /// ### What it does
|
@@ -90,109 +55,47 @@ declare_tool_lint! {
|
90 | 55 | report_in_external_macro: true
|
91 | 56 | }
|
92 | 57 |
|
93 |
| -#[derive(Clone, Debug, Default)] |
94 |
| -pub struct LintWithoutLintPass { |
95 |
| - declared_lints: FxIndexMap<Symbol, Span>, |
96 |
| - registered_lints: FxIndexSet<Symbol>, |
97 |
| -} |
98 |
| - |
99 |
| -impl_lint_pass!(LintWithoutLintPass => [ |
| 58 | +declare_lint_pass!(LintWithoutLintPass => [ |
100 | 59 | DEFAULT_LINT,
|
101 |
| - LINT_WITHOUT_LINT_PASS, |
102 | 60 | INVALID_CLIPPY_VERSION_ATTRIBUTE,
|
103 | 61 | MISSING_CLIPPY_VERSION_ATTRIBUTE,
|
104 | 62 | ]);
|
105 | 63 |
|
106 | 64 | impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
|
107 | 65 | fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
108 |
| - if let hir::ItemKind::Static(Mutability::Not, ident, ty, body_id) = item.kind { |
109 |
| - if is_lint_ref_type(cx, ty) { |
110 |
| - check_invalid_clippy_version_attribute(cx, item); |
| 66 | + if let hir::ItemKind::Static(Mutability::Not, ident, ty, body_id) = item.kind |
| 67 | + && is_lint_ref_type(cx, ty) |
| 68 | + { |
| 69 | + check_invalid_clippy_version_attribute(cx, item); |
111 | 70 |
|
112 |
| - let expr = &cx.tcx.hir_body(body_id).value; |
113 |
| - let fields = if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind |
114 |
| - && let ExprKind::Struct(_, struct_fields, _) = inner_exp.kind |
115 |
| - { |
116 |
| - struct_fields |
117 |
| - } else { |
118 |
| - return; |
119 |
| - }; |
| 71 | + let expr = &cx.tcx.hir_body(body_id).value; |
| 72 | + let fields = if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind |
| 73 | + && let ExprKind::Struct(_, struct_fields, _) = inner_exp.kind |
| 74 | + { |
| 75 | + struct_fields |
| 76 | + } else { |
| 77 | + return; |
| 78 | + }; |
120 | 79 |
|
121 |
| - let field = fields |
122 |
| - .iter() |
123 |
| - .find(|f| f.ident.as_str() == "desc") |
124 |
| - .expect("lints must have a description field"); |
| 80 | + let field = fields |
| 81 | + .iter() |
| 82 | + .find(|f| f.ident.as_str() == "desc") |
| 83 | + .expect("lints must have a description field"); |
125 | 84 |
|
126 |
| - if let ExprKind::Lit(Spanned { |
127 |
| - node: LitKind::Str(sym, _), |
128 |
| - .. |
129 |
| - }) = field.expr.kind |
130 |
| - { |
131 |
| - let sym_str = sym.as_str(); |
132 |
| - if sym_str == "default lint description" { |
133 |
| - span_lint( |
134 |
| - cx, |
135 |
| - DEFAULT_LINT, |
136 |
| - item.span, |
137 |
| - format!("the lint `{}` has the default lint description", ident.name), |
138 |
| - ); |
139 |
| - } |
140 |
| - self.declared_lints.insert(ident.name, item.span); |
141 |
| - } |
142 |
| - } |
143 |
| - } else if let Some(macro_call) = root_macro_call_first_node(cx, item) { |
144 |
| - if !matches!( |
145 |
| - cx.tcx.item_name(macro_call.def_id).as_str(), |
146 |
| - "impl_lint_pass" | "declare_lint_pass" |
147 |
| - ) { |
148 |
| - return; |
149 |
| - } |
150 |
| - if let hir::ItemKind::Impl(hir::Impl { |
151 |
| - of_trait: None, |
152 |
| - items: impl_item_refs, |
| 85 | + if let ExprKind::Lit(Spanned { |
| 86 | + node: LitKind::Str(sym, _), |
153 | 87 | ..
|
154 |
| - }) = item.kind |
| 88 | + }) = field.expr.kind |
155 | 89 | {
|
156 |
| - let mut collector = LintCollector { |
157 |
| - output: &mut self.registered_lints, |
158 |
| - cx, |
159 |
| - }; |
160 |
| - let body = cx.tcx.hir_body_owned_by( |
161 |
| - impl_item_refs |
162 |
| - .iter() |
163 |
| - .find(|iiref| iiref.ident.as_str() == "lint_vec") |
164 |
| - .expect("LintPass needs to implement lint_vec") |
165 |
| - .id |
166 |
| - .owner_id |
167 |
| - .def_id, |
168 |
| - ); |
169 |
| - collector.visit_expr(body.value); |
170 |
| - } |
171 |
| - } |
172 |
| - } |
173 |
| - |
174 |
| - fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { |
175 |
| - if is_lint_allowed(cx, LINT_WITHOUT_LINT_PASS, CRATE_HIR_ID) { |
176 |
| - return; |
177 |
| - } |
178 |
| - |
179 |
| - for (lint_name, &lint_span) in &self.declared_lints { |
180 |
| - // When using the `declare_tool_lint!` macro, the original `lint_span`'s |
181 |
| - // file points to "<rustc macros>". |
182 |
| - // `compiletest-rs` thinks that's an error in a different file and |
183 |
| - // just ignores it. This causes the test in compile-fail/lint_pass |
184 |
| - // not able to capture the error. |
185 |
| - // Therefore, we need to climb the macro expansion tree and find the |
186 |
| - // actual span that invoked `declare_tool_lint!`: |
187 |
| - let lint_span = lint_span.ctxt().outer_expn_data().call_site; |
188 |
| - |
189 |
| - if !self.registered_lints.contains(lint_name) { |
190 |
| - span_lint( |
191 |
| - cx, |
192 |
| - LINT_WITHOUT_LINT_PASS, |
193 |
| - lint_span, |
194 |
| - format!("the lint `{lint_name}` is not added to any `LintPass`"), |
195 |
| - ); |
| 90 | + let sym_str = sym.as_str(); |
| 91 | + if sym_str == "default lint description" { |
| 92 | + span_lint( |
| 93 | + cx, |
| 94 | + DEFAULT_LINT, |
| 95 | + item.span, |
| 96 | + format!("the lint `{}` has the default lint description", ident.name), |
| 97 | + ); |
| 98 | + } |
196 | 99 | }
|
197 | 100 | }
|
198 | 101 | }
|
@@ -261,22 +164,3 @@ pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<
|
261 | 164 | }
|
262 | 165 | })
|
263 | 166 | }
|
264 |
| - |
265 |
| -struct LintCollector<'a, 'tcx> { |
266 |
| - output: &'a mut FxIndexSet<Symbol>, |
267 |
| - cx: &'a LateContext<'tcx>, |
268 |
| -} |
269 |
| - |
270 |
| -impl<'tcx> Visitor<'tcx> for LintCollector<'_, 'tcx> { |
271 |
| - type NestedFilter = nested_filter::All; |
272 |
| - |
273 |
| - fn visit_path(&mut self, path: &Path<'_>, _: HirId) { |
274 |
| - if path.segments.len() == 1 { |
275 |
| - self.output.insert(path.segments[0].ident.name); |
276 |
| - } |
277 |
| - } |
278 |
| - |
279 |
| - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { |
280 |
| - self.cx.tcx |
281 |
| - } |
282 |
| -} |
0 commit comments