@@ -433,6 +433,32 @@ declare_clippy_lint! {
433
433
"prevent from misusing the wrong attr name"
434
434
}
435
435
436
+ declare_clippy_lint ! {
437
+ /// ### What it does
438
+ /// Checks for `#[cfg_attr(feature = "cargo-clippy", ...)]` and for
439
+ /// `#[cfg(feature = "cargo-clippy")]` and suggests to replace it with
440
+ /// `#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`.
441
+ ///
442
+ /// ### Why is this bad?
443
+ /// This feature has been deprecated for years and shouldn't be used anymore.
444
+ ///
445
+ /// ### Example
446
+ /// ```no_run
447
+ /// #[cfg(feature = "cargo-clippy")]
448
+ /// struct Bar;
449
+ /// ```
450
+ ///
451
+ /// Use instead:
452
+ /// ```no_run
453
+ /// #[cfg(clippy)]
454
+ /// struct Bar;
455
+ /// ```
456
+ #[ clippy:: version = "1.78.0" ]
457
+ pub DEPRECATED_CLIPPY_CFG_ATTR ,
458
+ suspicious,
459
+ "usage of `cfg(feature = \" cargo-clippy\" )` instead of `cfg(clippy)`"
460
+ }
461
+
436
462
declare_lint_pass ! ( Attributes => [
437
463
ALLOW_ATTRIBUTES_WITHOUT_REASON ,
438
464
INLINE_ALWAYS ,
@@ -794,6 +820,7 @@ impl_lint_pass!(EarlyAttributes => [
794
820
EMPTY_LINE_AFTER_DOC_COMMENTS ,
795
821
NON_MINIMAL_CFG ,
796
822
MAYBE_MISUSED_CFG ,
823
+ DEPRECATED_CLIPPY_CFG_ATTR ,
797
824
] ) ;
798
825
799
826
impl EarlyLintPass for EarlyAttributes {
@@ -803,6 +830,7 @@ impl EarlyLintPass for EarlyAttributes {
803
830
804
831
fn check_attribute ( & mut self , cx : & EarlyContext < ' _ > , attr : & Attribute ) {
805
832
check_deprecated_cfg_attr ( cx, attr, & self . msrv ) ;
833
+ check_deprecated_cfg ( cx, attr) ;
806
834
check_mismatched_target_os ( cx, attr) ;
807
835
check_minimal_cfg_condition ( cx, attr) ;
808
836
check_misused_cfg ( cx, attr) ;
@@ -857,39 +885,80 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It
857
885
}
858
886
}
859
887
888
+ fn check_cargo_clippy_attr ( cx : & EarlyContext < ' _ > , item : & rustc_ast:: MetaItem ) {
889
+ if item. has_name ( sym:: feature) && item. value_str ( ) . is_some_and ( |v| v. as_str ( ) == "cargo-clippy" ) {
890
+ span_lint_and_sugg (
891
+ cx,
892
+ DEPRECATED_CLIPPY_CFG_ATTR ,
893
+ item. span ,
894
+ "`feature = \" cargo-clippy\" ` was replaced by `clippy`" ,
895
+ "replace with" ,
896
+ "clippy" . to_string ( ) ,
897
+ Applicability :: MachineApplicable ,
898
+ ) ;
899
+ }
900
+ }
901
+
902
+ fn check_deprecated_cfg_recursively ( cx : & EarlyContext < ' _ > , attr : & rustc_ast:: MetaItem ) {
903
+ if let Some ( ident) = attr. ident ( ) {
904
+ if [ "any" , "all" , "not" ] . contains ( & ident. name . as_str ( ) ) {
905
+ let Some ( list) = attr. meta_item_list ( ) else { return } ;
906
+ for item in list. iter ( ) . filter_map ( |item| item. meta_item ( ) ) {
907
+ check_deprecated_cfg_recursively ( cx, item) ;
908
+ }
909
+ } else {
910
+ check_cargo_clippy_attr ( cx, attr) ;
911
+ }
912
+ }
913
+ }
914
+
915
+ fn check_deprecated_cfg ( cx : & EarlyContext < ' _ > , attr : & Attribute ) {
916
+ if attr. has_name ( sym:: cfg)
917
+ && let Some ( list) = attr. meta_item_list ( )
918
+ {
919
+ for item in list. iter ( ) . filter_map ( |item| item. meta_item ( ) ) {
920
+ check_deprecated_cfg_recursively ( cx, item) ;
921
+ }
922
+ }
923
+ }
924
+
860
925
fn check_deprecated_cfg_attr ( cx : & EarlyContext < ' _ > , attr : & Attribute , msrv : & Msrv ) {
861
- if msrv. meets ( msrvs:: TOOL_ATTRIBUTES )
862
- // check cfg_attr
863
- && attr. has_name ( sym:: cfg_attr)
926
+ // check cfg_attr
927
+ if attr. has_name ( sym:: cfg_attr)
864
928
&& let Some ( items) = attr. meta_item_list ( )
865
929
&& items. len ( ) == 2
866
- // check for `rustfmt`
867
930
&& let Some ( feature_item) = items[ 0 ] . meta_item ( )
868
- && feature_item. has_name ( sym:: rustfmt)
869
- // check for `rustfmt_skip` and `rustfmt::skip`
870
- && let Some ( skip_item) = & items[ 1 ] . meta_item ( )
871
- && ( skip_item. has_name ( sym ! ( rustfmt_skip) )
872
- || skip_item
873
- . path
874
- . segments
875
- . last ( )
876
- . expect ( "empty path in attribute" )
877
- . ident
878
- . name
879
- == sym:: skip)
880
- // Only lint outer attributes, because custom inner attributes are unstable
881
- // Tracking issue: https://github.com/rust-lang/rust/issues/54726
882
- && attr. style == AttrStyle :: Outer
883
931
{
884
- span_lint_and_sugg (
885
- cx,
886
- DEPRECATED_CFG_ATTR ,
887
- attr. span ,
888
- "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes" ,
889
- "use" ,
890
- "#[rustfmt::skip]" . to_string ( ) ,
891
- Applicability :: MachineApplicable ,
892
- ) ;
932
+ // check for `rustfmt`
933
+ if feature_item. has_name ( sym:: rustfmt)
934
+ && msrv. meets ( msrvs:: TOOL_ATTRIBUTES )
935
+ // check for `rustfmt_skip` and `rustfmt::skip`
936
+ && let Some ( skip_item) = & items[ 1 ] . meta_item ( )
937
+ && ( skip_item. has_name ( sym ! ( rustfmt_skip) )
938
+ || skip_item
939
+ . path
940
+ . segments
941
+ . last ( )
942
+ . expect ( "empty path in attribute" )
943
+ . ident
944
+ . name
945
+ == sym:: skip)
946
+ // Only lint outer attributes, because custom inner attributes are unstable
947
+ // Tracking issue: https://github.com/rust-lang/rust/issues/54726
948
+ && attr. style == AttrStyle :: Outer
949
+ {
950
+ span_lint_and_sugg (
951
+ cx,
952
+ DEPRECATED_CFG_ATTR ,
953
+ attr. span ,
954
+ "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes" ,
955
+ "use" ,
956
+ "#[rustfmt::skip]" . to_string ( ) ,
957
+ Applicability :: MachineApplicable ,
958
+ ) ;
959
+ } else {
960
+ check_deprecated_cfg_recursively ( cx, feature_item) ;
961
+ }
893
962
}
894
963
}
895
964
0 commit comments