Auto merge of #12354 - GuillaumeGomez:mixed_attributes_style, r=llogiq

Add new `mixed_attributes_style` lint

Add a new lint to detect cases where both inner and outer attributes are used on a same item.

r? `@llogiq`

----

changelog: Add new [`mixed_attributes_style`] lint
This commit is contained in:
bors 2024-02-29 11:44:51 +00:00
commit 00ff8c92d3
7 changed files with 137 additions and 9 deletions

View File

@ -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

View File

@ -485,6 +485,33 @@
"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 @@ pub struct 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 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
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

View File

@ -58,6 +58,7 @@
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,

View File

@ -1,5 +1,7 @@
#![allow(unused)]
#![warn(clippy::empty_docs)]
#![allow(clippy::mixed_attributes_style)]
mod outer {
//!

View File

@ -1,5 +1,5 @@
error: empty doc comment
--> tests/ui/empty_docs.rs:4:5
--> tests/ui/empty_docs.rs:6:5
|
LL | //!
| ^^^
@ -9,7 +9,7 @@ LL | //!
= help: to override `-D warnings` add `#[allow(clippy::empty_docs)]`
error: empty doc comment
--> tests/ui/empty_docs.rs:12:5
--> tests/ui/empty_docs.rs:14:5
|
LL | ///
| ^^^
@ -17,7 +17,7 @@ LL | ///
= help: consider removing or filling it
error: empty doc comment
--> tests/ui/empty_docs.rs:14:9
--> tests/ui/empty_docs.rs:16:9
|
LL | ///
| ^^^
@ -25,7 +25,7 @@ LL | ///
= help: consider removing or filling it
error: empty doc comment
--> tests/ui/empty_docs.rs:25:5
--> tests/ui/empty_docs.rs:27:5
|
LL | #[doc = ""]
| ^^^^^^^^^^^
@ -33,7 +33,7 @@ LL | #[doc = ""]
= help: consider removing or filling it
error: empty doc comment
--> tests/ui/empty_docs.rs:28:5
--> tests/ui/empty_docs.rs:30:5
|
LL | / #[doc = ""]
LL | | #[doc = ""]
@ -42,7 +42,7 @@ LL | | #[doc = ""]
= help: consider removing or filling it
error: empty doc comment
--> tests/ui/empty_docs.rs:35:5
--> tests/ui/empty_docs.rs:37:5
|
LL | ///
| ^^^
@ -50,7 +50,7 @@ LL | ///
= help: consider removing or filling it
error: empty doc comment
--> tests/ui/empty_docs.rs:48:13
--> tests/ui/empty_docs.rs:50:13
|
LL | /*! */
| ^^^^^^
@ -58,7 +58,7 @@ LL | /*! */
= help: consider removing or filling it
error: empty doc comment
--> tests/ui/empty_docs.rs:56:13
--> tests/ui/empty_docs.rs:58:13
|
LL | ///
| ^^^
@ -66,7 +66,7 @@ LL | ///
= help: consider removing or filling it
error: empty doc comment
--> tests/ui/empty_docs.rs:64:9
--> tests/ui/empty_docs.rs:66:9
|
LL | ///
| ^^^

View File

@ -0,0 +1,39 @@
#![warn(clippy::mixed_attributes_style)]
#[allow(unused)] //~ ERROR: item has both inner and outer attributes
fn foo1() {
#![allow(unused)]
}
#[allow(unused)]
#[allow(unused)]
fn foo2() {}
fn foo3() {
#![allow(unused)]
#![allow(unused)]
}
/// linux
//~^ ERROR: item has both inner and outer attributes
fn foo4() {
//! windows
}
/// linux
/// windows
fn foo5() {}
fn foo6() {
//! linux
//! windows
}
#[allow(unused)] //~ ERROR: item has both inner and outer attributes
mod bar {
#![allow(unused)]
}
fn main() {
// test code goes here
}

View File

@ -0,0 +1,30 @@
error: item has both inner and outer attributes
--> tests/ui/mixed_attributes_style.rs:3:1
|
LL | / #[allow(unused)]
LL | | fn foo1() {
LL | | #![allow(unused)]
| |_____________________^
|
= note: `-D clippy::mixed-attributes-style` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::mixed_attributes_style)]`
error: item has both inner and outer attributes
--> tests/ui/mixed_attributes_style.rs:17:1
|
LL | / /// linux
LL | |
LL | | fn foo4() {
LL | | //! windows
| |_______________^
error: item has both inner and outer attributes
--> tests/ui/mixed_attributes_style.rs:32:1
|
LL | / #[allow(unused)]
LL | | mod bar {
LL | | #![allow(unused)]
| |_____________________^
error: aborting due to 3 previous errors