1 use clippy_utils::{diagnostics::span_lint_and_then, source::snippet_opt};
2 use rustc_ast::ast::{Item, ItemKind, VariantData};
3 use rustc_errors::Applicability;
4 use rustc_lexer::TokenKind;
5 use rustc_lint::{EarlyContext, EarlyLintPass};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
11 /// Finds structs without fields (a so-called "empty struct") that are declared with brackets.
13 /// ### Why is this bad?
14 /// Empty brackets after a struct declaration can be omitted.
24 #[clippy::version = "1.62.0"]
25 pub EMPTY_STRUCTS_WITH_BRACKETS,
27 "finds struct declarations with empty brackets"
29 declare_lint_pass!(EmptyStructsWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS]);
31 impl EarlyLintPass for EmptyStructsWithBrackets {
32 fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
33 let span_after_ident = item.span.with_lo(item.ident.span.hi());
35 if let ItemKind::Struct(var_data, _) = &item.kind
36 && has_brackets(var_data)
37 && has_no_fields(cx, var_data, span_after_ident) {
40 EMPTY_STRUCTS_WITH_BRACKETS,
42 "found empty brackets on struct declaration",
44 diagnostic.span_suggestion_hidden(
46 "remove the brackets",
48 Applicability::MachineApplicable);
55 fn has_no_ident_token(braces_span_str: &str) -> bool {
56 !rustc_lexer::tokenize(braces_span_str).any(|t| t.kind == TokenKind::Ident)
59 fn has_brackets(var_data: &VariantData) -> bool {
60 !matches!(var_data, VariantData::Unit(_))
63 fn has_no_fields(cx: &EarlyContext<'_>, var_data: &VariantData, braces_span: Span) -> bool {
64 if !var_data.fields().is_empty() {
68 // there might still be field declarations hidden from the AST
69 // (conditionally compiled code using #[cfg(..)])
71 let Some(braces_span_str) = snippet_opt(cx, braces_span) else {
75 has_no_ident_token(braces_span_str.as_ref())
83 fn test_has_no_ident_token() {
84 let input = "{ field: u8 }";
85 assert!(!has_no_ident_token(input));
87 let input = "(u8, String);";
88 assert!(!has_no_ident_token(input));
94 assert!(has_no_ident_token(input));
97 assert!(has_no_ident_token(input));