@@ -13,10 +13,10 @@ use rustc_hir::*;
13
13
use rustc_lint:: { EarlyContext , EarlyLintPass , LateContext , LateLintPass } ;
14
14
use rustc_session:: declare_tool_lint;
15
15
use rustc_session:: { declare_lint_pass, impl_lint_pass} ;
16
- use rustc_span:: source_map:: Span ;
16
+ use rustc_span:: source_map:: { Span , Spanned } ;
17
17
use rustc_span:: symbol:: SymbolStr ;
18
18
use syntax:: ast;
19
- use syntax:: ast:: { Crate as AstCrate , ItemKind , Name } ;
19
+ use syntax:: ast:: { Crate as AstCrate , ItemKind , LitKind , Name } ;
20
20
use syntax:: visit:: FnKind ;
21
21
22
22
declare_clippy_lint ! {
@@ -121,6 +121,29 @@ declare_clippy_lint! {
121
121
"this message should not appear anywhere as we ICE before and don't emit the lint"
122
122
}
123
123
124
+ declare_clippy_lint ! {
125
+ /// **What it does:** Checks for cases of an auto-generated lint without an updated description,
126
+ /// ie `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
+
124
147
declare_lint_pass ! ( ClippyLintsInternal => [ CLIPPY_LINTS_INTERNAL ] ) ;
125
148
126
149
impl EarlyLintPass for ClippyLintsInternal {
@@ -165,10 +188,34 @@ pub struct LintWithoutLintPass {
165
188
166
189
impl_lint_pass ! ( LintWithoutLintPass => [ LINT_WITHOUT_LINT_PASS ] ) ;
167
190
191
+ declare_lint_pass ! ( DefaultLint => [ DEFAULT_LINT ] ) ;
192
+
168
193
impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for LintWithoutLintPass {
169
194
fn check_item ( & mut self , cx : & LateContext < ' a , ' tcx > , item : & ' tcx Item < ' _ > ) {
170
- if let hir:: ItemKind :: Static ( ref ty, Mutability :: Not , _ ) = item. kind {
195
+ if let hir:: ItemKind :: Static ( ref ty, Mutability :: Not , body_id ) = item. kind {
171
196
if is_lint_ref_type ( cx, ty) {
197
+ let expr = & cx. tcx . hir ( ) . body ( body_id) . value ;
198
+ if_chain ! {
199
+ if let ExprKind :: AddrOf ( _, _, ref inner_exp) = expr. kind;
200
+ if let ExprKind :: Struct ( _, ref fields, _) = inner_exp. kind;
201
+ let field = fields. iter( )
202
+ . find( |f| f. ident. as_str( ) == "desc" )
203
+ . expect( "lints must have a description field" ) ;
204
+ if let ExprKind :: Lit ( Spanned {
205
+ node: LitKind :: Str ( ref sym, _) ,
206
+ ..
207
+ } ) = field. expr. kind;
208
+ if sym. as_str( ) == "default lint description" ;
209
+
210
+ then {
211
+ span_lint(
212
+ cx,
213
+ DEFAULT_LINT ,
214
+ item. span,
215
+ & format!( "the lint `{}` has the default lint description" , item. ident. name) ,
216
+ ) ;
217
+ }
218
+ }
172
219
self . declared_lints . insert ( item. ident . name , item. span ) ;
173
220
}
174
221
} else if is_expn_of ( item. span , "impl_lint_pass" ) . is_some ( )
0 commit comments