#![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], stats: &mut Stats) {
use Rust::*;
if matches!(node.kind_id().into(), ImplItem | TraitItem) && stats.is_disabled() {
stats.is_class_space = true;
}
match node.kind_id().into() {
StructItem => rust_count_struct_attrs(node, stats),
ConstItem | StaticItem => rust_count_assoc_const(node, stats),
AssociatedType => rust_count_assoc_type(node, 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;
}
_ => {}
}
}
if attrs > 0 {
if stats.is_disabled() {
stats.is_class_space = true;
}
stats.class_na += attrs;
stats.class_npa += public_attrs;
}
}
fn rust_count_assoc_const(node: &Node, stats: &mut Stats) {
use Rust::*;
let Some(parent) = node.parent() else {
return;
};
let Some(grand) = parent.parent() 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(node: &Node, stats: &mut Stats) {
use Rust::*;
let Some(parent) = node.parent() else {
return;
};
let Some(grand) = parent.parent() 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)
}