-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathpartial_pub_fields.rs
74 lines (69 loc) · 2.48 KB
/
partial_pub_fields.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::ast::{Item, ItemKind};
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::declare_lint_pass;
declare_clippy_lint! {
/// ### What it does
/// Checks whether some but not all fields of a `struct` are public.
///
/// Either make all fields of a type public, or make none of them public
///
/// ### Why restrict this?
/// 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,
/// but have no invariants.
///
/// ### Example
/// ```no_run
/// pub struct Color {
/// pub r: u8,
/// pub g: u8,
/// b: u8,
/// }
/// ```
/// Use instead:
/// ```no_run
/// 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() {
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(cx, PARTIAL_PUB_FIELDS, field.vis.span, msg, |diag| {
diag.help("consider using private field here");
});
return;
} else if all_pub && !field.vis.kind.is_pub() {
#[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
span_lint_and_then(cx, PARTIAL_PUB_FIELDS, field.vis.span, msg, |diag| {
diag.help("consider using public field here");
});
return;
}
}
}
}