use tree_sitter::Node;
pub(super) fn collect_inherits(node: Node<'_>, src: &[u8], lang: &str) -> Vec<String> {
let mut out = Vec::new();
match (lang, node.kind()) {
("rust", "impl_item") => collect_rust_impl_inherits(node, src, &mut out),
("python", "class_definition") => collect_python_class_inherits(node, src, &mut out),
("scala", "class_definition" | "object_definition" | "trait_definition") => {
collect_scala_template_inherits(node, src, &mut out);
}
("php", "class_declaration" | "interface_declaration" | "trait_declaration") => {
collect_php_class_inherits(node, src, &mut out);
}
_ => {}
}
out.retain(|s| !s.is_empty());
out
}
fn collect_rust_impl_inherits(node: Node<'_>, src: &[u8], out: &mut Vec<String>) {
if let Some(t) = node.child_by_field_name("trait") {
out.push(
std::str::from_utf8(&src[t.start_byte()..t.end_byte()])
.unwrap_or("")
.to_string(),
);
}
}
fn collect_python_class_inherits(node: Node<'_>, src: &[u8], out: &mut Vec<String>) {
let Some(s) = node.child_by_field_name("superclasses") else {
return;
};
let txt = std::str::from_utf8(&src[s.start_byte()..s.end_byte()])
.unwrap_or("")
.trim_matches(|c: char| c == '(' || c == ')')
.to_string();
for part in txt.split(',') {
let p = part.trim();
if !p.is_empty() {
out.push(p.to_string());
}
}
}
fn collect_scala_template_inherits(node: Node<'_>, src: &[u8], out: &mut Vec<String>) {
let mut cur = node.walk();
for child in node.children(&mut cur) {
if child.kind() != "extends_clause" {
continue;
}
let mut cur2 = child.walk();
for sub in child.children(&mut cur2) {
if sub.kind() == "type_identifier" {
let t = std::str::from_utf8(&src[sub.start_byte()..sub.end_byte()])
.unwrap_or("")
.to_string();
if !t.is_empty() {
out.push(t);
}
}
}
}
}
fn collect_php_class_inherits(node: Node<'_>, src: &[u8], out: &mut Vec<String>) {
let mut cur = node.walk();
for child in node.children(&mut cur) {
if !matches!(child.kind(), "base_clause" | "class_interface_clause") {
continue;
}
let mut cur2 = child.walk();
for sub in child.children(&mut cur2) {
if sub.kind() == "name" || sub.kind() == "qualified_name" {
let t = std::str::from_utf8(&src[sub.start_byte()..sub.end_byte()])
.unwrap_or("")
.to_string();
if !t.is_empty() {
out.push(t);
}
}
}
}
}