@@ -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
+ /// 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
+
124
147
declare_lint_pass ! ( ClippyLintsInternal => [ CLIPPY_LINTS_INTERNAL ] ) ;
125
148
126
149
impl EarlyLintPass for ClippyLintsInternal {
@@ -163,12 +186,34 @@ pub struct LintWithoutLintPass {
163
186
registered_lints : FxHashSet < Name > ,
164
187
}
165
188
166
- impl_lint_pass ! ( LintWithoutLintPass => [ LINT_WITHOUT_LINT_PASS ] ) ;
189
+ impl_lint_pass ! ( LintWithoutLintPass => [ DEFAULT_LINT , LINT_WITHOUT_LINT_PASS ] ) ;
167
190
168
191
impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for LintWithoutLintPass {
169
192
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 {
171
194
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
+ }
172
217
self . declared_lints . insert ( item. ident . name , item. span ) ;
173
218
}
174
219
} else if is_expn_of ( item. span , "impl_lint_pass" ) . is_some ( )
0 commit comments