use tree_sitter::{Node, Parser, Tree};
use crate::{Error, ErrorKind};
pub struct TreeWalker<'a> {
nodes: Vec<Node<'a>>,
index: usize,
}
impl TreeWalker<'_> {
pub fn new(node: Node<'_>) -> TreeWalker<'_> {
let mut nodes: Vec<Node> = Vec::new();
TreeWalker::traverse(node, &mut nodes);
TreeWalker { nodes, index: 0 }
}
fn traverse<'a>(node: Node<'a>, collection: &mut Vec<Node<'a>>) {
collection.push(node);
let mut cursor = node.walk();
for child in node.children(&mut cursor) {
TreeWalker::traverse(child, collection);
}
}
}
impl<'a> Iterator for TreeWalker<'a> {
type Item = Node<'a>;
fn next(&mut self) -> Option<Node<'a>> {
if self.index >= self.nodes.len() {
None
} else {
let node = self.nodes[self.index];
self.index += 1;
Some(node)
}
}
}
pub struct Pkgbuild {
pub source: Vec<u8>,
pub parser: Parser,
pub tree: Tree,
}
impl Pkgbuild {
pub fn new(source: &str) -> Result<Pkgbuild, Error> {
let mut parser = Parser::new();
parser.set_language(tree_sitter_bash::language()).unwrap();
let tree = match parser.parse(source, None) {
Some(tree) => tree,
None => {
return Err(Error::new(
ErrorKind::ParseError,
"failed to parse source code",
));
}
};
Ok(Pkgbuild {
source: source.as_bytes().iter().copied().collect(),
parser,
tree,
})
}
}