From 9f4a58f6162c66c76ce16e2ecbe3e757d6fbb6db Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Feb 2024 12:25:04 +0100 Subject: [PATCH] Add new `mixed_attributes_style` lint --- CHANGELOG.md | 1 + clippy_lints/src/attrs.rs | 55 ++++++++++++++++++++++++++++++ clippy_lints/src/declared_lints.rs | 1 + 3 files changed, 57 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b01742deb0..20fc17df3c48 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 f2937d51340b..d3ca4d338065 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 fb3ae2457e3c..a453386154d9 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,