about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_lints/src/attrs.rs125
-rw-r--r--clippy_lints/src/declared_lints.rs1
3 files changed, 99 insertions, 28 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6080fd3663b..053f7de5446 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5071,6 +5071,7 @@ Released 2018-09-13
 [`default_trait_access`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_trait_access
 [`default_union_representation`]: https://rust-lang.github.io/rust-clippy/master/index.html#default_union_representation
 [`deprecated_cfg_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_cfg_attr
+[`deprecated_clippy_cfg_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_clippy_cfg_attr
 [`deprecated_semver`]: https://rust-lang.github.io/rust-clippy/master/index.html#deprecated_semver
 [`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof
 [`deref_by_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_by_slicing
diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs
index da38422874b..755f4ad3c89 100644
--- a/clippy_lints/src/attrs.rs
+++ b/clippy_lints/src/attrs.rs
@@ -433,6 +433,32 @@ declare_clippy_lint! {
     "prevent from misusing the wrong attr name"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for `#[cfg_attr(feature = "cargo-clippy", ...)]` and for
+    /// `#[cfg(feature = "cargo-clippy")]` and suggests to replace it with
+    /// `#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`.
+    ///
+    /// ### Why is this bad?
+    /// This feature has been deprecated for years and shouldn't be used anymore.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[cfg(feature = "cargo-clippy")]
+    /// struct Bar;
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// #[cfg(clippy)]
+    /// struct Bar;
+    /// ```
+    #[clippy::version = "1.78.0"]
+    pub DEPRECATED_CLIPPY_CFG_ATTR,
+    suspicious,
+    "usage of `cfg(feature = \"cargo-clippy\")` instead of `cfg(clippy)`"
+}
+
 declare_lint_pass!(Attributes => [
     ALLOW_ATTRIBUTES_WITHOUT_REASON,
     INLINE_ALWAYS,
@@ -794,6 +820,7 @@ impl_lint_pass!(EarlyAttributes => [
     EMPTY_LINE_AFTER_DOC_COMMENTS,
     NON_MINIMAL_CFG,
     MAYBE_MISUSED_CFG,
+    DEPRECATED_CLIPPY_CFG_ATTR,
 ]);
 
 impl EarlyLintPass for EarlyAttributes {
@@ -803,6 +830,7 @@ impl EarlyLintPass for EarlyAttributes {
 
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
         check_deprecated_cfg_attr(cx, attr, &self.msrv);
+        check_deprecated_cfg(cx, attr);
         check_mismatched_target_os(cx, attr);
         check_minimal_cfg_condition(cx, attr);
         check_misused_cfg(cx, attr);
@@ -857,39 +885,80 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It
     }
 }
 
+fn check_cargo_clippy_attr(cx: &EarlyContext<'_>, item: &rustc_ast::MetaItem) {
+    if item.has_name(sym::feature) && item.value_str().is_some_and(|v| v.as_str() == "cargo-clippy") {
+        span_lint_and_sugg(
+            cx,
+            DEPRECATED_CLIPPY_CFG_ATTR,
+            item.span,
+            "`feature = \"cargo-clippy\"` was replaced by `clippy`",
+            "replace with",
+            "clippy".to_string(),
+            Applicability::MachineApplicable,
+        );
+    }
+}
+
+fn check_deprecated_cfg_recursively(cx: &EarlyContext<'_>, attr: &rustc_ast::MetaItem) {
+    if let Some(ident) = attr.ident() {
+        if ["any", "all", "not"].contains(&ident.name.as_str()) {
+            let Some(list) = attr.meta_item_list() else { return };
+            for item in list.iter().filter_map(|item| item.meta_item()) {
+                check_deprecated_cfg_recursively(cx, item);
+            }
+        } else {
+            check_cargo_clippy_attr(cx, attr);
+        }
+    }
+}
+
+fn check_deprecated_cfg(cx: &EarlyContext<'_>, attr: &Attribute) {
+    if attr.has_name(sym::cfg)
+        && let Some(list) = attr.meta_item_list()
+    {
+        for item in list.iter().filter_map(|item| item.meta_item()) {
+            check_deprecated_cfg_recursively(cx, item);
+        }
+    }
+}
+
 fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msrv) {
-    if msrv.meets(msrvs::TOOL_ATTRIBUTES)
-        // check cfg_attr
-        && attr.has_name(sym::cfg_attr)
+    // check cfg_attr
+    if attr.has_name(sym::cfg_attr)
         && let Some(items) = attr.meta_item_list()
         && items.len() == 2
-        // check for `rustfmt`
         && let Some(feature_item) = items[0].meta_item()
-        && feature_item.has_name(sym::rustfmt)
-        // check for `rustfmt_skip` and `rustfmt::skip`
-        && let Some(skip_item) = &items[1].meta_item()
-        && (skip_item.has_name(sym!(rustfmt_skip))
-            || skip_item
-                .path
-                .segments
-                .last()
-                .expect("empty path in attribute")
-                .ident
-                .name
-                == sym::skip)
-        // Only lint outer attributes, because custom inner attributes are unstable
-        // Tracking issue: https://github.com/rust-lang/rust/issues/54726
-        && attr.style == AttrStyle::Outer
     {
-        span_lint_and_sugg(
-            cx,
-            DEPRECATED_CFG_ATTR,
-            attr.span,
-            "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes",
-            "use",
-            "#[rustfmt::skip]".to_string(),
-            Applicability::MachineApplicable,
-        );
+        // check for `rustfmt`
+        if feature_item.has_name(sym::rustfmt)
+            && msrv.meets(msrvs::TOOL_ATTRIBUTES)
+            // check for `rustfmt_skip` and `rustfmt::skip`
+            && let Some(skip_item) = &items[1].meta_item()
+            && (skip_item.has_name(sym!(rustfmt_skip))
+                || skip_item
+                    .path
+                    .segments
+                    .last()
+                    .expect("empty path in attribute")
+                    .ident
+                    .name
+                    == sym::skip)
+            // Only lint outer attributes, because custom inner attributes are unstable
+            // Tracking issue: https://github.com/rust-lang/rust/issues/54726
+            && attr.style == AttrStyle::Outer
+        {
+            span_lint_and_sugg(
+                cx,
+                DEPRECATED_CFG_ATTR,
+                attr.span,
+                "`cfg_attr` is deprecated for rustfmt and got replaced by tool attributes",
+                "use",
+                "#[rustfmt::skip]".to_string(),
+                Applicability::MachineApplicable,
+            );
+        } else {
+            check_deprecated_cfg_recursively(cx, feature_item);
+        }
     }
 }
 
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index b96a7af9070..c4d26e65b1a 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -51,6 +51,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::attrs::ALLOW_ATTRIBUTES_WITHOUT_REASON_INFO,
     crate::attrs::BLANKET_CLIPPY_RESTRICTION_LINTS_INFO,
     crate::attrs::DEPRECATED_CFG_ATTR_INFO,
+    crate::attrs::DEPRECATED_CLIPPY_CFG_ATTR_INFO,
     crate::attrs::DEPRECATED_SEMVER_INFO,
     crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
     crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,