Skip to content

Commit 6571681

Browse files
Add new UNIQUE_CFG_CONDITION lint
1 parent d696f3b commit 6571681

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

Diff for: clippy_lints/src/attrs.rs

+60
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,30 @@ declare_clippy_lint! {
292292
"ensures that all `allow` and `expect` attributes have a reason"
293293
}
294294

295+
declare_clippy_lint! {
296+
/// ### What it does
297+
/// Checks for `any` and `all` combinators in `cfg` with only one condition.
298+
///
299+
/// ### Why is this bad?
300+
/// If there is only one condition, no need to wrap it into `any` or `all` combinators.
301+
///
302+
/// ### Example
303+
/// ```rust
304+
/// #[cfg(any(unix))]
305+
/// pub struct Bar;
306+
/// ```
307+
///
308+
/// Use instead:
309+
/// ```rust
310+
/// #[cfg(unix)]
311+
/// pub struct Bar;
312+
/// ```
313+
#[clippy::version = "1.71.0"]
314+
pub UNIQUE_CFG_CONDITION,
315+
style,
316+
"ensure that all `cfg(any())` and `cfg(all())` have more than one condition"
317+
}
318+
295319
declare_lint_pass!(Attributes => [
296320
ALLOW_ATTRIBUTES_WITHOUT_REASON,
297321
INLINE_ALWAYS,
@@ -604,6 +628,7 @@ impl_lint_pass!(EarlyAttributes => [
604628
DEPRECATED_CFG_ATTR,
605629
MISMATCHED_TARGET_OS,
606630
EMPTY_LINE_AFTER_OUTER_ATTR,
631+
UNIQUE_CFG_CONDITION,
607632
]);
608633

609634
impl EarlyLintPass for EarlyAttributes {
@@ -614,6 +639,7 @@ impl EarlyLintPass for EarlyAttributes {
614639
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
615640
check_deprecated_cfg_attr(cx, attr, &self.msrv);
616641
check_mismatched_target_os(cx, attr);
642+
check_unique_cfg_condition(cx, attr);
617643
}
618644

619645
extract_msrv_attr!(EarlyContext);
@@ -690,6 +716,40 @@ fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msr
690716
}
691717
}
692718

719+
fn check_nested_cfg(cx: &EarlyContext<'_>, items: &[NestedMetaItem]) {
720+
for item in items.iter() {
721+
if let NestedMetaItem::MetaItem(meta) = item {
722+
if !meta.has_name(sym::any) && !meta.has_name(sym::all) {
723+
continue;
724+
}
725+
if let MetaItemKind::List(list) = &meta.kind {
726+
check_nested_cfg(cx, list);
727+
if list.len() == 1 {
728+
span_lint_and_then(
729+
cx,
730+
UNIQUE_CFG_CONDITION,
731+
meta.span,
732+
"unneeded sub `cfg` when there is only one condition",
733+
|diag| {
734+
if let Some(snippet) = snippet_opt(cx, list[0].span()) {
735+
diag.span_suggestion(meta.span, "try", snippet, Applicability::MaybeIncorrect);
736+
}
737+
},
738+
);
739+
}
740+
}
741+
}
742+
}
743+
}
744+
745+
fn check_unique_cfg_condition(cx: &EarlyContext<'_>, attr: &Attribute) {
746+
if attr.has_name(sym::cfg) &&
747+
let Some(items) = attr.meta_item_list()
748+
{
749+
check_nested_cfg(cx, &items);
750+
}
751+
}
752+
693753
fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
694754
fn find_os(name: &str) -> Option<&'static str> {
695755
UNIX_SYSTEMS

Diff for: clippy_lints/src/declared_lints.rs

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
5151
crate::attrs::EMPTY_LINE_AFTER_OUTER_ATTR_INFO,
5252
crate::attrs::INLINE_ALWAYS_INFO,
5353
crate::attrs::MISMATCHED_TARGET_OS_INFO,
54+
crate::attrs::UNIQUE_CFG_CONDITION_INFO,
5455
crate::attrs::USELESS_ATTRIBUTE_INFO,
5556
crate::await_holding_invalid::AWAIT_HOLDING_INVALID_TYPE_INFO,
5657
crate::await_holding_invalid::AWAIT_HOLDING_LOCK_INFO,

0 commit comments

Comments
 (0)