use crate::model::Node;
use tree_sitter::{Node as AstNode, Parser};
#[derive(Debug, Clone)]
pub(crate) struct FlatItem {
pub parent: Option<usize>,
pub node: Node,
}
pub(crate) fn build_tree(items: &[FlatItem], parent: Option<usize>) -> Vec<Node> {
items
.iter()
.enumerate()
.filter(|(_, item)| item.parent == parent)
.map(|(index, item)| {
let mut node = item.node.clone();
node.children = build_tree(items, Some(index));
node
})
.collect()
}
pub(crate) fn parse(grammar: tree_sitter::Language, source: &str) -> Option<tree_sitter::Tree> {
let mut parser = Parser::new();
parser
.set_language(&grammar)
.expect("tree-sitter grammar is valid");
parser.parse(source, None)
}
pub(crate) fn collect_items<F>(
ast_node: AstNode,
parent: Option<usize>,
items: &mut Vec<FlatItem>,
classify: &F,
) where
F: Fn(AstNode) -> Option<Node>,
{
let current_parent = match classify(ast_node) {
Some(node) => {
let index = items.len();
items.push(FlatItem { parent, node });
Some(index)
}
None => parent,
};
let mut cursor = ast_node.walk();
for child in ast_node.named_children(&mut cursor) {
collect_items(child, current_parent, items, classify);
}
}
pub(crate) fn ast_preview(ast_node: AstNode, source: &str, preview_len: usize) -> Option<String> {
source
.lines()
.nth(ast_node.start_position().row)
.map(str::trim)
.filter(|line| !line.is_empty())
.map(|line| crate::util::truncate_preview(line, preview_len))
}