use tree_sitter::Node;
use super::skip_subtree;
fn binds_value(name: &str) -> bool {
!name.starts_with('_') && name.chars().next().is_some_and(|c| c.is_lowercase())
}
fn push_identifier<'t>(n: Node<'t>, src: &[u8], out: &mut Vec<Node<'t>>) {
if binds_value(n.utf8_text(src).unwrap_or("")) {
out.push(n);
}
}
pub(super) fn pattern_identifiers<'t>(pattern: Node<'t>, src: &[u8], out: &mut Vec<Node<'t>>) {
if pattern.kind() == "identifier" {
push_identifier(pattern, src, out);
return;
}
if skippable_pattern(pattern.kind()) {
return;
}
let mut cursor = pattern.walk();
for child in pattern.children(&mut cursor) {
descend_pattern(child, src, out);
}
}
fn skippable_pattern(kind: &str) -> bool {
kind == "_" || skip_subtree(kind)
}
fn descend_pattern<'t>(child: Node<'t>, src: &[u8], out: &mut Vec<Node<'t>>) {
if child.kind() == "identifier" {
push_identifier(child, src, out);
} else if !skippable_pattern(child.kind()) {
pattern_identifiers(child, src, out);
}
}
pub(super) fn match_binders<'t>(pattern: Node<'t>, src: &[u8], out: &mut Vec<Node<'t>>) {
let mut cursor = pattern.walk();
for child in pattern.children(&mut cursor) {
match child.kind() {
"if" => return,
"identifier" => {
let name = child.utf8_text(src).unwrap_or("");
if binds_value(name) {
out.push(child);
}
}
"_" => {}
k if skip_subtree(k) => {}
_ => match_binders(child, src, out),
}
}
}