@@ -14,7 +14,7 @@ use rustc::ty::{self, TyCtxt};
14
14
use rustc:: { declare_tool_lint, lint_array} ;
15
15
use rustc_errors:: Applicability ;
16
16
use semver:: Version ;
17
- use syntax:: ast:: { AttrStyle , Attribute , Lit , LitKind , MetaItemKind , NestedMetaItem , NestedMetaItemKind } ;
17
+ use syntax:: ast:: { AttrStyle , Attribute , Lit , LitKind , MetaItemKind , NestedMetaItem } ;
18
18
use syntax:: source_map:: Span ;
19
19
20
20
declare_clippy_lint ! {
@@ -208,22 +208,24 @@ impl LintPass for AttrPass {
208
208
impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for AttrPass {
209
209
fn check_attribute ( & mut self , cx : & LateContext < ' a , ' tcx > , attr : & ' tcx Attribute ) {
210
210
if let Some ( items) = & attr. meta_item_list ( ) {
211
- match & * attr. name ( ) . as_str ( ) {
212
- "allow" | "warn" | "deny" | "forbid" => {
213
- check_clippy_lint_names ( cx, items) ;
214
- } ,
215
- _ => { } ,
216
- }
217
- if items. is_empty ( ) || attr. name ( ) != "deprecated" {
218
- return ;
219
- }
220
- for item in items {
221
- if_chain ! {
222
- if let NestedMetaItemKind :: MetaItem ( mi) = & item. node;
223
- if let MetaItemKind :: NameValue ( lit) = & mi. node;
224
- if mi. name( ) == "since" ;
225
- then {
226
- check_semver( cx, item. span, lit) ;
211
+ if let Some ( ident) = attr. ident_str ( ) {
212
+ match ident {
213
+ "allow" | "warn" | "deny" | "forbid" => {
214
+ check_clippy_lint_names ( cx, items) ;
215
+ } ,
216
+ _ => { } ,
217
+ }
218
+ if items. is_empty ( ) || !attr. check_name ( "deprecated" ) {
219
+ return ;
220
+ }
221
+ for item in items {
222
+ if_chain ! {
223
+ if let NestedMetaItem :: MetaItem ( mi) = & item;
224
+ if let MetaItemKind :: NameValue ( lit) = & mi. node;
225
+ if mi. check_name( "since" ) ;
226
+ then {
227
+ check_semver( cx, item. span( ) , lit) ;
228
+ }
227
229
}
228
230
}
229
231
}
@@ -236,55 +238,57 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
236
238
}
237
239
match item. node {
238
240
ItemKind :: ExternCrate ( ..) | ItemKind :: Use ( ..) => {
239
- let skip_unused_imports = item. attrs . iter ( ) . any ( |attr| attr. name ( ) == "macro_use" ) ;
241
+ let skip_unused_imports = item. attrs . iter ( ) . any ( |attr| attr. check_name ( "macro_use" ) ) ;
240
242
241
243
for attr in & item. attrs {
242
244
if let Some ( lint_list) = & attr. meta_item_list ( ) {
243
- match & * attr. name ( ) . as_str ( ) {
244
- "allow" | "warn" | "deny" | "forbid" => {
245
- // whitelist `unused_imports` and `deprecated` for `use` items
246
- // and `unused_imports` for `extern crate` items with `macro_use`
247
- for lint in lint_list {
248
- match item. node {
249
- ItemKind :: Use ( ..) => {
250
- if is_word ( lint, "unused_imports" ) || is_word ( lint, "deprecated" ) {
251
- return ;
252
- }
253
- } ,
254
- ItemKind :: ExternCrate ( ..) => {
255
- if is_word ( lint, "unused_imports" ) && skip_unused_imports {
256
- return ;
257
- }
258
- if is_word ( lint, "unused_extern_crates" ) {
259
- return ;
260
- }
261
- } ,
262
- _ => { } ,
263
- }
264
- }
265
- let line_span = last_line_of_span ( cx, attr. span ) ;
266
-
267
- if let Some ( mut sugg) = snippet_opt ( cx, line_span) {
268
- if sugg. contains ( "#[" ) {
269
- span_lint_and_then (
270
- cx,
271
- USELESS_ATTRIBUTE ,
272
- line_span,
273
- "useless lint attribute" ,
274
- |db| {
275
- sugg = sugg. replacen ( "#[" , "#![" , 1 ) ;
276
- db. span_suggestion (
277
- line_span,
278
- "if you just forgot a `!`, use" ,
279
- sugg,
280
- Applicability :: MachineApplicable ,
281
- ) ;
245
+ if let Some ( ident) = attr. ident_str ( ) {
246
+ match ident {
247
+ "allow" | "warn" | "deny" | "forbid" => {
248
+ // whitelist `unused_imports` and `deprecated` for `use` items
249
+ // and `unused_imports` for `extern crate` items with `macro_use`
250
+ for lint in lint_list {
251
+ match item. node {
252
+ ItemKind :: Use ( ..) => {
253
+ if is_word ( lint, "unused_imports" ) || is_word ( lint, "deprecated" ) {
254
+ return ;
255
+ }
256
+ } ,
257
+ ItemKind :: ExternCrate ( ..) => {
258
+ if is_word ( lint, "unused_imports" ) && skip_unused_imports {
259
+ return ;
260
+ }
261
+ if is_word ( lint, "unused_extern_crates" ) {
262
+ return ;
263
+ }
282
264
} ,
283
- ) ;
265
+ _ => { } ,
266
+ }
284
267
}
285
- }
286
- } ,
287
- _ => { } ,
268
+ let line_span = last_line_of_span ( cx, attr. span ) ;
269
+
270
+ if let Some ( mut sugg) = snippet_opt ( cx, line_span) {
271
+ if sugg. contains ( "#[" ) {
272
+ span_lint_and_then (
273
+ cx,
274
+ USELESS_ATTRIBUTE ,
275
+ line_span,
276
+ "useless lint attribute" ,
277
+ |db| {
278
+ sugg = sugg. replacen ( "#[" , "#![" , 1 ) ;
279
+ db. span_suggestion (
280
+ line_span,
281
+ "if you just forgot a `!`, use" ,
282
+ sugg,
283
+ Applicability :: MachineApplicable ,
284
+ ) ;
285
+ } ,
286
+ ) ;
287
+ }
288
+ }
289
+ } ,
290
+ _ => { } ,
291
+ }
288
292
}
289
293
}
290
294
}
@@ -311,10 +315,11 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
311
315
let lint_store = cx. lints ( ) ;
312
316
for lint in items {
313
317
if_chain ! {
314
- if let Some ( word) = lint. word( ) ;
315
- if let Some ( tool_name) = word. is_scoped( ) ;
318
+ if let Some ( meta_item) = lint. meta_item( ) ;
319
+ if meta_item. path. segments. len( ) > 1 ;
320
+ if let tool_name = meta_item. path. segments[ 0 ] . ident;
316
321
if tool_name. as_str( ) == "clippy" ;
317
- let name = word . name ( ) ;
322
+ let name = meta_item . path . segments . last ( ) . unwrap ( ) . ident . name ;
318
323
if let CheckLintNameResult :: Tool ( Err ( ( None , _) ) ) = lint_store. check_lint_name(
319
324
& name. as_str( ) ,
320
325
Some ( tool_name. as_str( ) ) ,
@@ -323,7 +328,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
323
328
span_lint_and_then(
324
329
cx,
325
330
UNKNOWN_CLIPPY_LINTS ,
326
- lint. span,
331
+ lint. span( ) ,
327
332
& format!( "unknown clippy lint: clippy::{}" , name) ,
328
333
|db| {
329
334
if name. as_str( ) . chars( ) . any( char :: is_uppercase) {
@@ -337,7 +342,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
337
342
CheckLintNameResult :: NoLint ( None ) => ( ) ,
338
343
_ => {
339
344
db. span_suggestion(
340
- lint. span,
345
+ lint. span( ) ,
341
346
"lowercase the lint name" ,
342
347
name_lower,
343
348
Applicability :: MaybeIncorrect ,
@@ -352,22 +357,22 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
352
357
}
353
358
}
354
359
355
- fn is_relevant_item ( tcx : TyCtxt < ' _ , ' _ , ' _ > , item : & Item ) -> bool {
360
+ fn is_relevant_item < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , item : & Item ) -> bool {
356
361
if let ItemKind :: Fn ( _, _, _, eid) = item. node {
357
362
is_relevant_expr ( tcx, tcx. body_tables ( eid) , & tcx. hir ( ) . body ( eid) . value )
358
363
} else {
359
364
true
360
365
}
361
366
}
362
367
363
- fn is_relevant_impl ( tcx : TyCtxt < ' _ , ' _ , ' _ > , item : & ImplItem ) -> bool {
368
+ fn is_relevant_impl < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , item : & ImplItem ) -> bool {
364
369
match item. node {
365
370
ImplItemKind :: Method ( _, eid) => is_relevant_expr ( tcx, tcx. body_tables ( eid) , & tcx. hir ( ) . body ( eid) . value ) ,
366
371
_ => false ,
367
372
}
368
373
}
369
374
370
- fn is_relevant_trait ( tcx : TyCtxt < ' _ , ' _ , ' _ > , item : & TraitItem ) -> bool {
375
+ fn is_relevant_trait < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , item : & TraitItem ) -> bool {
371
376
match item. node {
372
377
TraitItemKind :: Method ( _, TraitMethod :: Required ( _) ) => true ,
373
378
TraitItemKind :: Method ( _, TraitMethod :: Provided ( eid) ) => {
@@ -377,7 +382,7 @@ fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool {
377
382
}
378
383
}
379
384
380
- fn is_relevant_block ( tcx : TyCtxt < ' _ , ' _ , ' _ > , tables : & ty:: TypeckTables < ' _ > , block : & Block ) -> bool {
385
+ fn is_relevant_block < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , tables : & ty:: TypeckTables < ' _ > , block : & Block ) -> bool {
381
386
if let Some ( stmt) = block. stmts . first ( ) {
382
387
match & stmt. node {
383
388
StmtKind :: Local ( _) => true ,
@@ -389,7 +394,7 @@ fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, blo
389
394
}
390
395
}
391
396
392
- fn is_relevant_expr ( tcx : TyCtxt < ' _ , ' _ , ' _ > , tables : & ty:: TypeckTables < ' _ > , expr : & Expr ) -> bool {
397
+ fn is_relevant_expr < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , tables : & ty:: TypeckTables < ' _ > , expr : & Expr ) -> bool {
393
398
match & expr. node {
394
399
ExprKind :: Block ( block, _) => is_relevant_block ( tcx, tables, block) ,
395
400
ExprKind :: Ret ( Some ( e) ) => is_relevant_expr ( tcx, tables, e) ,
@@ -443,7 +448,7 @@ fn check_attrs(cx: &LateContext<'_, '_>, span: Span, name: Name, attrs: &[Attrib
443
448
}
444
449
445
450
if let Some ( values) = attr. meta_item_list ( ) {
446
- if values. len ( ) != 1 || attr. name ( ) != "inline" {
451
+ if values. len ( ) != 1 || ! attr. check_name ( "inline" ) {
447
452
continue ;
448
453
}
449
454
if is_word ( & values[ 0 ] , "always" ) {
@@ -476,8 +481,8 @@ fn check_semver(cx: &LateContext<'_, '_>, span: Span, lit: &Lit) {
476
481
}
477
482
478
483
fn is_word ( nmi : & NestedMetaItem , expected : & str ) -> bool {
479
- if let NestedMetaItemKind :: MetaItem ( mi) = & nmi. node {
480
- mi. is_word ( ) && mi. name ( ) == expected
484
+ if let NestedMetaItem :: MetaItem ( mi) = & nmi {
485
+ mi. is_word ( ) && mi. check_name ( expected)
481
486
} else {
482
487
false
483
488
}
@@ -514,15 +519,16 @@ impl EarlyLintPass for CfgAttrPass {
514
519
fn check_attribute ( & mut self , cx : & EarlyContext < ' _ > , attr : & Attribute ) {
515
520
if_chain ! {
516
521
// check cfg_attr
517
- if attr. name ( ) == "cfg_attr" ;
522
+ if attr. check_name ( "cfg_attr" ) ;
518
523
if let Some ( items) = attr. meta_item_list( ) ;
519
524
if items. len( ) == 2 ;
520
525
// check for `rustfmt`
521
526
if let Some ( feature_item) = items[ 0 ] . meta_item( ) ;
522
- if feature_item. name ( ) == "rustfmt" ;
527
+ if feature_item. check_name ( "rustfmt" ) ;
523
528
// check for `rustfmt_skip` and `rustfmt::skip`
524
529
if let Some ( skip_item) = & items[ 1 ] . meta_item( ) ;
525
- if skip_item. name( ) == "rustfmt_skip" || skip_item. name( ) == "skip" ;
530
+ if skip_item. check_name( "rustfmt_skip" ) ||
531
+ skip_item. path. segments. last( ) . expect( "empty path in attribute" ) . ident. name == "skip" ;
526
532
// Only lint outer attributes, because custom inner attributes are unstable
527
533
// Tracking issue: https://github.com/rust-lang/rust/issues/54726
528
534
if let AttrStyle :: Outer = attr. style;
0 commit comments