use tree_sitter::Node;
pub(super) fn declared_idents<'tree>(node: Node<'tree>, _src: &[u8]) -> Vec<Node<'tree>> {
let mut out = Vec::new();
match node.kind() {
"let_statement" | "const_statement" => {
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
match child.kind() {
"identifier" | "name" => out.push(child),
"scoped_identifier" => {
if let Some(ident) = scoped_ident(child) {
out.push(ident);
}
}
"list_assignment" => list_target_idents(child, &mut out),
_ => {}
}
}
}
"for_loop" => {
if let Some(variable) = node.child_by_field_name("variable") {
match variable.kind() {
"identifier" | "name" => out.push(variable),
"scoped_identifier" => {
if let Some(ident) = scoped_ident(variable) {
out.push(ident);
}
}
"list_assignment" => list_target_idents(variable, &mut out),
_ => {}
}
}
}
"parameters" => {
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
match child.kind() {
"identifier" => out.push(child),
"default_parameter" => {
if let Some(name) = child.child_by_field_name("name") {
out.push(name);
}
}
_ => {}
}
}
}
"function_declaration" => {
if let Some(name) = node.child_by_field_name("name") {
if name.kind() == "identifier" || name.kind() == "name" {
out.push(name);
}
}
}
_ => {}
}
out
}
fn scoped_ident(node: Node<'_>) -> Option<Node<'_>> {
let mut cursor = node.walk();
node.children(&mut cursor)
.find(|child| child.kind() == "identifier")
}
fn list_target_idents<'tree>(node: Node<'tree>, out: &mut Vec<Node<'tree>>) {
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
match child.kind() {
"identifier" | "name" => out.push(child),
"scoped_identifier" => {
if let Some(ident) = scoped_ident(child) {
out.push(ident);
}
}
"list_assignment" => list_target_idents(child, out),
_ => {}
}
}
}
pub(super) fn is_reference(node: Node<'_>) -> bool {
let Some(parent) = node.parent() else {
return true;
};
if parent.kind() == "field_expression" && parent.child_by_field_name("field") == Some(node) {
return false;
}
true
}
pub(super) fn escapes_scope(node: Node<'_>) -> bool {
node.parent().is_some_and(|parent| {
parent.kind() == "function_declaration" && parent.child_by_field_name("name") == Some(node)
})
}