Add new duplicated_attributes
lint
This commit is contained in:
parent
453242cbde
commit
f34804d807
@ -5157,6 +5157,7 @@ Released 2018-09-13
|
||||
[`drop_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#drop_ref
|
||||
[`duplicate_mod`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_mod
|
||||
[`duplicate_underscore_argument`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicate_underscore_argument
|
||||
[`duplicated_attributes`]: https://rust-lang.github.io/rust-clippy/master/index.html#duplicated_attributes
|
||||
[`duration_subsec`]: https://rust-lang.github.io/rust-clippy/master/index.html#duration_subsec
|
||||
[`eager_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#eager_transmute
|
||||
[`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
|
||||
|
64
clippy_lints/src/attrs/duplicated_attributes.rs
Normal file
64
clippy_lints/src/attrs/duplicated_attributes.rs
Normal file
@ -0,0 +1,64 @@
|
||||
use super::DUPLICATED_ATTRIBUTES;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use rustc_ast::{Attribute, MetaItem};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::{sym, Span};
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
fn emit_if_duplicated(
|
||||
cx: &EarlyContext<'_>,
|
||||
attr: &MetaItem,
|
||||
attr_paths: &mut FxHashMap<String, Span>,
|
||||
complete_path: String,
|
||||
) {
|
||||
match attr_paths.entry(complete_path) {
|
||||
Entry::Vacant(v) => {
|
||||
v.insert(attr.span);
|
||||
},
|
||||
Entry::Occupied(o) => {
|
||||
span_lint_and_then(cx, DUPLICATED_ATTRIBUTES, attr.span, "duplicated attribute", |diag| {
|
||||
diag.span_note(*o.get(), "first defined here");
|
||||
diag.span_help(attr.span, "remove this attribute");
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn check_duplicated_attr(
|
||||
cx: &EarlyContext<'_>,
|
||||
attr: &MetaItem,
|
||||
attr_paths: &mut FxHashMap<String, Span>,
|
||||
parent: &mut Vec<String>,
|
||||
) {
|
||||
let Some(ident) = attr.ident() else { return };
|
||||
let name = ident.name;
|
||||
if name == sym::doc || name == sym::cfg_attr {
|
||||
// FIXME: Would be nice to handle `cfg_attr` as well. Only problem is to check that cfg
|
||||
// conditions are the same.
|
||||
return;
|
||||
}
|
||||
if let Some(value) = attr.value_str() {
|
||||
emit_if_duplicated(cx, attr, attr_paths, format!("{}:{name}={value}", parent.join(":")));
|
||||
} else if let Some(sub_attrs) = attr.meta_item_list() {
|
||||
parent.push(name.as_str().to_string());
|
||||
for sub_attr in sub_attrs {
|
||||
if let Some(meta) = sub_attr.meta_item() {
|
||||
check_duplicated_attr(cx, meta, attr_paths, parent);
|
||||
}
|
||||
}
|
||||
parent.pop();
|
||||
} else {
|
||||
emit_if_duplicated(cx, attr, attr_paths, format!("{}:{name}", parent.join(":")));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
|
||||
let mut attr_paths = FxHashMap::default();
|
||||
|
||||
for attr in attrs {
|
||||
if let Some(meta) = attr.meta() {
|
||||
check_duplicated_attr(cx, &meta, &mut attr_paths, &mut Vec::new());
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
mod blanket_clippy_restriction_lints;
|
||||
mod deprecated_cfg_attr;
|
||||
mod deprecated_semver;
|
||||
mod duplicated_attributes;
|
||||
mod empty_line_after;
|
||||
mod inline_always;
|
||||
mod maybe_misused_cfg;
|
||||
@ -16,7 +17,7 @@
|
||||
mod utils;
|
||||
|
||||
use clippy_config::msrvs::Msrv;
|
||||
use rustc_ast::{Attribute, MetaItemKind, NestedMetaItem};
|
||||
use rustc_ast::{Attribute, Crate, MetaItemKind, NestedMetaItem};
|
||||
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, impl_lint_pass};
|
||||
@ -489,6 +490,32 @@
|
||||
"item has both inner and outer attributes"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for attributes that appear two or more times.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Repeating an attribute on the same item (or globally on the same crate)
|
||||
/// is unnecessary and doesn't have an effect.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```no_run
|
||||
/// #[allow(dead_code)]
|
||||
/// #[allow(dead_code)]
|
||||
/// fn foo() {}
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```no_run
|
||||
/// #[allow(dead_code)]
|
||||
/// fn foo() {}
|
||||
/// ```
|
||||
#[clippy::version = "1.78.0"]
|
||||
pub DUPLICATED_ATTRIBUTES,
|
||||
suspicious,
|
||||
"duplicated attribute"
|
||||
}
|
||||
|
||||
declare_lint_pass!(Attributes => [
|
||||
ALLOW_ATTRIBUTES_WITHOUT_REASON,
|
||||
INLINE_ALWAYS,
|
||||
@ -568,12 +595,18 @@ pub struct EarlyAttributes {
|
||||
DEPRECATED_CLIPPY_CFG_ATTR,
|
||||
UNNECESSARY_CLIPPY_CFG,
|
||||
MIXED_ATTRIBUTES_STYLE,
|
||||
DUPLICATED_ATTRIBUTES,
|
||||
]);
|
||||
|
||||
impl EarlyLintPass for EarlyAttributes {
|
||||
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
|
||||
duplicated_attributes::check(cx, &krate.attrs);
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &rustc_ast::Item) {
|
||||
empty_line_after::check(cx, item);
|
||||
mixed_attributes_style::check(cx, item);
|
||||
duplicated_attributes::check(cx, &item.attrs);
|
||||
}
|
||||
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
|
@ -54,6 +54,7 @@
|
||||
crate::attrs::DEPRECATED_CFG_ATTR_INFO,
|
||||
crate::attrs::DEPRECATED_CLIPPY_CFG_ATTR_INFO,
|
||||
crate::attrs::DEPRECATED_SEMVER_INFO,
|
||||
crate::attrs::DUPLICATED_ATTRIBUTES_INFO,
|
||||
crate::attrs::EMPTY_LINE_AFTER_DOC_COMMENTS_INFO,
|
||||
crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
|
||||
crate::attrs::INLINE_ALWAYS_INFO,
|
||||
|
Loading…
Reference in New Issue
Block a user