about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-02-26 12:25:04 +0100
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2024-02-27 15:22:39 +0100
commit9f4a58f6162c66c76ce16e2ecbe3e757d6fbb6db (patch)
tree98a0340921945c80b580b0694d9d269b7c1134dc
parent10136170fe9ed01e46aeb4f4479175b79eb0e3c7 (diff)
downloadrust-9f4a58f6162c66c76ce16e2ecbe3e757d6fbb6db.tar.gz
rust-9f4a58f6162c66c76ce16e2ecbe3e757d6fbb6db.zip
Add new `mixed_attributes_style` lint
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_lints/src/attrs.rs55
-rw-r--r--clippy_lints/src/declared_lints.rs1
3 files changed, 57 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f0b01742deb..20fc17df3c4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5423,6 +5423,7 @@ Released 2018-09-13
 [`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_spin_loop
 [`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_trait_methods
 [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes
+[`mixed_attributes_style`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_attributes_style
 [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals
 [`mixed_read_write_in_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_read_write_in_expression
 [`mod_module_files`]: https://rust-lang.github.io/rust-clippy/master/index.html#mod_module_files
diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs
index f2937d51340..d3ca4d33806 100644
--- a/clippy_lints/src/attrs.rs
+++ b/clippy_lints/src/attrs.rs
@@ -485,6 +485,33 @@ declare_clippy_lint! {
     "usage of `cfg_attr(clippy, allow(clippy::lint))` instead of `allow(clippy::lint)`"
 }
 
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks that an item has only one kind of attributes.
+    ///
+    /// ### Why is this bad?
+    /// Having both kinds of attributes makes it more complicated to read code.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// #[cfg(linux)]
+    /// pub fn foo() {
+    ///     #![cfg(windows)]
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```no_run
+    /// #[cfg(linux)]
+    /// #[cfg(windows)]
+    /// pub fn foo() {
+    /// }
+    /// ```
+    #[clippy::version = "1.78.0"]
+    pub MIXED_ATTRIBUTES_STYLE,
+    suspicious,
+    "item has both inner and outer attributes"
+}
+
 declare_lint_pass!(Attributes => [
     ALLOW_ATTRIBUTES_WITHOUT_REASON,
     INLINE_ALWAYS,
@@ -849,11 +876,13 @@ impl_lint_pass!(EarlyAttributes => [
     MAYBE_MISUSED_CFG,
     DEPRECATED_CLIPPY_CFG_ATTR,
     UNNECESSARY_CLIPPY_CFG,
+    MIXED_ATTRIBUTES_STYLE,
 ]);
 
 impl EarlyLintPass for EarlyAttributes {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
         check_empty_line_after_outer_attr(cx, item);
+        check_mixed_attributes(cx, item);
     }
 
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
@@ -867,6 +896,32 @@ impl EarlyLintPass for EarlyAttributes {
     extract_msrv_attr!(EarlyContext);
 }
 
+fn check_mixed_attributes(cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
+    let mut has_outer = false;
+    let mut has_inner = false;
+
+    for attr in &item.attrs {
+        if attr.span.from_expansion() {
+            continue;
+        }
+        match attr.style {
+            AttrStyle::Inner => has_inner = true,
+            AttrStyle::Outer => has_outer = true,
+        }
+    }
+    if !has_outer || !has_inner {
+        return;
+    }
+    let mut attrs_iter = item.attrs.iter().filter(|attr| !attr.span.from_expansion());
+    let span = attrs_iter.next().unwrap().span;
+    span_lint(
+        cx,
+        MIXED_ATTRIBUTES_STYLE,
+        span.with_hi(attrs_iter.last().unwrap().span.hi()),
+        "item has both inner and outer attributes",
+    );
+}
+
 /// Check for empty lines after outer attributes.
 ///
 /// Attributes and documentation comments are both considered outer attributes
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index fb3ae2457e3..a453386154d 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -58,6 +58,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::attrs::INLINE_ALWAYS_INFO,
     crate::attrs::MAYBE_MISUSED_CFG_INFO,
     crate::attrs::MISMATCHED_TARGET_OS_INFO,
+    crate::attrs::MIXED_ATTRIBUTES_STYLE_INFO,
     crate::attrs::NON_MINIMAL_CFG_INFO,
     crate::attrs::SHOULD_PANIC_WITHOUT_EXPECT_INFO,
     crate::attrs::UNNECESSARY_CLIPPY_CFG_INFO,