1- use super :: { Attribute , DEPRECATED_CFG_ATTR , DEPRECATED_CLIPPY_CFG_ATTR , unnecessary_clippy_cfg } ;
2- use clippy_utils:: diagnostics:: span_lint_and_sugg;
1+ use super :: { Attribute , DEPRECATED_CFG_ATTR , DEPRECATED_CLIPPY_CFG_ATTR } ;
2+ use clippy_utils:: diagnostics:: { span_lint_and_sugg, span_lint_and_then , span_lint_hir_and_then } ;
33use clippy_utils:: msrvs:: { self , MsrvStack } ;
44use clippy_utils:: sym;
55use rustc_ast:: AttrStyle ;
66use rustc_errors:: Applicability ;
7- use rustc_lint:: EarlyContext ;
7+ use rustc_hir:: attrs:: CfgEntry ;
8+ use rustc_hir:: def_id:: { LOCAL_CRATE , LocalDefId } ;
9+ use rustc_lint:: { EarlyContext , LateContext } ;
810
9- pub ( super ) fn check ( cx : & EarlyContext < ' _ > , attr : & Attribute , msrv : & MsrvStack ) {
11+ pub ( super ) fn check_rustfmt ( cx : & EarlyContext < ' _ > , attrs : & [ Attribute ] , msrv : & MsrvStack ) {
12+ for attr in attrs {
13+ check_rustfmt_attr ( cx, attr, msrv) ;
14+ }
15+ }
16+
17+ fn check_rustfmt_attr ( cx : & EarlyContext < ' _ > , attr : & Attribute , msrv : & MsrvStack ) {
1018 // check cfg_attr
11- if attr. has_name ( sym:: cfg_attr )
19+ if attr. has_name ( sym:: cfg_attr_trace )
1220 && let Some ( items) = attr. meta_item_list ( )
1321 && items. len ( ) == 2
1422 && let Some ( feature_item) = items[ 0 ] . meta_item ( )
15- {
1623 // check for `rustfmt`
17- if feature_item. has_name ( sym:: rustfmt)
18- && msrv. meets ( msrvs:: TOOL_ATTRIBUTES )
19- // check for `rustfmt_skip` and `rustfmt::skip`
20- && let Some ( skip_item) = & items[ 1 ] . meta_item ( )
21- && ( skip_item. has_name ( sym:: rustfmt_skip)
22- || skip_item
23- . path
24- . segments
25- . last ( )
26- . expect ( "empty path in attribute" )
27- . ident
28- . name
29- == sym:: skip)
30- // Only lint outer attributes, because custom inner attributes are unstable
31- // Tracking issue: https://github.com/rust-lang/rust/issues/54726
32- && attr. style == AttrStyle :: Outer
33- {
34- span_lint_and_sugg (
35- cx,
36- DEPRECATED_CFG_ATTR ,
37- attr. span ,
38- "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes" ,
39- "use" ,
40- "#[rustfmt::skip]" . to_string ( ) ,
41- Applicability :: MachineApplicable ,
42- ) ;
43- } else {
44- check_deprecated_cfg_recursively ( cx, feature_item) ;
45- if let Some ( behind_cfg_attr) = items[ 1 ] . meta_item ( ) {
46- unnecessary_clippy_cfg:: check ( cx, feature_item, behind_cfg_attr, attr) ;
47- }
48- }
49- }
50- }
51-
52- pub ( super ) fn check_clippy ( cx : & EarlyContext < ' _ > , attr : & Attribute ) {
53- if attr. has_name ( sym:: cfg)
54- && let Some ( list) = attr. meta_item_list ( )
24+ && feature_item. has_name ( sym:: rustfmt)
25+ && msrv. meets ( msrvs:: TOOL_ATTRIBUTES )
26+ // check for `rustfmt_skip` and `rustfmt::skip`
27+ && let Some ( skip_item) = & items[ 1 ] . meta_item ( )
28+ && ( skip_item. has_name ( sym:: rustfmt_skip)
29+ || skip_item
30+ . path
31+ . segments
32+ . last ( )
33+ . expect ( "empty path in attribute" )
34+ . ident
35+ . name
36+ == sym:: skip)
37+ // Only lint outer attributes, because custom inner attributes are unstable
38+ // Tracking issue: https://github.com/rust-lang/rust/issues/54726
39+ && attr. style == AttrStyle :: Outer
5540 {
56- for item in list. iter ( ) . filter_map ( |item| item. meta_item ( ) ) {
57- check_deprecated_cfg_recursively ( cx, item) ;
58- }
41+ span_lint_and_then (
42+ cx,
43+ DEPRECATED_CFG_ATTR ,
44+ attr. span ,
45+ "`cfg_attr` is deprecated for rustfmt" ,
46+ |diag| {
47+ diag. span_suggestion_verbose (
48+ attr. span ,
49+ "use the `rustfmt::skip` tool attribute instead" ,
50+ "#[rustfmt::skip]" ,
51+ Applicability :: MachineApplicable ,
52+ ) ;
53+ } ,
54+ ) ;
5955 }
6056}
6157
62- fn check_deprecated_cfg_recursively ( cx : & EarlyContext < ' _ > , attr : & rustc_ast:: MetaItem ) {
58+ pub ( super ) fn check ( cx : & EarlyContext < ' _ > , attr : & rustc_ast:: MetaItem ) {
6359 if let Some ( ident) = attr. ident ( ) {
6460 if matches ! ( ident. name, sym:: any | sym:: all | sym:: not) {
6561 let Some ( list) = attr. meta_item_list ( ) else { return } ;
6662 for item in list. iter ( ) . filter_map ( |item| item. meta_item ( ) ) {
67- check_deprecated_cfg_recursively ( cx, item) ;
63+ check ( cx, item) ;
6864 }
6965 } else {
7066 check_cargo_clippy_attr ( cx, attr) ;
@@ -85,3 +81,40 @@ fn check_cargo_clippy_attr(cx: &EarlyContext<'_>, item: &rustc_ast::MetaItem) {
8581 ) ;
8682 }
8783}
84+
85+ pub fn check_stripped ( cx : & LateContext < ' _ > ) {
86+ for stripped in cx. tcx . stripped_cfg_items ( LOCAL_CRATE ) {
87+ if let Some ( parent_module) = stripped. parent_module . as_local ( ) {
88+ check_cfg_entry ( cx, & stripped. cfg . 0 , parent_module) ;
89+ }
90+ }
91+ }
92+
93+ fn check_cfg_entry ( cx : & LateContext < ' _ > , cfg : & CfgEntry , parent_module : LocalDefId ) {
94+ match cfg {
95+ & CfgEntry :: NameValue {
96+ name : sym:: feature,
97+ name_span : _,
98+ value : Some ( ( sym:: cargo_clippy, _) ) ,
99+ span,
100+ } => {
101+ span_lint_hir_and_then (
102+ cx,
103+ DEPRECATED_CLIPPY_CFG_ATTR ,
104+ cx. tcx . local_def_id_to_hir_id ( parent_module) ,
105+ span,
106+ "`feature = \" cargo-clippy\" ` was replaced by `clippy`" ,
107+ |diag| {
108+ diag. span_suggestion ( span, "replace with" , "clippy" , Applicability :: MachineApplicable ) ;
109+ } ,
110+ ) ;
111+ } ,
112+ CfgEntry :: All ( children, _) | CfgEntry :: Any ( children, _) => {
113+ for child in children {
114+ check_cfg_entry ( cx, child, parent_module) ;
115+ }
116+ } ,
117+ CfgEntry :: Not ( child, _) => check_cfg_entry ( cx, child, parent_module) ,
118+ _ => { } ,
119+ }
120+ }
0 commit comments