about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_lints/src/lib.register_all.rs1
-rw-r--r--clippy_lints/src/lib.register_lints.rs1
-rw-r--r--clippy_lints/src/lib.register_style.rs1
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--clippy_lints/src/unit_like_struct_brackets.rs53
-rw-r--r--tests/ui/unit_like_struct_brackets.fixed13
-rw-r--r--tests/ui/unit_like_struct_brackets.rs13
-rw-r--r--tests/ui/unit_like_struct_brackets.stderr16
9 files changed, 101 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1d1e081e839..49a44d98813 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3636,6 +3636,7 @@ Released 2018-09-13
 [`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg
 [`unit_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_cmp
 [`unit_hash`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_hash
+[`unit_like_struct_brackets`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_like_struct_brackets
 [`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_return_expecting_ord
 [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_cast
 [`unnecessary_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_filter_map
diff --git a/clippy_lints/src/lib.register_all.rs b/clippy_lints/src/lib.register_all.rs
index 1fb3ca1fd9b..f488aab46ec 100644
--- a/clippy_lints/src/lib.register_all.rs
+++ b/clippy_lints/src/lib.register_all.rs
@@ -301,6 +301,7 @@ 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 e3161795139..a1e6ca76a16 100644
--- a/clippy_lints/src/lib.register_lints.rs
+++ b/clippy_lints/src/lib.register_lints.rs
@@ -512,6 +512,7 @@ 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 dcf399cf956..89657cfb784 100644
--- a/clippy_lints/src/lib.register_style.rs
+++ b/clippy_lints/src/lib.register_style.rs
@@ -105,6 +105,7 @@ 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 c8b57956b1b..af8d9b3655c 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -380,6 +380,7 @@ 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;
@@ -869,6 +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));
     // 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
new file mode 100644
index 00000000000..0eeb765be85
--- /dev/null
+++ b/clippy_lints/src/unit_like_struct_brackets.rs
@@ -0,0 +1,53 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use rustc_ast::ast::*;
+use rustc_errors::Applicability;
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+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.61.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) {
+        if let ItemKind::Struct(var_data, _) = &item.kind && has_no_fields(var_data) {
+            let span_after_ident = item.span.with_lo(item.ident.span.hi());
+
+            span_lint_and_sugg(
+                cx,
+                UNIT_LIKE_STRUCT_BRACKETS,
+                span_after_ident,
+                "found empty brackets on struct declaration",
+                "remove the brackets",
+                ";".to_string(),
+                Applicability::MachineApplicable
+            );
+        }
+    }
+}
+
+fn has_no_fields(var_data: &VariantData) -> bool {
+    match var_data {
+        VariantData::Struct(defs, _) => defs.is_empty(),
+        VariantData::Tuple(defs, _) => defs.is_empty(),
+        VariantData::Unit(_) => false,
+    }
+}
diff --git a/tests/ui/unit_like_struct_brackets.fixed b/tests/ui/unit_like_struct_brackets.fixed
new file mode 100644
index 00000000000..a69c310e973
--- /dev/null
+++ b/tests/ui/unit_like_struct_brackets.fixed
@@ -0,0 +1,13 @@
+// run-rustfix
+#![warn(clippy::unit_like_struct_brackets)]
+#![allow(dead_code)]
+
+pub struct MyEmptyStruct;             // should trigger lint
+struct MyEmptyTupleStruct;            // should trigger lint
+
+struct MyStruct {                       // should not trigger lint
+    field: u8,
+}
+struct MyTupleStruct(usize, String);    // should not trigger lint
+
+fn main() {}
diff --git a/tests/ui/unit_like_struct_brackets.rs b/tests/ui/unit_like_struct_brackets.rs
new file mode 100644
index 00000000000..8697a24f1d7
--- /dev/null
+++ b/tests/ui/unit_like_struct_brackets.rs
@@ -0,0 +1,13 @@
+// run-rustfix
+#![warn(clippy::unit_like_struct_brackets)]
+#![allow(dead_code)]
+
+pub struct MyEmptyStruct {}             // should trigger lint
+struct MyEmptyTupleStruct();            // should trigger lint
+
+struct MyStruct {                       // should not trigger lint
+    field: u8,
+}
+struct MyTupleStruct(usize, String);    // should not trigger lint
+
+fn main() {}
diff --git a/tests/ui/unit_like_struct_brackets.stderr b/tests/ui/unit_like_struct_brackets.stderr
new file mode 100644
index 00000000000..146ede19c07
--- /dev/null
+++ b/tests/ui/unit_like_struct_brackets.stderr
@@ -0,0 +1,16 @@
+error: found empty brackets on struct declaration
+  --> $DIR/unit_like_struct_brackets.rs:5:25
+   |
+LL | pub struct MyEmptyStruct {}             // should trigger lint
+   |                         ^^^ help: remove the brackets: `;`
+   |
+   = note: `-D clippy::unit-like-struct-brackets` implied by `-D warnings`
+
+error: found empty brackets on struct declaration
+  --> $DIR/unit_like_struct_brackets.rs:6:26
+   |
+LL | struct MyEmptyTupleStruct();            // should trigger lint
+   |                          ^^^ help: remove the brackets: `;`
+
+error: aborting due to 2 previous errors
+