#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
#![allow(
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
clippy::cast_sign_loss
)]
use super::*;
impl Npa for RustCode {
fn compute<'a>(
node: &Node<'a>,
_code: &'a [u8],
ancestors: Ancestors<'a, '_>,
stats: &mut Stats,
) {
use Rust::*;
match node.kind_id().into() {
StructItem => rust_count_struct_attrs(node, stats),
ConstItem | StaticItem => rust_count_assoc_const(node, ancestors, stats),
AssociatedType => rust_count_assoc_type(node, ancestors, stats),
_ => {}
}
}
}
fn rust_count_struct_attrs(node: &Node, stats: &mut Stats) {
use Rust::*;
let mut attrs = 0;
let mut public_attrs = 0;
for body in node.children() {
match body.kind_id().into() {
FieldDeclarationList => {
for field in body
.children()
.filter(|c| matches!(c.kind_id().into(), FieldDeclaration))
{
attrs += 1;
if rust_item_is_public(&field) {
public_attrs += 1;
}
}
}
OrderedFieldDeclarationList => {
let (count, public) = rust_count_tuple_struct_fields(&body);
attrs += count;
public_attrs += public;
}
_ => {}
}
}
stats.class_na += attrs;
stats.class_npa += public_attrs;
}
fn rust_count_assoc_const<'a>(node: &Node<'a>, ancestors: Ancestors<'a, '_>, stats: &mut Stats) {
use Rust::*;
let mut climb = ancestors.iter(node);
let Some((parent, _)) = climb.next() else {
return;
};
let Some((grand, _)) = climb.next() else {
return;
};
match grand.kind_id().into() {
ImplItem if matches!(parent.kind_id().into(), DeclarationList) => {
stats.class_na += 1;
if rust_item_is_public(node) {
stats.class_npa += 1;
}
}
TraitItem if matches!(parent.kind_id().into(), DeclarationList) => {
stats.interface_na += 1;
stats.interface_npa = stats.interface_na;
}
_ => {}
}
}
fn rust_count_assoc_type<'a>(node: &Node<'a>, ancestors: Ancestors<'a, '_>, stats: &mut Stats) {
use Rust::*;
let mut climb = ancestors.iter(node);
let Some((parent, _)) = climb.next() else {
return;
};
let Some((grand, _)) = climb.next() else {
return;
};
if matches!(grand.kind_id().into(), TraitItem)
&& matches!(parent.kind_id().into(), DeclarationList)
{
stats.interface_na += 1;
stats.interface_npa = stats.interface_na;
}
}
fn rust_count_tuple_struct_fields(list: &Node) -> (usize, usize) {
use Rust::*;
let mut total = 0;
let mut public = 0;
let mut pending_pub = false;
for child in list.children() {
match child.kind_id().into() {
LPAREN | RPAREN | COMMA => {
pending_pub = false;
}
VisibilityModifier => {
pending_pub = rust_visibility_modifier_is_public(&child);
}
AttributeItem | LineComment | BlockComment => {}
_ => {
total += 1;
if pending_pub {
public += 1;
}
pending_pub = false;
}
}
}
(total, public)
}