@@ -14,7 +14,7 @@ use rustc::ty::{self, TyCtxt};
1414use rustc:: { declare_tool_lint, lint_array} ;
1515use rustc_errors:: Applicability ;
1616use semver:: Version ;
17- use syntax:: ast:: { AttrStyle , Attribute , Lit , LitKind , MetaItemKind , NestedMetaItem , NestedMetaItemKind } ;
17+ use syntax:: ast:: { AttrStyle , Attribute , Lit , LitKind , MetaItemKind , NestedMetaItem } ;
1818use syntax:: source_map:: Span ;
1919
2020declare_clippy_lint ! {
@@ -208,22 +208,24 @@ impl LintPass for AttrPass {
208208impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for AttrPass {
209209 fn check_attribute ( & mut self , cx : & LateContext < ' a , ' tcx > , attr : & ' tcx Attribute ) {
210210 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+ }
227229 }
228230 }
229231 }
@@ -236,55 +238,57 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
236238 }
237239 match item. node {
238240 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" ) ) ;
240242
241243 for attr in & item. attrs {
242244 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+ }
282264 } ,
283- ) ;
265+ _ => { } ,
266+ }
284267 }
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+ }
288292 }
289293 }
290294 }
@@ -311,10 +315,11 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
311315 let lint_store = cx. lints ( ) ;
312316 for lint in items {
313317 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;
316321 if tool_name. as_str( ) == "clippy" ;
317- let name = word . name ( ) ;
322+ let name = meta_item . path . segments . last ( ) . unwrap ( ) . ident . name ;
318323 if let CheckLintNameResult :: Tool ( Err ( ( None , _) ) ) = lint_store. check_lint_name(
319324 & name. as_str( ) ,
320325 Some ( tool_name. as_str( ) ) ,
@@ -323,7 +328,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
323328 span_lint_and_then(
324329 cx,
325330 UNKNOWN_CLIPPY_LINTS ,
326- lint. span,
331+ lint. span( ) ,
327332 & format!( "unknown clippy lint: clippy::{}" , name) ,
328333 |db| {
329334 if name. as_str( ) . chars( ) . any( char :: is_uppercase) {
@@ -337,7 +342,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
337342 CheckLintNameResult :: NoLint ( None ) => ( ) ,
338343 _ => {
339344 db. span_suggestion(
340- lint. span,
345+ lint. span( ) ,
341346 "lowercase the lint name" ,
342347 name_lower,
343348 Applicability :: MaybeIncorrect ,
@@ -352,22 +357,22 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
352357 }
353358}
354359
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 {
356361 if let ItemKind :: Fn ( _, _, _, eid) = item. node {
357362 is_relevant_expr ( tcx, tcx. body_tables ( eid) , & tcx. hir ( ) . body ( eid) . value )
358363 } else {
359364 true
360365 }
361366}
362367
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 {
364369 match item. node {
365370 ImplItemKind :: Method ( _, eid) => is_relevant_expr ( tcx, tcx. body_tables ( eid) , & tcx. hir ( ) . body ( eid) . value ) ,
366371 _ => false ,
367372 }
368373}
369374
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 {
371376 match item. node {
372377 TraitItemKind :: Method ( _, TraitMethod :: Required ( _) ) => true ,
373378 TraitItemKind :: Method ( _, TraitMethod :: Provided ( eid) ) => {
@@ -377,7 +382,7 @@ fn is_relevant_trait(tcx: TyCtxt<'_, '_, '_>, item: &TraitItem) -> bool {
377382 }
378383}
379384
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 {
381386 if let Some ( stmt) = block. stmts . first ( ) {
382387 match & stmt. node {
383388 StmtKind :: Local ( _) => true ,
@@ -389,7 +394,7 @@ fn is_relevant_block(tcx: TyCtxt<'_, '_, '_>, tables: &ty::TypeckTables<'_>, blo
389394 }
390395}
391396
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 {
393398 match & expr. node {
394399 ExprKind :: Block ( block, _) => is_relevant_block ( tcx, tables, block) ,
395400 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
443448 }
444449
445450 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" ) {
447452 continue ;
448453 }
449454 if is_word ( & values[ 0 ] , "always" ) {
@@ -476,8 +481,8 @@ fn check_semver(cx: &LateContext<'_, '_>, span: Span, lit: &Lit) {
476481}
477482
478483fn 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)
481486 } else {
482487 false
483488 }
@@ -514,15 +519,16 @@ impl EarlyLintPass for CfgAttrPass {
514519 fn check_attribute ( & mut self , cx : & EarlyContext < ' _ > , attr : & Attribute ) {
515520 if_chain ! {
516521 // check cfg_attr
517- if attr. name ( ) == "cfg_attr" ;
522+ if attr. check_name ( "cfg_attr" ) ;
518523 if let Some ( items) = attr. meta_item_list( ) ;
519524 if items. len( ) == 2 ;
520525 // check for `rustfmt`
521526 if let Some ( feature_item) = items[ 0 ] . meta_item( ) ;
522- if feature_item. name ( ) == "rustfmt" ;
527+ if feature_item. check_name ( "rustfmt" ) ;
523528 // check for `rustfmt_skip` and `rustfmt::skip`
524529 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" ;
526532 // Only lint outer attributes, because custom inner attributes are unstable
527533 // Tracking issue: https://github.com/rust-lang/rust/issues/54726
528534 if let AttrStyle :: Outer = attr. style;
0 commit comments