Skip to content

Commit 32337a9

Browse files
committed
Add lint for default lint description
- Lint for any new lints that have the default lint description from the automation
1 parent 237a01d commit 32337a9

File tree

4 files changed

+99
-4
lines changed

4 files changed

+99
-4
lines changed

clippy_lints/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10901090
LintId::of(&utils::internal_lints::LINT_WITHOUT_LINT_PASS),
10911091
LintId::of(&utils::internal_lints::OUTER_EXPN_EXPN_DATA),
10921092
LintId::of(&utils::internal_lints::PRODUCE_ICE),
1093+
LintId::of(&utils::internal_lints::DEFAULT_LINT),
10931094
]);
10941095

10951096
store.register_group(true, "clippy::all", Some("clippy"), vec![

clippy_lints/src/utils/internal_lints.rs

+49-4
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ use rustc_hir::*;
1313
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
1414
use rustc_session::declare_tool_lint;
1515
use rustc_session::{declare_lint_pass, impl_lint_pass};
16-
use rustc_span::source_map::Span;
16+
use rustc_span::source_map::{Span, Spanned};
1717
use rustc_span::symbol::SymbolStr;
1818
use syntax::ast;
19-
use syntax::ast::{Crate as AstCrate, ItemKind, Name};
19+
use syntax::ast::{Crate as AstCrate, ItemKind, LitKind, Name};
2020
use syntax::visit::FnKind;
2121

2222
declare_clippy_lint! {
@@ -121,6 +121,29 @@ declare_clippy_lint! {
121121
"this message should not appear anywhere as we ICE before and don't emit the lint"
122122
}
123123

124+
declare_clippy_lint! {
125+
/// **What it does:** Checks for cases of an auto-generated lint without an updated description,
126+
/// i.e. `default lint description`.
127+
///
128+
/// **Why is this bad?** Indicates that the lint is not finished.
129+
///
130+
/// **Known problems:** None
131+
///
132+
/// **Example:**
133+
/// Bad:
134+
/// ```rust,ignore
135+
/// declare_lint! { pub COOL_LINT, nursery, "default lint description" }
136+
/// ```
137+
///
138+
/// Good:
139+
/// ```rust,ignore
140+
/// declare_lint! { pub COOL_LINT, nursery, "a great new lint" }
141+
/// ```
142+
pub DEFAULT_LINT,
143+
internal,
144+
"found 'default lint description' in a lint declaration"
145+
}
146+
124147
declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
125148

126149
impl EarlyLintPass for ClippyLintsInternal {
@@ -163,12 +186,34 @@ pub struct LintWithoutLintPass {
163186
registered_lints: FxHashSet<Name>,
164187
}
165188

166-
impl_lint_pass!(LintWithoutLintPass => [LINT_WITHOUT_LINT_PASS]);
189+
impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS]);
167190

168191
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass {
169192
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) {
170-
if let hir::ItemKind::Static(ref ty, Mutability::Not, _) = item.kind {
193+
if let hir::ItemKind::Static(ref ty, Mutability::Not, body_id) = item.kind {
171194
if is_lint_ref_type(cx, ty) {
195+
let expr = &cx.tcx.hir().body(body_id).value;
196+
if_chain! {
197+
if let ExprKind::AddrOf(_, _, ref inner_exp) = expr.kind;
198+
if let ExprKind::Struct(_, ref fields, _) = inner_exp.kind;
199+
let field = fields.iter()
200+
.find(|f| f.ident.as_str() == "desc")
201+
.expect("lints must have a description field");
202+
if let ExprKind::Lit(Spanned {
203+
node: LitKind::Str(ref sym, _),
204+
..
205+
}) = field.expr.kind;
206+
if sym.as_str() == "default lint description";
207+
208+
then {
209+
span_lint(
210+
cx,
211+
DEFAULT_LINT,
212+
item.span,
213+
&format!("the lint `{}` has the default lint description", item.ident.name),
214+
);
215+
}
216+
}
172217
self.declared_lints.insert(item.ident.name, item.span);
173218
}
174219
} else if is_expn_of(item.span, "impl_lint_pass").is_some()

tests/ui/default_lint.rs

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![deny(clippy::internal)]
2+
#![feature(rustc_private)]
3+
4+
#[macro_use]
5+
extern crate rustc;
6+
#[macro_use]
7+
extern crate rustc_session;
8+
extern crate rustc_lint;
9+
use rustc_lint::{LintArray, LintPass};
10+
11+
declare_tool_lint! {
12+
pub clippy::TEST_LINT,
13+
Warn,
14+
"",
15+
report_in_external_macro: true
16+
}
17+
18+
declare_tool_lint! {
19+
pub clippy::TEST_LINT_DEFAULT,
20+
Warn,
21+
"default lint description",
22+
report_in_external_macro: true
23+
}
24+
25+
declare_lint_pass!(Pass => [TEST_LINT]);
26+
declare_lint_pass!(Pass2 => [TEST_LINT_DEFAULT]);
27+
28+
fn main() {}

tests/ui/default_lint.stderr

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error: the lint `TEST_LINT_DEFAULT` has the default lint description
2+
--> $DIR/default_lint.rs:18:1
3+
|
4+
LL | / declare_tool_lint! {
5+
LL | | pub clippy::TEST_LINT_DEFAULT,
6+
LL | | Warn,
7+
LL | | "default lint description",
8+
LL | | report_in_external_macro: true
9+
LL | | }
10+
| |_^
11+
|
12+
note: lint level defined here
13+
--> $DIR/default_lint.rs:1:9
14+
|
15+
LL | #![deny(clippy::internal)]
16+
| ^^^^^^^^^^^^^^^^
17+
= note: `#[deny(clippy::default_lint)]` implied by `#[deny(clippy::internal)]`
18+
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
19+
20+
error: aborting due to previous error
21+

0 commit comments

Comments
 (0)