Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New lint: empty_enum_variants_with_brackets #12033

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5105,6 +5105,7 @@ Released 2018-09-13
[`else_if_without_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#else_if_without_else
[`empty_drop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_drop
[`empty_enum`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum
[`empty_enum_variants_with_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_enum_variants_with_brackets
[`empty_line_after_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_doc_comments
[`empty_line_after_outer_attr`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_line_after_outer_attr
[`empty_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#empty_loop
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::else_if_without_else::ELSE_IF_WITHOUT_ELSE_INFO,
crate::empty_drop::EMPTY_DROP_INFO,
crate::empty_enum::EMPTY_ENUM_INFO,
crate::empty_enum_variants_with_brackets::EMPTY_ENUM_VARIANTS_WITH_BRACKETS_INFO,
crate::empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS_INFO,
crate::endian_bytes::BIG_ENDIAN_BYTES_INFO,
crate::endian_bytes::HOST_ENDIAN_BYTES_INFO,
Expand Down
78 changes: 78 additions & 0 deletions clippy_lints/src/empty_enum_variants_with_brackets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_opt;
use rustc_ast::ast::{Variant, VariantData};
use rustc_errors::Applicability;
use rustc_lexer::TokenKind;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::Span;

declare_clippy_lint! {
/// ### What it does
/// Finds enum variants without fields that are declared with brackets.
/// ### Why is this bad?
/// Empty brackets while defining enum variants are redundant and can be omitted.
/// ### Example
/// ```no_run
/// enum Season {
/// Summer(), // redundant parentheses
/// Winter{}, // redundant braces
/// Spring
/// }
/// ```
/// Use instead:
/// ```no_run
/// enum Season {
/// Summer,
/// Winter,
/// Spring
/// }
/// ```
#[clippy::version = "1.76.0"]
pub EMPTY_ENUM_VARIANTS_WITH_BRACKETS,
restriction,
"enum variant has empty body with redundant brackets"
}

declare_lint_pass!(EmptyEnumVariantsWithBrackets => [EMPTY_ENUM_VARIANTS_WITH_BRACKETS]);

impl EarlyLintPass for EmptyEnumVariantsWithBrackets {
fn check_variant(&mut self, cx: &EarlyContext<'_>, variant: &Variant) {
let span_after_ident = variant.span.with_lo(variant.ident.span.hi());
if has_brackets(&variant.data) && has_no_fields(cx, &variant.data, span_after_ident) {
span_lint_and_then(
cx,
EMPTY_ENUM_VARIANTS_WITH_BRACKETS,
span_after_ident,
"enum variant with brackets has empty body",
|diagnostic| {
diagnostic.span_suggestion_hidden(
span_after_ident,
"remove the brackets",
"",
Applicability::MachineApplicable,
);
},
);
}
}
}

fn has_brackets(var_data: &VariantData) -> bool {
!matches!(var_data, VariantData::Unit(_))
}

fn has_no_fields(cx: &EarlyContext<'_>, var_data: &VariantData, braces_span: Span) -> bool {
if !var_data.fields().is_empty() {
return false;
}
let Some(braces_span_str) = snippet_opt(cx, braces_span) else {
return false;
};

has_no_ident_token(braces_span_str.as_ref())
}

fn has_no_ident_token(braces_span_str: &str) -> bool {
!rustc_lexer::tokenize(braces_span_str).any(|t| t.kind == TokenKind::Ident)
}
2 changes: 2 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ mod duplicate_mod;
mod else_if_without_else;
mod empty_drop;
mod empty_enum;
mod empty_enum_variants_with_brackets;
mod empty_structs_with_brackets;
mod endian_bytes;
mod entry;
Expand Down Expand Up @@ -1081,6 +1082,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(|_| Box::new(uninhabited_references::UninhabitedReferences));
store.register_late_pass(|_| Box::new(ineffective_open_options::IneffectiveOpenOptions));
store.register_late_pass(|_| Box::new(unconditional_recursion::UnconditionalRecursion));
store.register_early_pass(|| Box::new(empty_enum_variants_with_brackets::EmptyEnumVariantsWithBrackets));
// add lints here, do not remove this comment, it's used in `new_lint`
}

Expand Down
24 changes: 24 additions & 0 deletions tests/ui/empty_enum_variants_with_brackets.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#![warn(clippy::empty_enum_variants_with_brackets)]

enum TestEnum {
// These two enums should not trigger the lint.
NonEmptyBrace { x: i32, y: i32 },
NonEmptyParentheses(i32, i32),

// Enum variant with braces and no data
EmptyBrace, //~ ERROR: enum variant with brackets has empty body

// Enum variant with parentheses and no data
EmptyParentheses, //~ ERROR: enum variant with brackets has empty body
}

enum TestEnumWithFeature {
// These two enums should not trigger the lint.
NonEmptyBrace {
#[cfg(feature = "thisisneverenabled")]
x: i32,
},
NonEmptyParentheses(#[cfg(feature = "thisisneverenabled")] i32),
}

fn main() {}
24 changes: 24 additions & 0 deletions tests/ui/empty_enum_variants_with_brackets.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#![warn(clippy::empty_enum_variants_with_brackets)]

enum TestEnum {
// These two enums should not trigger the lint.
NonEmptyBrace { x: i32, y: i32 },
NonEmptyParentheses(i32, i32),

// Enum variant with braces and no data
EmptyBrace {}, //~ ERROR: enum variant with brackets has empty body

// Enum variant with parentheses and no data
EmptyParentheses(), //~ ERROR: enum variant with brackets has empty body
}

enum TestEnumWithFeature {
// These two enums should not trigger the lint.
NonEmptyBrace {
#[cfg(feature = "thisisneverenabled")]
x: i32,
},
NonEmptyParentheses(#[cfg(feature = "thisisneverenabled")] i32),
}

fn main() {}
20 changes: 20 additions & 0 deletions tests/ui/empty_enum_variants_with_brackets.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: enum variant with brackets has empty body
--> $DIR/empty_enum_variants_with_brackets.rs:9:15
|
LL | EmptyBrace {},
| ^^^
|
= note: `-D clippy::empty-enum-variants-with-brackets` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::empty_enum_variants_with_brackets)]`
= help: remove the brackets

error: enum variant with brackets has empty body
--> $DIR/empty_enum_variants_with_brackets.rs:12:21
|
LL | EmptyParentheses(),
| ^^
|
= help: remove the brackets

error: aborting due to 2 previous errors