summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/partial_pub_fields.rs')
-rw-r--r--src/tools/clippy/clippy_lints/src/partial_pub_fields.rs81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
new file mode 100644
index 000000000..f60d9d65b
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
@@ -0,0 +1,81 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use rustc_ast::ast::{Item, ItemKind};
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks whether partial fields of a struct are public.
+ ///
+ /// Either make all fields of a type public, or make none of them public
+ ///
+ /// ### Why is this bad?
+ /// Most types should either be:
+ /// * Abstract data types: complex objects with opaque implementation which guard
+ /// interior invariants and expose intentionally limited API to the outside world.
+ /// * Data: relatively simple objects which group a bunch of related attributes together.
+ ///
+ /// ### Example
+ /// ```rust
+ /// pub struct Color {
+ /// pub r: u8,
+ /// pub g: u8,
+ /// b: u8,
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// pub struct Color {
+ /// pub r: u8,
+ /// pub g: u8,
+ /// pub b: u8,
+ /// }
+ /// ```
+ #[clippy::version = "1.66.0"]
+ pub PARTIAL_PUB_FIELDS,
+ restriction,
+ "partial fields of a struct are public"
+}
+declare_lint_pass!(PartialPubFields => [PARTIAL_PUB_FIELDS]);
+
+impl EarlyLintPass for PartialPubFields {
+ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
+ let ItemKind::Struct(ref st, _) = item.kind else {
+ return;
+ };
+
+ let mut fields = st.fields().iter();
+ let Some(first_field) = fields.next() else {
+ // Empty struct.
+ return;
+ };
+ let all_pub = first_field.vis.kind.is_pub();
+ let all_priv = !all_pub;
+
+ let msg = "mixed usage of pub and non-pub fields";
+
+ for field in fields {
+ if all_priv && field.vis.kind.is_pub() {
+ span_lint_and_help(
+ cx,
+ PARTIAL_PUB_FIELDS,
+ field.vis.span,
+ msg,
+ None,
+ "consider using private field here",
+ );
+ return;
+ } else if all_pub && !field.vis.kind.is_pub() {
+ span_lint_and_help(
+ cx,
+ PARTIAL_PUB_FIELDS,
+ field.vis.span,
+ msg,
+ None,
+ "consider using public field here",
+ );
+ return;
+ }
+ }
+ }
+}