use std::sync::Arc;
use super::green::{GreenElement, GreenNode};
use super::red::SyntaxNode;
pub type TransformResult = Option<Arc<GreenNode>>;
pub trait Transformer {
fn transform_node(&mut self, node: &SyntaxNode) -> TransformResult;
}
pub fn transform(root: &SyntaxNode, transformer: &mut impl Transformer) -> SyntaxNode {
let new_green = rebuild(root, transformer);
SyntaxNode::new_root(new_green)
}
fn rebuild(node: &SyntaxNode, transformer: &mut impl Transformer) -> Arc<GreenNode> {
if let Some(replacement) = transformer.transform_node(node) {
return replacement;
}
let green = node.green();
let mut new_children = Vec::with_capacity(green.children.len());
let mut off = node.offset();
for child in &green.children {
match child {
GreenElement::Node(child_green) => {
let child_red = SyntaxNode::new(Arc::clone(child_green), off);
new_children.push(GreenElement::Node(rebuild(&child_red, transformer)));
off += child_green.text_len;
}
GreenElement::Token(t) => {
new_children.push(GreenElement::Token(Arc::clone(t)));
off += t.text_len;
}
}
}
GreenNode::new(node.kind(), new_children)
}