use tree_sitter::Node;
use super::ChunkType;
pub(super) fn swift_class_decl_kind(node: Node<'_>) -> ChunkType {
let kw = node
.child(0)
.map(|c| c.kind().to_string())
.unwrap_or_default();
match kw.as_str() {
"struct" => ChunkType::Struct,
"enum" => ChunkType::Enum,
"extension" => ChunkType::Module,
_ => ChunkType::Class, }
}
pub(super) fn classify_node(lang: &str, node: Node<'_>) -> Option<ChunkType> {
let kind = node.kind();
let parent_kind = node.parent().map(|p| p.kind()).unwrap_or("");
Some(match (lang, kind) {
("rust", "function_item") => {
if matches!(parent_kind, "declaration_list" | "impl_item" | "trait_item")
|| ancestor_kind(node, "impl_item").is_some()
{
ChunkType::Method
} else {
ChunkType::Function
}
}
("rust", "impl_item") => ChunkType::Impl,
("rust", "struct_item") => ChunkType::Class,
("rust", "trait_item") => ChunkType::Trait,
("rust", "enum_item") => ChunkType::Enum,
("rust", "mod_item") => ChunkType::Module,
("python", "function_definition") => {
if ancestor_kind(node, "class_definition").is_some() {
ChunkType::Method
} else {
ChunkType::Function
}
}
("python", "class_definition") => ChunkType::Class,
("python", "decorated_definition") => return None,
("javascript" | "typescript", "function_declaration") => ChunkType::Function,
("javascript" | "typescript", "class_declaration") => ChunkType::Class,
("javascript" | "typescript", "method_definition") => ChunkType::Method,
("go", "function_declaration") => ChunkType::Function,
("go", "method_declaration") => ChunkType::Method,
("go", "type_declaration") => ChunkType::Class,
("java", "method_declaration") => ChunkType::Method,
("java", "class_declaration") => ChunkType::Class,
("java", "interface_declaration") => ChunkType::Trait,
("c" | "cpp", "function_definition") => ChunkType::Function,
("cpp", "class_specifier") => ChunkType::Class,
("c" | "cpp", "struct_specifier") => ChunkType::Class,
("ruby", "method") => ChunkType::Function,
("ruby", "singleton_method") => ChunkType::Method,
("ruby", "module") => ChunkType::Module,
("ruby", "class") => ChunkType::Class,
("php", "function_definition") => ChunkType::Function,
("php", "method_declaration") => ChunkType::Method,
("php", "class_declaration") => ChunkType::Class,
("php", "interface_declaration") => ChunkType::Trait,
("php", "trait_declaration") => ChunkType::Trait,
("php", "namespace_definition") => ChunkType::Module,
("scala", "function_definition") => {
if ancestor_kind(node, "class_definition").is_some()
|| ancestor_kind(node, "object_definition").is_some()
|| ancestor_kind(node, "trait_definition").is_some()
{
ChunkType::Method
} else {
ChunkType::Function
}
}
("scala", "class_definition") => ChunkType::Class,
("scala", "object_definition") => ChunkType::Class,
("scala", "trait_definition") => ChunkType::Trait,
("csharp", "method_declaration") => {
if ancestor_kind(node, "class_declaration").is_some()
|| ancestor_kind(node, "interface_declaration").is_some()
|| ancestor_kind(node, "struct_declaration").is_some()
{
ChunkType::Method
} else {
ChunkType::Function
}
}
("csharp", "constructor_declaration") => ChunkType::Method,
("csharp", "class_declaration") => ChunkType::Class,
("csharp", "interface_declaration") => ChunkType::Trait,
("csharp", "struct_declaration") => ChunkType::Class,
("csharp", "namespace_declaration") => ChunkType::Module,
("csharp", "enum_declaration") => ChunkType::Enum,
("kotlin", "function_declaration") => {
if ancestor_kind(node, "class_declaration").is_some()
|| ancestor_kind(node, "object_declaration").is_some()
{
ChunkType::Method
} else {
ChunkType::Function
}
}
("kotlin", "secondary_constructor") => ChunkType::Method,
("kotlin", "class_declaration") => ChunkType::Class,
("kotlin", "object_declaration") => ChunkType::Class,
("kotlin", "companion_object") => ChunkType::Class,
("kotlin", "interface_declaration") => ChunkType::Trait,
("swift", "class_declaration") => swift_class_decl_kind(node),
("swift", "protocol_declaration") => ChunkType::Trait,
("swift", "function_declaration") | ("swift", "protocol_function_declaration") => {
if ancestor_kind(node, "class_declaration").is_some()
|| ancestor_kind(node, "protocol_declaration").is_some()
{
ChunkType::Method
} else {
ChunkType::Function
}
}
("swift", "init_declaration") => ChunkType::Method,
_ => return None,
})
}
pub(super) fn ancestor_kind<'a>(node: Node<'a>, kind: &str) -> Option<Node<'a>> {
let mut cur = node.parent();
while let Some(c) = cur {
if c.kind() == kind {
return Some(c);
}
cur = c.parent();
}
None
}
pub(super) fn ancestor_kind_any<'a>(node: Node<'a>, kinds: &[&str]) -> Option<Node<'a>> {
let mut cur = node.parent();
while let Some(c) = cur {
if kinds.contains(&c.kind()) {
return Some(c);
}
cur = c.parent();
}
None
}
pub(super) fn name_of(node: Node<'_>, src: &[u8]) -> String {
if let Some(n) = node.child_by_field_name("name") {
return std::str::from_utf8(&src[n.start_byte()..n.end_byte()])
.unwrap_or("")
.to_string();
}
String::new()
}
pub(super) fn rust_impl_type_name(node: Node<'_>, src: &[u8]) -> Option<String> {
let imp = ancestor_kind(node, "impl_item")?;
let t = imp.child_by_field_name("type")?;
Some(
std::str::from_utf8(&src[t.start_byte()..t.end_byte()])
.unwrap_or("")
.to_string(),
)
}
pub(super) fn scala_enclosing_class_name(node: Node<'_>, src: &[u8]) -> Option<String> {
let owner = ancestor_kind_any(
node,
&["class_definition", "object_definition", "trait_definition"],
)?;
let n = owner.child_by_field_name("name")?;
Some(
std::str::from_utf8(&src[n.start_byte()..n.end_byte()])
.unwrap_or("")
.to_string(),
)
}
pub(super) fn php_enclosing_class_name(node: Node<'_>, src: &[u8]) -> Option<String> {
let owner = ancestor_kind_any(
node,
&[
"class_declaration",
"interface_declaration",
"trait_declaration",
],
)?;
let n = owner.child_by_field_name("name")?;
Some(
std::str::from_utf8(&src[n.start_byte()..n.end_byte()])
.unwrap_or("")
.to_string(),
)
}