use std::collections::HashMap;
use tree_sitter::Node;
const VETO_KINDS: &[&str] = &[
"if_statement",
"for_statement",
"expression_switch_statement",
"type_switch_statement",
"select_statement",
];
const PURE_LITERALS: &[&str] = &[
"int_literal",
"float_literal",
"imaginary_literal",
"rune_literal",
"raw_string_literal",
"interpreted_string_literal",
"true",
"false",
"nil",
"iota",
];
pub(super) fn pure(n: Node) -> bool {
match n.kind() {
k if PURE_LITERALS.contains(&k) => true,
"parenthesized_expression" => n.named_child(0).map(pure).unwrap_or(false),
"binary_expression" => operands_pure(n, 0),
"unary_expression" => operands_pure(n, 1),
_ => false,
}
}
fn operands_pure(n: Node, skip: usize) -> bool {
let mut c = n.walk();
n.children(&mut c).skip(skip).all(pure) && (skip == 0 || unary_op_ok(n))
}
fn unary_op_ok(n: Node) -> bool {
let mut c = n.walk();
for ch in n.children(&mut c) {
if !ch.is_named() {
return matches!(ch.utf8_text(b"").unwrap_or(""), "-" | "+" | "^" | "!");
}
}
false
}
pub(super) fn unconditionally_executed(write_node: Node) -> bool {
const OWNERS: [&str; 2] = ["function_declaration", "method_declaration"];
let mut cur = Some(write_node);
while let Some(n) = cur {
if VETO_KINDS.contains(&n.kind()) {
return false;
}
if OWNERS.contains(&n.kind()) {
return true;
}
cur = n.parent();
}
true
}
pub(super) fn index_nodes<'t>(root: Node<'t>) -> HashMap<usize, Node<'t>> {
let mut map = HashMap::new();
rec(root, &mut map);
map
}
fn rec<'t>(n: Node<'t>, map: &mut HashMap<usize, Node<'t>>) {
map.insert(n.id(), n);
let mut cursor = n.walk();
for child in n.children(&mut cursor) {
rec(child, map);
}
}