mod common;
use common::{Kind, Shape, build};
use syntax_lang::{BuildError, Builder, Element, Node, Span, Token};
fn sample() -> (Node<Kind>, &'static str) {
let source = "foo (bar)";
let mut b = Builder::new();
b.start_node(Kind::Group); b.token(Token::new(Kind::Word, Span::new(0, 3))); b.token(Token::new(Kind::Space, Span::new(3, 4))); b.start_node(Kind::Group); b.token(Token::new(Kind::Word, Span::new(4, 5))); b.token(Token::new(Kind::Word, Span::new(5, 8))); b.token(Token::new(Kind::Word, Span::new(8, 9))); b.finish_node();
b.finish_node();
(b.finish().expect("balanced"), source)
}
#[test]
fn test_tree_reconstructs_source_losslessly() {
let (root, source) = sample();
assert_eq!(root.text(source), Some(source));
let mut rebuilt = String::new();
for token in root.tokens() {
let lo = token.span().start().to_usize();
let hi = token.span().end().to_usize();
rebuilt.push_str(&source[lo..hi]);
}
assert_eq!(rebuilt, source);
}
#[test]
fn test_tokens_are_in_source_order() {
let (root, _) = sample();
let spans: Vec<_> = root.tokens().map(|t| t.span()).collect();
let mut sorted = spans.clone();
sorted.sort();
assert_eq!(spans, sorted);
assert_eq!(root.tokens().count(), 5);
}
#[test]
fn test_trivia_is_preserved_but_filterable() {
let (root, _) = sample();
assert_eq!(root.tokens().count(), 5);
let significant = root.tokens().filter(|t| !t.is_trivia()).count();
assert_eq!(significant, 4);
}
#[test]
fn test_covering_span_equals_child_range_at_every_node() {
let (root, source) = sample();
for node in root.descendants() {
if let Some(text) = node.text(source) {
let mut rebuilt = String::new();
for token in node.tokens() {
let lo = token.span().start().to_usize();
let hi = token.span().end().to_usize();
rebuilt.push_str(&source[lo..hi]);
}
assert_eq!(text, rebuilt, "node {:?} span mismatch", node.kind());
}
}
}
#[test]
fn test_nested_group_span() {
let (root, _) = sample();
let inner = root.child_nodes().next().expect("one nested group");
assert_eq!(inner.span(), Span::new(4, 9));
assert_eq!(inner.tokens().count(), 3);
}
#[test]
fn test_shape_helper_builds_expected_leaf_count() {
let shape = Shape::Branch(vec![
Shape::Leaf(Kind::Word, 2),
Shape::Branch(vec![
Shape::Leaf(Kind::Space, 1),
Shape::Leaf(Kind::Word, 3),
]),
]);
let (root, len) = build(&shape);
assert_eq!(len, 6);
assert_eq!(root.span(), Span::new(0, 6));
assert_eq!(root.tokens().count(), 3);
assert_eq!(root.descendants().count(), 2); }
#[test]
fn test_direct_children_split_correctly() {
let (root, _) = sample();
assert_eq!(root.len(), 3); assert_eq!(root.child_tokens().count(), 2);
assert_eq!(root.child_nodes().count(), 1);
let kinds: Vec<_> = root.children().map(Element::kind).copied().collect();
assert_eq!(kinds, [Kind::Word, Kind::Space, Kind::Group]);
}
#[test]
fn test_error_paths_end_to_end() {
let mut b = Builder::new();
b.start_node(Kind::Group);
b.token(Token::new(Kind::Word, Span::new(0, 1)));
assert_eq!(b.finish(), Err(BuildError::UnclosedNodes));
let mut b = Builder::new();
b.token(Token::new(Kind::Word, Span::new(0, 1)));
assert_eq!(b.finish(), Err(BuildError::TokenOutsideNode));
let mut b = Builder::<Kind>::new();
b.finish_node();
assert_eq!(b.finish(), Err(BuildError::UnbalancedFinish));
let mut b = Builder::new();
b.start_node(Kind::Group);
b.finish_node();
b.start_node(Kind::Group);
b.finish_node();
assert_eq!(b.finish(), Err(BuildError::MultipleRoots));
assert_eq!(Builder::<Kind>::new().finish(), Err(BuildError::EmptyTree));
}
#[test]
fn test_clone_and_eq_roundtrip() {
let (root, _) = sample();
let clone = root.clone();
assert_eq!(root, clone);
}
#[test]
fn test_deep_chain_builds_walks_and_drops() {
let mut b = Builder::new();
for _ in 0..50_000 {
b.start_node(Kind::Group);
}
b.token(Token::new(Kind::Word, Span::new(0, 1)));
for _ in 0..50_000 {
b.finish_node();
}
let root = b.finish().expect("balanced");
assert_eq!(root.descendants().count(), 50_000);
assert_eq!(root.tokens().count(), 1);
assert_eq!(root.span(), Span::new(0, 1));
drop(root); }