Files
ruff/src/flake8_boolean_trap/plugins.rs
Martin Fischer 43db446dfa structs 6/9: Automatically change CheckKind::* to violations::*
The changes in this commit were generated by running:

for f in $(find src -name '*.rs'); do sed -Ei 's/use crate::registry::.*;/\0use crate::violations;/g' $f; done
for f in $(find src -name '*.rs'); do sed -Ei 's/CheckKind::([A-Z])/violations::\1/g' $f; done
git checkout src/registry.rs src/lib.rs src/lib_wasm.rs src/violations.rs
cargo +nightly fmt
2023-01-07 15:14:58 -05:00

115 lines
2.9 KiB
Rust

use rustpython_ast::{Arguments, ExprKind};
use rustpython_parser::ast::{Constant, Expr};
use crate::ast::types::Range;
use crate::checkers::ast::Checker;
use crate::registry::{Check, CheckKind};
use crate::violations;
const FUNC_NAME_ALLOWLIST: &[&str] = &[
"assertEqual",
"assertEquals",
"assertNotEqual",
"assertNotEquals",
"failIfEqual",
"failUnlessEqual",
"fromkeys",
"get",
"getattr",
"index",
"pop",
"setattr",
"setdefault",
];
/// Returns `true` if an argument is allowed to use a boolean trap. To return
/// `true`, the function name must be explicitly allowed, and the argument must
/// be either the first or second argument in the call.
fn allow_boolean_trap(func: &Expr) -> bool {
if let ExprKind::Attribute { attr, .. } = &func.node {
return FUNC_NAME_ALLOWLIST.contains(&attr.as_ref());
}
if let ExprKind::Name { id, .. } = &func.node {
return FUNC_NAME_ALLOWLIST.contains(&id.as_ref());
}
false
}
fn is_boolean_arg(arg: &Expr) -> bool {
matches!(
&arg.node,
ExprKind::Constant {
value: Constant::Bool(_),
..
}
)
}
fn add_if_boolean(checker: &mut Checker, arg: &Expr, kind: CheckKind) {
if is_boolean_arg(arg) {
checker
.checks
.push(Check::new(kind, Range::from_located(arg)));
}
}
pub fn check_positional_boolean_in_def(checker: &mut Checker, arguments: &Arguments) {
for arg in arguments.posonlyargs.iter().chain(arguments.args.iter()) {
if arg.node.annotation.is_none() {
continue;
}
let Some(expr) = &arg.node.annotation else {
continue;
};
// check for both bool (python class) and 'bool' (string annotation)
let hint = match &expr.node {
ExprKind::Name { id, .. } => id == "bool",
ExprKind::Constant {
value: Constant::Str(value),
..
} => value == "bool",
_ => false,
};
if !hint {
continue;
}
checker.checks.push(Check::new(
violations::BooleanPositionalArgInFunctionDefinition,
Range::from_located(arg),
));
}
}
pub fn check_boolean_default_value_in_function_definition(
checker: &mut Checker,
arguments: &Arguments,
) {
for arg in &arguments.defaults {
add_if_boolean(
checker,
arg,
violations::BooleanDefaultValueInFunctionDefinition,
);
}
}
pub fn check_boolean_positional_value_in_function_call(
checker: &mut Checker,
args: &[Expr],
func: &Expr,
) {
for arg in args {
if allow_boolean_trap(func) {
continue;
}
add_if_boolean(
checker,
arg,
violations::BooleanPositionalValueInFunctionCall,
);
}
}