74 lines
2.6 KiB
Rust
74 lines
2.6 KiB
Rust
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
|
|
use clippy_utils::source::snippet_opt;
|
|
use rustc_ast::ast::{Pat, PatKind};
|
|
use rustc_lint::EarlyContext;
|
|
|
|
use super::UNNEEDED_FIELD_PATTERN;
|
|
|
|
pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
|
|
if let PatKind::Struct(_, ref npat, ref pfields, _) = pat.kind {
|
|
let mut wilds = 0;
|
|
let type_name = npat
|
|
.segments
|
|
.last()
|
|
.expect("A path must have at least one segment")
|
|
.ident
|
|
.name;
|
|
|
|
for field in pfields {
|
|
if let PatKind::Wild = field.pat.kind {
|
|
wilds += 1;
|
|
}
|
|
}
|
|
if !pfields.is_empty() && wilds == pfields.len() {
|
|
span_lint_and_help(
|
|
cx,
|
|
UNNEEDED_FIELD_PATTERN,
|
|
pat.span,
|
|
"all the struct fields are matched to a wildcard pattern, consider using `..`",
|
|
None,
|
|
&format!("try with `{} {{ .. }}` instead", type_name),
|
|
);
|
|
return;
|
|
}
|
|
if wilds > 0 {
|
|
for field in pfields {
|
|
if let PatKind::Wild = field.pat.kind {
|
|
wilds -= 1;
|
|
if wilds > 0 {
|
|
span_lint(
|
|
cx,
|
|
UNNEEDED_FIELD_PATTERN,
|
|
field.span,
|
|
"you matched a field with a wildcard pattern, consider using `..` instead",
|
|
);
|
|
} else {
|
|
let mut normal = vec![];
|
|
|
|
for field in pfields {
|
|
match field.pat.kind {
|
|
PatKind::Wild => {},
|
|
_ => {
|
|
if let Some(n) = snippet_opt(cx, field.span) {
|
|
normal.push(n);
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
span_lint_and_help(
|
|
cx,
|
|
UNNEEDED_FIELD_PATTERN,
|
|
field.span,
|
|
"you matched a field with a wildcard pattern, consider using `..` \
|
|
instead",
|
|
None,
|
|
&format!("try with `{} {{ {}, .. }}`", type_name, normal[..].join(", ")),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|