mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-24 05:33:27 +00:00
Refactor excessive_bools
:
* Check HIR tree before checking for macros. * Check item count before checking for bools.
This commit is contained in:
parent
1b0230cf25
commit
f178316ae2
1 changed files with 44 additions and 53 deletions
|
@ -87,12 +87,6 @@ pub struct ExcessiveBools {
|
||||||
max_fn_params_bools: u64,
|
max_fn_params_bools: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
|
|
||||||
enum Kind {
|
|
||||||
Struct,
|
|
||||||
Fn,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ExcessiveBools {
|
impl ExcessiveBools {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(max_struct_bools: u64, max_fn_params_bools: u64) -> Self {
|
pub fn new(max_struct_bools: u64, max_fn_params_bools: u64) -> Self {
|
||||||
|
@ -101,46 +95,42 @@ impl ExcessiveBools {
|
||||||
max_fn_params_bools,
|
max_fn_params_bools,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn too_many_bools<'tcx>(&self, tys: impl Iterator<Item = &'tcx Ty<'tcx>>, kind: Kind) -> bool {
|
|
||||||
if let Ok(bools) = tys.filter(|ty| is_bool(ty)).count().try_into() {
|
|
||||||
(if Kind::Fn == kind {
|
|
||||||
self.max_fn_params_bools
|
|
||||||
} else {
|
|
||||||
self.max_struct_bools
|
|
||||||
}) < bools
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_fn_sig(&self, cx: &LateContext<'_>, fn_decl: &FnDecl<'_>, span: Span) {
|
impl_lint_pass!(ExcessiveBools => [STRUCT_EXCESSIVE_BOOLS, FN_PARAMS_EXCESSIVE_BOOLS]);
|
||||||
if !span.from_expansion() && self.too_many_bools(fn_decl.inputs.iter(), Kind::Fn) {
|
|
||||||
|
fn has_n_bools<'tcx>(iter: impl Iterator<Item = &'tcx Ty<'tcx>>, mut count: u64) -> bool {
|
||||||
|
iter.filter(|ty| is_bool(ty)).any(|_| {
|
||||||
|
let (x, overflow) = count.overflowing_sub(1);
|
||||||
|
count = x;
|
||||||
|
overflow
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_fn_decl(cx: &LateContext<'_>, decl: &FnDecl<'_>, sp: Span, max: u64) {
|
||||||
|
if has_n_bools(decl.inputs.iter(), max) && !sp.from_expansion() {
|
||||||
span_lint_and_help(
|
span_lint_and_help(
|
||||||
cx,
|
cx,
|
||||||
FN_PARAMS_EXCESSIVE_BOOLS,
|
FN_PARAMS_EXCESSIVE_BOOLS,
|
||||||
span,
|
sp,
|
||||||
format!("more than {} bools in function parameters", self.max_fn_params_bools),
|
format!("more than {max} bools in function parameters"),
|
||||||
None,
|
None,
|
||||||
"consider refactoring bools into two-variant enums",
|
"consider refactoring bools into two-variant enums",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl_lint_pass!(ExcessiveBools => [STRUCT_EXCESSIVE_BOOLS, FN_PARAMS_EXCESSIVE_BOOLS]);
|
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
|
impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||||
if item.span.from_expansion() {
|
if let ItemKind::Struct(variant_data, _) = &item.kind
|
||||||
return;
|
&& variant_data.fields().len() as u64 > self.max_struct_bools
|
||||||
}
|
&& has_n_bools(
|
||||||
if let ItemKind::Struct(variant_data, _) = &item.kind {
|
variant_data.fields().iter().map(|field| field.ty),
|
||||||
if has_repr_attr(cx, item.hir_id()) {
|
self.max_struct_bools,
|
||||||
return;
|
)
|
||||||
}
|
&& !has_repr_attr(cx, item.hir_id())
|
||||||
|
&& !item.span.from_expansion()
|
||||||
if self.too_many_bools(variant_data.fields().iter().map(|field| field.ty), Kind::Struct) {
|
{
|
||||||
span_lint_and_help(
|
span_lint_and_help(
|
||||||
cx,
|
cx,
|
||||||
STRUCT_EXCESSIVE_BOOLS,
|
STRUCT_EXCESSIVE_BOOLS,
|
||||||
|
@ -151,14 +141,14 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx TraitItem<'tcx>) {
|
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx TraitItem<'tcx>) {
|
||||||
// functions with a body are already checked by `check_fn`
|
// functions with a body are already checked by `check_fn`
|
||||||
if let TraitItemKind::Fn(fn_sig, TraitFn::Required(_)) = &trait_item.kind
|
if let TraitItemKind::Fn(fn_sig, TraitFn::Required(_)) = &trait_item.kind
|
||||||
&& fn_sig.header.abi == Abi::Rust
|
&& fn_sig.header.abi == Abi::Rust
|
||||||
|
&& fn_sig.decl.inputs.len() as u64 > self.max_fn_params_bools
|
||||||
{
|
{
|
||||||
self.check_fn_sig(cx, fn_sig.decl, fn_sig.span);
|
check_fn_decl(cx, fn_sig.decl, fn_sig.span, self.max_fn_params_bools);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,12 +161,13 @@ impl<'tcx> LateLintPass<'tcx> for ExcessiveBools {
|
||||||
span: Span,
|
span: Span,
|
||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
) {
|
) {
|
||||||
let hir_id = cx.tcx.local_def_id_to_hir_id(def_id);
|
|
||||||
if let Some(fn_header) = fn_kind.header()
|
if let Some(fn_header) = fn_kind.header()
|
||||||
&& fn_header.abi == Abi::Rust
|
&& fn_header.abi == Abi::Rust
|
||||||
&& get_parent_as_impl(cx.tcx, hir_id).map_or(true, |impl_item| impl_item.of_trait.is_none())
|
&& fn_decl.inputs.len() as u64 > self.max_fn_params_bools
|
||||||
|
&& get_parent_as_impl(cx.tcx, cx.tcx.local_def_id_to_hir_id(def_id))
|
||||||
|
.map_or(true, |impl_item| impl_item.of_trait.is_none())
|
||||||
{
|
{
|
||||||
self.check_fn_sig(cx, fn_decl, span);
|
check_fn_decl(cx, fn_decl, span, self.max_fn_params_bools);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue