@@ -362,6 +362,32 @@ declare_clippy_lint! {
362
362
"ensure that all `cfg(any())` and `cfg(all())` have more than one condition"
363
363
}
364
364
365
+ declare_clippy_lint ! {
366
+ /// ### What it does
367
+ /// Checks for `#[cfg(features = "...")]` and suggests to replace it with
368
+ /// `#[cfg(feature = "...")]`.
369
+ ///
370
+ /// ### Why is this bad?
371
+ /// Misspelling `feature` as `features` can be sometimes hard to spot. It
372
+ /// may cause conditional compilation not work quitely.
373
+ ///
374
+ /// ### Example
375
+ /// ```rust
376
+ /// #[cfg(features = "some-feature")]
377
+ /// fn conditional() { }
378
+ /// ```
379
+ ///
380
+ /// Use instead:
381
+ /// ```rust
382
+ /// #[cfg(feature = "some-feature")]
383
+ /// fn conditional() { }
384
+ /// ```
385
+ #[ clippy:: version = "1.69.0" ]
386
+ pub MAYBE_MISUSED_CFG ,
387
+ suspicious,
388
+ "prevent from misusing the wrong attr name"
389
+ }
390
+
365
391
declare_lint_pass ! ( Attributes => [
366
392
ALLOW_ATTRIBUTES_WITHOUT_REASON ,
367
393
INLINE_ALWAYS ,
@@ -676,6 +702,7 @@ impl_lint_pass!(EarlyAttributes => [
676
702
EMPTY_LINE_AFTER_OUTER_ATTR ,
677
703
EMPTY_LINE_AFTER_DOC_COMMENTS ,
678
704
NON_MINIMAL_CFG ,
705
+ MAYBE_MISUSED_CFG ,
679
706
] ) ;
680
707
681
708
impl EarlyLintPass for EarlyAttributes {
@@ -687,6 +714,7 @@ impl EarlyLintPass for EarlyAttributes {
687
714
check_deprecated_cfg_attr ( cx, attr, & self . msrv ) ;
688
715
check_mismatched_target_os ( cx, attr) ;
689
716
check_minimal_cfg_condition ( cx, attr) ;
717
+ check_misused_cfg ( cx, attr) ;
690
718
}
691
719
692
720
extract_msrv_attr ! ( EarlyContext ) ;
@@ -810,6 +838,27 @@ fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
810
838
}
811
839
}
812
840
841
+ fn check_nested_misused_cfg ( cx : & EarlyContext < ' _ > , items : & [ NestedMetaItem ] ) {
842
+ for item in items. iter ( ) {
843
+ if let NestedMetaItem :: MetaItem ( meta) = item {
844
+ if meta. has_name ( sym ! ( features) ) && let Some ( val) = meta. value_str ( ) {
845
+ span_lint_and_sugg (
846
+ cx,
847
+ MAYBE_MISUSED_CFG ,
848
+ meta. span ,
849
+ "feature may misspelled as features" ,
850
+ "use" ,
851
+ format ! ( "feature = \" {val}\" " ) ,
852
+ Applicability :: MaybeIncorrect ,
853
+ ) ;
854
+ }
855
+ if let MetaItemKind :: List ( list) = & meta. kind {
856
+ check_nested_misused_cfg ( cx, list) ;
857
+ }
858
+ }
859
+ }
860
+ }
861
+
813
862
fn check_minimal_cfg_condition ( cx : & EarlyContext < ' _ > , attr : & Attribute ) {
814
863
if attr. has_name ( sym:: cfg) &&
815
864
let Some ( items) = attr. meta_item_list ( )
@@ -818,6 +867,14 @@ fn check_minimal_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) {
818
867
}
819
868
}
820
869
870
+ fn check_misused_cfg ( cx : & EarlyContext < ' _ > , attr : & Attribute ) {
871
+ if attr. has_name ( sym:: cfg) &&
872
+ let Some ( items) = attr. meta_item_list ( )
873
+ {
874
+ check_nested_misused_cfg ( cx, & items) ;
875
+ }
876
+ }
877
+
821
878
fn check_mismatched_target_os ( cx : & EarlyContext < ' _ > , attr : & Attribute ) {
822
879
fn find_os ( name : & str ) -> Option < & ' static str > {
823
880
UNIX_SYSTEMS
0 commit comments