use ast::{Expr, StmtIf};
use ruff_macros::{ViolationMetadata, derive_message_formats};
use ruff_python_ast as ast;
use ruff_text_size::Ranged;
use crate::Violation;
use crate::checkers::ast::Checker;
#[derive(ViolationMetadata)]
#[violation_metadata(preview_since = "v0.1.1")]
pub(crate) struct TooManyBooleanExpressions {
expressions: usize,
max_expressions: usize,
}
impl Violation for TooManyBooleanExpressions {
#[derive_message_formats]
fn message(&self) -> String {
let TooManyBooleanExpressions {
expressions,
max_expressions,
} = self;
format!("Too many Boolean expressions ({expressions} > {max_expressions})")
}
}
pub(crate) fn too_many_boolean_expressions(checker: &Checker, stmt: &StmtIf) {
if let Some(bool_op) = stmt.test.as_bool_op_expr() {
let expressions = count_bools(bool_op);
if expressions > checker.settings().pylint.max_bool_expr {
checker.report_diagnostic(
TooManyBooleanExpressions {
expressions,
max_expressions: checker.settings().pylint.max_bool_expr,
},
bool_op.range(),
);
}
}
for elif in &stmt.elif_else_clauses {
if let Some(bool_op) = elif.test.as_ref().and_then(Expr::as_bool_op_expr) {
let expressions = count_bools(bool_op);
if expressions > checker.settings().pylint.max_bool_expr {
checker.report_diagnostic(
TooManyBooleanExpressions {
expressions,
max_expressions: checker.settings().pylint.max_bool_expr,
},
bool_op.range(),
);
}
}
}
}
fn count_bools(bool_op: &ast::ExprBoolOp) -> usize {
bool_op
.values
.iter()
.map(|expr| {
if let Expr::BoolOp(bool_op) = expr {
count_bools(bool_op)
} else {
1
}
})
.sum::<usize>()
}