Skip to content

Commit ae90357

Browse files
Add unneeded_clippy_cfg_attr lint
1 parent 32c006c commit ae90357

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -5746,6 +5746,7 @@ Released 2018-09-13
57465746
[`unnecessary_to_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_to_owned
57475747
[`unnecessary_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_unwrap
57485748
[`unnecessary_wraps`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_wraps
5749+
[`unnecessary_clippy_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_clippy_cfg
57495750
[`unneeded_field_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_field_pattern
57505751
[`unneeded_wildcard_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#unneeded_wildcard_pattern
57515752
[`unnested_or_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns

clippy_lints/src/attrs.rs

+93-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
//! checks for attributes
22
33
use clippy_config::msrvs::{self, Msrv};
4-
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
4+
use clippy_utils::diagnostics::{
5+
span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
6+
};
57
use clippy_utils::is_from_proc_macro;
68
use clippy_utils::macros::{is_panic, macro_backtrace};
79
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
@@ -459,6 +461,30 @@ declare_clippy_lint! {
459461
"usage of `cfg(feature = \"cargo-clippy\")` instead of `cfg(clippy)`"
460462
}
461463

464+
declare_clippy_lint! {
465+
/// ### What it does
466+
/// Checks for `#[cfg_attr(clippy, allow(clippy::lint))]` and for
467+
/// and suggests to replace it with `#[allow(clippy::lint)]`.
468+
///
469+
/// ### Why is this bad?
470+
/// There is no reason to put clippy attributes behind a clippy `cfg` as they are not
471+
/// run by anything else than clippy.
472+
///
473+
/// ### Example
474+
/// ```no_run
475+
/// #![cfg_attr(clippy, allow(clippy::deprecated_cfg_attr))]
476+
/// ```
477+
///
478+
/// Use instead:
479+
/// ```no_run
480+
/// #![allow(clippy::deprecated_cfg_attr)]
481+
/// ```
482+
#[clippy::version = "1.78.0"]
483+
pub UNNECESSARY_CLIPPY_CFG,
484+
suspicious,
485+
"usage of `cfg_attr(clippy, allow(clippy::lint))` instead of `allow(clippy::lint)`"
486+
}
487+
462488
declare_lint_pass!(Attributes => [
463489
ALLOW_ATTRIBUTES_WITHOUT_REASON,
464490
INLINE_ALWAYS,
@@ -821,6 +847,7 @@ impl_lint_pass!(EarlyAttributes => [
821847
NON_MINIMAL_CFG,
822848
MAYBE_MISUSED_CFG,
823849
DEPRECATED_CLIPPY_CFG_ATTR,
850+
UNNECESSARY_CLIPPY_CFG,
824851
]);
825852

826853
impl EarlyLintPass for EarlyAttributes {
@@ -958,6 +985,71 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr
958985
);
959986
} else {
960987
check_deprecated_cfg_recursively(cx, feature_item);
988+
if let Some(behind_cfg_attr) = items[1].meta_item() {
989+
check_clippy_cfg_attr(cx, feature_item, behind_cfg_attr, attr);
990+
}
991+
}
992+
}
993+
}
994+
995+
fn check_clippy_cfg_attr(
996+
cx: &EarlyContext<'_>,
997+
cfg_attr: &rustc_ast::MetaItem,
998+
behind_cfg_attr: &rustc_ast::MetaItem,
999+
attr: &Attribute,
1000+
) {
1001+
if cfg_attr.has_name(sym::clippy)
1002+
&& let Some(ident) = behind_cfg_attr.ident()
1003+
// FIXME: replace with `from_symbol` once https://github.com/rust-lang/rust/pull/121230
1004+
// is merged.
1005+
&& Level::from_str(ident.name.as_str()).is_some()
1006+
&& let Some(items) = behind_cfg_attr.meta_item_list()
1007+
{
1008+
let nb_items = items.len();
1009+
let mut clippy_lints = Vec::with_capacity(items.len());
1010+
for item in items {
1011+
if let Some(meta_item) = item.meta_item()
1012+
&& let [part1, _] = meta_item.path.segments.as_slice()
1013+
&& part1.ident.name == sym::clippy
1014+
{
1015+
clippy_lints.push(item.span());
1016+
}
1017+
}
1018+
if nb_items == clippy_lints.len() {
1019+
if let Some(snippet) = snippet_opt(cx, behind_cfg_attr.span) {
1020+
span_lint_and_sugg(
1021+
cx,
1022+
UNNECESSARY_CLIPPY_CFG,
1023+
attr.span,
1024+
"no need to put clippy lints behind a `clippy` cfg",
1025+
"replace with",
1026+
format!(
1027+
"#{}[{}]",
1028+
if attr.style == AttrStyle::Inner { "!" } else { "" },
1029+
snippet
1030+
),
1031+
Applicability::MachineApplicable,
1032+
);
1033+
}
1034+
} else {
1035+
let snippet = clippy_lints
1036+
.iter()
1037+
.filter_map(|sp| snippet_opt(cx, *sp))
1038+
.collect::<Vec<_>>()
1039+
.join(",");
1040+
span_lint_and_note(
1041+
cx,
1042+
UNNECESSARY_CLIPPY_CFG,
1043+
clippy_lints,
1044+
"no need to put clippy lints behind a `clippy` cfg",
1045+
None,
1046+
&format!(
1047+
"write instead: `#{}[{}({})]`",
1048+
if attr.style == AttrStyle::Inner { "!" } else { "" },
1049+
ident.name,
1050+
snippet
1051+
),
1052+
);
9611053
}
9621054
}
9631055
}

clippy_lints/src/declared_lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
6060
crate::attrs::MISMATCHED_TARGET_OS_INFO,
6161
crate::attrs::NON_MINIMAL_CFG_INFO,
6262
crate::attrs::SHOULD_PANIC_WITHOUT_EXPECT_INFO,
63+
crate::attrs::UNNECESSARY_CLIPPY_CFG_INFO,
6364
crate::attrs::USELESS_ATTRIBUTE_INFO,
6465
crate::await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE_INFO,
6566
crate::await_holding_invalid::AWAIT_HOLDING_LOCK_INFO,

0 commit comments

Comments
 (0)