#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
#![allow(
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
clippy::cast_sign_loss
)]
use super::*;
pub(crate) fn groovy_body_is_interface_like(body: &Node) -> bool {
use Groovy::*;
body.parent().is_some_and(|p| {
matches!(
p.kind_id().into(),
InterfaceDeclaration | TraitDeclaration | AnnotationTypeDeclaration
)
})
}
pub(crate) fn groovy_has_explicit_public(declaration: &Node) -> bool {
declaration.first_child(|id| id == Groovy::Public).is_some()
}
pub(crate) fn csharp_is_explicit_public(declaration: &Node) -> bool {
declaration.children().any(|child| {
matches!(child.kind_id().into(), Csharp::Modifier)
&& child.first_child(|id| id == Csharp::Public).is_some()
})
}
pub(crate) fn csharp_node_has_private_or_protected_modifier(node: &Node) -> bool {
node.children().any(|child| {
matches!(child.kind_id().into(), Csharp::Modifier)
&& child
.first_child(|id| id == Csharp::Private || id == Csharp::Protected)
.is_some()
})
}
pub(crate) fn csharp_interface_member_is_public(declaration: &Node) -> bool {
!csharp_node_has_private_or_protected_modifier(declaration)
}
pub(crate) fn php_is_explicit_public(declaration: &Node) -> bool {
declaration.children().any(|child| {
matches!(child.kind_id().into(), Php::VisibilityModifier)
&& child.first_child(|id| id == Php::Public).is_some()
})
}
pub(crate) fn ruby_attr_macro_symbol_count(call: &Node) -> usize {
use Ruby::*;
call.children()
.find(|c| matches!(c.kind_id().into(), ArgumentList | ArgumentList2))
.map_or(0, |args| {
args.children()
.filter(|c| {
matches!(
c.kind_id().into(),
SimpleSymbol | DelimitedSymbol | HashKeySymbol | BareSymbol
)
})
.count()
})
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub(crate) enum RubyVisibility {
Public,
Private,
Protected,
}
pub(crate) fn ruby_visibility_marker(node: &Node, source: &[u8]) -> Option<RubyVisibility> {
if !matches!(node.kind_id().into(), Ruby::Identifier) {
return None;
}
match node.utf8_text(source)? {
"private" => Some(RubyVisibility::Private),
"public" => Some(RubyVisibility::Public),
"protected" => Some(RubyVisibility::Protected),
_ => None,
}
}
pub(crate) fn ruby_attr_macro_name(call: &Node, source: &[u8]) -> Option<&'static str> {
let ident = call
.children()
.find(|c| matches!(c.kind_id().into(), Ruby::Identifier))?;
match ident.utf8_text(source)? {
"attr_accessor" => Some("attr_accessor"),
"attr_reader" => Some("attr_reader"),
"attr_writer" => Some("attr_writer"),
_ => None,
}
}
pub(crate) fn ruby_walk_class_body(body: &Node, source: &[u8], stats: &mut Stats) {
use Ruby::*;
let mut visibility = RubyVisibility::Public;
for child in body.children() {
if let Some(marker) = ruby_visibility_marker(&child, source) {
visibility = marker;
continue;
}
match child.kind_id().into() {
Assignment | Assignment2 => {
let Some(lhs) = child.children().next() else {
continue;
};
if matches!(lhs.kind_id().into(), InstanceVariable | ClassVariable) {
stats.class_na += 1;
if visibility == RubyVisibility::Public {
stats.class_npa += 1;
}
}
}
Call | Call2 | Call3 | Call4 if ruby_attr_macro_name(&child, source).is_some() => {
let count = ruby_attr_macro_symbol_count(&child);
stats.class_na += count;
if visibility == RubyVisibility::Public {
stats.class_npa += count;
}
}
_ => {}
}
}
}
pub(crate) fn go_is_exported(name: &str) -> bool {
name.chars().next().is_some_and(char::is_uppercase)
}
pub(crate) fn go_embedded_field_name<'a>(declaration: &Node<'a>) -> Option<Node<'a>> {
use self::Go::{PointerType, QualifiedType, TypeIdentifier};
declaration
.children()
.find_map(|child| match child.kind_id().into() {
PointerType | QualifiedType => child
.children()
.filter(|n| matches!(n.kind_id().into(), TypeIdentifier))
.last(),
TypeIdentifier => Some(child),
_ => None,
})
}
pub(crate) fn cpp_has_function_declarator(node: &Node) -> bool {
node.children().any(|child| match child.kind() {
"function_declarator" => true,
"pointer_declarator" | "reference_declarator" | "declaration" => {
cpp_has_function_declarator(&child)
}
_ => false,
})
}
pub(crate) fn cpp_count_field_identifiers(node: &Node) -> usize {
let mut count = 0;
for child in node.children() {
match child.kind() {
"field_identifier" => count += 1,
"pointer_declarator"
| "array_declarator"
| "init_declarator"
| "reference_declarator" => {
count += cpp_count_field_identifiers(&child);
}
_ => {}
}
}
count
}
pub(crate) fn pattern_is_bare_underscore(pat: &Node, underscore_id: u16) -> bool {
let mut found_underscore = false;
for child in pat.children() {
if child.kind_id() == underscore_id {
if found_underscore {
return false;
}
found_underscore = true;
} else if child.is_named() {
return false;
}
}
found_underscore
}
pub(crate) fn python_case_clause_counts(node: &Node, underscore_id: u16) -> bool {
let mut bare_underscore = false;
for child in node.children() {
match child.kind_id().into() {
Python::IfClause => return true,
Python::CasePattern => {
bare_underscore = pattern_is_bare_underscore(&child, underscore_id);
if !bare_underscore {
return true;
}
}
_ => {}
}
}
!bare_underscore
}
pub(crate) fn ruby_in_clause_counts(in_clause: &Node, source: &[u8]) -> bool {
let mut pattern: Option<Node> = None;
for child in in_clause.children() {
match child.kind_id().into() {
Ruby::Guard | Ruby::IfGuard | Ruby::UnlessGuard => return true,
_ if pattern.is_none() && child.is_named() => pattern = Some(child),
_ => {}
}
}
pattern.is_none_or(|pat| {
!(matches!(pat.kind_id().into(), Ruby::Identifier) && pat.utf8_text(source) == Some("_"))
})
}
pub(crate) fn rust_visibility_modifier_is_public(node: &Node) -> bool {
!node.children().any(|c| c.kind_id() == Rust::Zelf)
}
pub(crate) fn rust_item_is_public(node: &Node) -> bool {
node.children()
.filter(|c| c.kind_id() == Rust::VisibilityModifier)
.any(|vis| rust_visibility_modifier_is_public(&vis))
}
pub(crate) fn python_is_block(node: &Node) -> bool {
matches!(node.kind_id().into(), Python::Block | Python::Block2)
}
pub(crate) fn kotlin_class_body_is_interface(class_body: &Node) -> bool {
class_body.parent().is_some_and(|p| {
matches!(p.kind_id().into(), Kotlin::ClassDeclaration)
&& p.first_child(|id| id == Kotlin::Interface).is_some()
})
}
pub(crate) fn kotlin_is_public(decl: &Node) -> bool {
let Some(modifiers) = decl.first_child(|id| id == Kotlin::Modifiers) else {
return true;
};
let Some(visibility) = modifiers.first_child(|id| id == Kotlin::VisibilityModifier) else {
return true;
};
visibility
.first_child(|id| {
matches!(
id.into(),
Kotlin::Private | Kotlin::Protected | Kotlin::Internal
)
})
.is_none()
}