#[cfg(feature = "tree-sitter")]
use tree_sitter::Node;
#[cfg(feature = "tree-sitter")]
pub fn is_fn_like(kind: &str) -> bool {
matches!(
kind,
"function_item"
| "function_declaration"
| "function_definition"
| "closure_expression"
| "arrow_function"
| "method_definition"
| "method_declaration"
| "constructor_declaration"
| "lambda"
| "func_literal"
)
}
#[cfg(feature = "tree-sitter")]
pub fn fn_name(node: Node, source: &[u8]) -> Option<String> {
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
match child.kind() {
"identifier" | "type_identifier" | "property_identifier" | "field_identifier" => {
if let Ok(t) = child.utf8_text(source) {
return Some(t.to_string());
}
}
_ => {}
}
}
None
}
#[cfg(feature = "tree-sitter")]
pub fn logical_body_root(fn_like: Node<'_>) -> Node<'_> {
fn_like
.child_by_field_name("body")
.or_else(|| fn_like.child_by_field_name("value"))
.unwrap_or(fn_like)
}
#[cfg(feature = "tree-sitter")]
pub fn for_each_function(
content: &str,
ext: &str,
mut visit: impl FnMut(Node, &str, &[u8]),
) -> Option<()> {
let source = content.as_bytes();
let mut seen: std::collections::HashSet<usize> = std::collections::HashSet::new();
crate::core::chunks_ts::for_each_chunk_node(content, ext, |chunk_root, _name, _kind, _, _| {
crate::core::ast_walk::for_each_descendant(chunk_root, |node| {
if is_fn_like(node.kind()) && seen.insert(node.start_byte()) {
let name = fn_name(node, source).unwrap_or_else(|| "<anonymous>".to_string());
visit(node, &name, source);
}
});
})
}