From 2953cba1160cb4dd8fe4923a4e9166b3ca6867f1 Mon Sep 17 00:00:00 2001 From: Max Baumann Date: Mon, 28 Mar 2022 11:35:43 +0200 Subject: unit_like_struct_brackets -> empty_structs_with_brackets --- clippy_lints/src/empty_structs_with_brackets.rs | 99 +++++++++++++++++++++++++ clippy_lints/src/lib.register_all.rs | 2 +- clippy_lints/src/lib.register_lints.rs | 2 +- clippy_lints/src/lib.register_style.rs | 2 +- clippy_lints/src/lib.rs | 4 +- clippy_lints/src/unit_like_struct_brackets.rs | 99 ------------------------- 6 files changed, 104 insertions(+), 104 deletions(-) create mode 100644 clippy_lints/src/empty_structs_with_brackets.rs delete mode 100644 clippy_lints/src/unit_like_struct_brackets.rs (limited to 'clippy_lints/src') diff --git a/clippy_lints/src/empty_structs_with_brackets.rs b/clippy_lints/src/empty_structs_with_brackets.rs new file mode 100644 index 00000000000..e3f33c1a4a3 --- /dev/null +++ b/clippy_lints/src/empty_structs_with_brackets.rs @@ -0,0 +1,99 @@ +use clippy_utils::{diagnostics::span_lint_and_then, source::snippet_opt}; +use rustc_ast::ast::{Item, ItemKind, VariantData}; +use rustc_errors::Applicability; +use rustc_lexer::TokenKind; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Span; + +declare_clippy_lint! { + /// ### What it does + /// Finds structs without fields ("unit-like structs") that are declared with brackets. + /// + /// ### Why is this bad? + /// Empty brackets after a struct declaration can be omitted. + /// + /// ### Example + /// ```rust + /// struct Cookie {} + /// ``` + /// Use instead: + /// ```rust + /// struct Cookie; + /// ``` + #[clippy::version = "1.62.0"] + pub EMPTY_STRUCTS_WITH_BRACKETS, + style, + "finds struct declarations with empty brackets" +} +declare_lint_pass!(EmptyStructsWithBrackets => [EMPTY_STRUCTS_WITH_BRACKETS]); + +impl EarlyLintPass for EmptyStructsWithBrackets { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + let span_after_ident = item.span.with_lo(item.ident.span.hi()); + + if let ItemKind::Struct(var_data, _) = &item.kind + && !is_unit_like_struct(var_data) + && has_no_fields(cx, var_data, span_after_ident) { + span_lint_and_then( + cx, + EMPTY_STRUCTS_WITH_BRACKETS, + span_after_ident, + "found empty brackets on struct declaration", + |diagnostic| { + diagnostic.span_suggestion_hidden( + span_after_ident, + "remove the brackets", + ";".to_string(), + Applicability::MachineApplicable); + }, + ); + } + } +} + +fn has_no_ident_token(braces_span_str: &str) -> bool { + !rustc_lexer::tokenize(braces_span_str).any(|t| t.kind == TokenKind::Ident) +} + +fn is_unit_like_struct(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; + } + + // there might still be field declarations hidden from the AST + // (conditionaly compiled code using #[cfg(..)]) + + let Some(braces_span_str) = snippet_opt(cx, braces_span) else { + return false; + }; + + has_no_ident_token(braces_span_str.as_ref()) +} + +#[cfg(test)] +mod unit_test { + use super::*; + + #[test] + fn test_has_no_ident_token() { + let input = "{ field: u8 }"; + assert!(!has_no_ident_token(input)); + + let input = "(u8, String);"; + assert!(!has_no_ident_token(input)); + + let input = " { + // test = 5 + } + "; + assert!(has_no_ident_token(input)); + + let input = " ();"; + assert!(has_no_ident_token(input)); + } +} diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs index f488aab46ec..bdad518a3e8 100644 --- a/clippy_lints/src/lib.register_all.rs +++ b/clippy_lints/src/lib.register_all.rs @@ -54,6 +54,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(drop_forget_ref::FORGET_COPY), LintId::of(drop_forget_ref::FORGET_REF), LintId::of(duration_subsec::DURATION_SUBSEC), + LintId::of(empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS), LintId::of(entry::MAP_ENTRY), LintId::of(enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT), LintId::of(enum_variants::ENUM_VARIANT_NAMES), @@ -301,7 +302,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![ LintId::of(unicode::INVISIBLE_CHARACTERS), LintId::of(uninit_vec::UNINIT_VEC), LintId::of(unit_hash::UNIT_HASH), - LintId::of(unit_like_struct_brackets::UNIT_LIKE_STRUCT_BRACKETS), LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD), LintId::of(unit_types::UNIT_ARG), LintId::of(unit_types::UNIT_CMP), diff --git a/clippy_lints/src/lib.register_lints.rs b/clippy_lints/src/lib.register_lints.rs index a1e6ca76a16..bba3cae45f5 100644 --- a/clippy_lints/src/lib.register_lints.rs +++ b/clippy_lints/src/lib.register_lints.rs @@ -129,6 +129,7 @@ store.register_lints(&[ duration_subsec::DURATION_SUBSEC, else_if_without_else::ELSE_IF_WITHOUT_ELSE, empty_enum::EMPTY_ENUM, + empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS, entry::MAP_ENTRY, enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT, enum_variants::ENUM_VARIANT_NAMES, @@ -512,7 +513,6 @@ store.register_lints(&[ unicode::UNICODE_NOT_NFC, uninit_vec::UNINIT_VEC, unit_hash::UNIT_HASH, - unit_like_struct_brackets::UNIT_LIKE_STRUCT_BRACKETS, unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD, unit_types::LET_UNIT_VALUE, unit_types::UNIT_ARG, diff --git a/clippy_lints/src/lib.register_style.rs b/clippy_lints/src/lib.register_style.rs index 89657cfb784..b2465d1a0cd 100644 --- a/clippy_lints/src/lib.register_style.rs +++ b/clippy_lints/src/lib.register_style.rs @@ -20,6 +20,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(disallowed_types::DISALLOWED_TYPES), LintId::of(doc::MISSING_SAFETY_DOC), LintId::of(doc::NEEDLESS_DOCTEST_MAIN), + LintId::of(empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS), LintId::of(enum_variants::ENUM_VARIANT_NAMES), LintId::of(enum_variants::MODULE_INCEPTION), LintId::of(eq_op::OP_REF), @@ -105,7 +106,6 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![ LintId::of(single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS), LintId::of(tabs_in_doc_comments::TABS_IN_DOC_COMMENTS), LintId::of(to_digit_is_some::TO_DIGIT_IS_SOME), - LintId::of(unit_like_struct_brackets::UNIT_LIKE_STRUCT_BRACKETS), LintId::of(unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), LintId::of(unused_unit::UNUSED_UNIT), LintId::of(upper_case_acronyms::UPPER_CASE_ACRONYMS), diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index af8d9b3655c..3138ee9bce5 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -209,6 +209,7 @@ mod drop_forget_ref; mod duration_subsec; mod else_if_without_else; mod empty_enum; +mod empty_structs_with_brackets; mod entry; mod enum_clike; mod enum_variants; @@ -380,7 +381,6 @@ mod undropped_manually_drops; mod unicode; mod uninit_vec; mod unit_hash; -mod unit_like_struct_brackets; mod unit_return_expecting_ord; mod unit_types; mod unnamed_address; @@ -870,7 +870,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: }) }); store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef)); - store.register_early_pass(|| Box::new(unit_like_struct_brackets::UnitLikeStructBrackets)); + store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/unit_like_struct_brackets.rs b/clippy_lints/src/unit_like_struct_brackets.rs deleted file mode 100644 index 6269719e696..00000000000 --- a/clippy_lints/src/unit_like_struct_brackets.rs +++ /dev/null @@ -1,99 +0,0 @@ -use clippy_utils::{diagnostics::span_lint_and_then, source::snippet_opt}; -use rustc_ast::ast::{Item, ItemKind, VariantData}; -use rustc_errors::Applicability; -use rustc_lexer::TokenKind; -use rustc_lint::{EarlyContext, EarlyLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::Span; - -declare_clippy_lint! { - /// ### What it does - /// Finds structs without fields ("unit-like structs") that are declared with brackets. - /// - /// ### Why is this bad? - /// Empty brackets after a struct declaration can be omitted. - /// - /// ### Example - /// ```rust - /// struct Cookie {} - /// ``` - /// Use instead: - /// ```rust - /// struct Cookie; - /// ``` - #[clippy::version = "1.62.0"] - pub UNIT_LIKE_STRUCT_BRACKETS, - style, - "finds struct declarations with empty brackets" -} -declare_lint_pass!(UnitLikeStructBrackets => [UNIT_LIKE_STRUCT_BRACKETS]); - -impl EarlyLintPass for UnitLikeStructBrackets { - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - let span_after_ident = item.span.with_lo(item.ident.span.hi()); - - if let ItemKind::Struct(var_data, _) = &item.kind - && !is_unit_like_struct(var_data) - && has_no_fields(cx, var_data, span_after_ident) { - span_lint_and_then( - cx, - UNIT_LIKE_STRUCT_BRACKETS, - span_after_ident, - "found empty brackets on struct declaration", - |diagnostic| { - diagnostic.span_suggestion_hidden( - span_after_ident, - "remove the brackets", - ";".to_string(), - Applicability::MachineApplicable); - }, - ); - } - } -} - -fn has_no_ident_token(braces_span_str: &str) -> bool { - !rustc_lexer::tokenize(braces_span_str).any(|t| t.kind == TokenKind::Ident) -} - -fn is_unit_like_struct(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; - } - - // there might still be field declarations hidden from the AST - // (conditionaly compiled code using #[cfg(..)]) - - let Some(braces_span_str) = snippet_opt(cx, braces_span) else { - return false; - }; - - has_no_ident_token(braces_span_str.as_ref()) -} - -#[cfg(test)] -mod unit_test { - use super::*; - - #[test] - fn test_has_no_ident_token() { - let input = "{ field: u8 }"; - assert!(!has_no_ident_token(input)); - - let input = "(u8, String);"; - assert!(!has_no_ident_token(input)); - - let input = " { - // test = 5 - } - "; - assert!(has_no_ident_token(input)); - - let input = " ();"; - assert!(has_no_ident_token(input)); - } -} -- cgit 1.4.1-3-g733a5