#![allow(
clippy::enum_glob_use,
clippy::too_many_lines,
clippy::wildcard_imports
)]
#![allow(
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
clippy::cast_sign_loss
)]
use super::{Abc, Stats};
use crate::macros::python_bool_terminal_kinds;
use crate::*;
fn python_inspect_container(container_node: &Node, conditions: &mut f64) {
use Python::*;
let mut node = *container_node;
let mut node_kind = node.kind_id().into();
let Some(parent) = node.parent() else { return };
let has_boolean_content = matches!(
parent.kind_id().into(),
BooleanOperator | IfStatement | WhileStatement | ConditionalExpression
);
loop {
if !matches!(node_kind, ParenthesizedExpression) {
break;
}
let Some(child) = node.child(1) else { break };
node = child;
node_kind = node.kind_id().into();
if matches!(node_kind, python_bool_terminal_kinds!()) {
if has_boolean_content {
*conditions += 1.;
}
break;
}
}
}
fn python_count_condition(condition: &Node, conditions: &mut f64) {
use Python::*;
let kind = condition.kind_id().into();
if matches!(kind, python_bool_terminal_kinds!()) {
*conditions += 1.;
} else if matches!(kind, ParenthesizedExpression) {
python_inspect_container(condition, conditions);
}
}
fn python_inspect_child(node: &Node, idx: usize, conditions: &mut f64) {
if let Some(child) = node.child(idx) {
python_count_condition(&child, conditions);
}
}
fn python_count_unary_conditions(list_node: &Node, conditions: &mut f64) {
use Python::*;
let list_kind = list_node.kind_id().into();
let mut cursor = list_node.cursor();
if cursor.goto_first_child() {
loop {
let node = cursor.node();
let node_kind = node.kind_id().into();
if matches!(node_kind, python_bool_terminal_kinds!())
&& matches!(list_kind, BooleanOperator)
{
*conditions += 1.;
} else if matches!(node_kind, ParenthesizedExpression) {
python_inspect_container(&node, conditions);
}
if !cursor.goto_next_sibling() {
break;
}
}
}
}
impl Abc for PythonCode {
fn compute<'a>(node: &Node<'a>, _code: &'a [u8], stats: &mut Stats) {
use Python::*;
match node.kind_id().into() {
Assignment if node.first_child(|id| id == EQ).is_some() => {
stats.assignments += 1.;
}
AugmentedAssignment | NamedExpression => {
stats.assignments += 1.;
}
Call => {
stats.branches += 1.;
}
ComparisonOperator
| ConditionalExpression
| ElifClause
| ElseClause
| ExceptClause
| FinallyClause
| NotOperator => {
stats.conditions += 1.;
}
CaseClause if super::npa::python_case_clause_counts(node, UNDERSCORE as u16) => {
stats.conditions += 1.;
}
And | Or => {
if let Some(parent) = node.parent() {
python_count_unary_conditions(&parent, &mut stats.conditions);
}
}
IfStatement | WhileStatement => {
python_inspect_child(node, 1, &mut stats.conditions);
}
_ => {}
}
}
}