use super::*;
use cstree::interning::Resolver;
type GreenNodeBuilder<'cache, 'interner> = cstree::build::GreenNodeBuilder<'cache, 'interner, SyntaxKind>;
fn with_builder(f: impl FnOnce(&mut GreenNodeBuilder)) -> (SyntaxNode, impl Resolver) {
let mut builder = GreenNodeBuilder::new();
f(&mut builder);
let (node, cache) = builder.finish();
(SyntaxNode::new_root(node), cache.unwrap().into_interner().unwrap())
}
#[test]
#[should_panic = "`left == right` failed"]
fn comparison_works() {
let (first, res1) = with_builder(|_| {});
let (second, res2) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
builder.token(SyntaxKind(1), "hi");
builder.finish_node();
});
assert_tree_eq((&first, &res1), (&second, &res2));
}
#[test]
fn no_rollback_token() {
let (first, res1) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
builder.token(SyntaxKind(1), "hi");
builder.finish_node();
});
let (second, res2) = with_builder(|builder| {
let checkpoint = builder.checkpoint();
builder.token(SyntaxKind(1), "hi");
builder.start_node_at(checkpoint, SyntaxKind(0));
builder.finish_node();
});
assert_tree_eq((&first, &res1), (&second, &res2));
}
#[test]
fn no_rollback_node() {
let (first, res1) = with_builder(|builder| {
builder.start_node(SyntaxKind(2));
builder.start_node(SyntaxKind(0));
builder.token(SyntaxKind(1), "hi");
builder.finish_node();
builder.finish_node();
});
let (second, res2) = with_builder(|builder| {
let checkpoint = builder.checkpoint();
builder.start_node(SyntaxKind(0));
builder.token(SyntaxKind(1), "hi");
builder.finish_node();
builder.start_node_at(checkpoint, SyntaxKind(2));
builder.finish_node();
});
assert_tree_eq((&first, &res1), (&second, &res2));
}
#[test]
#[should_panic = "unfinished nodes"]
fn no_rollback_unfinished_node() {
let (second, res2) = with_builder(|builder| {
let checkpoint = builder.checkpoint();
builder.start_node(SyntaxKind(0));
builder.token(SyntaxKind(1), "hi");
builder.start_node_at(checkpoint, SyntaxKind(2));
builder.finish_node();
builder.finish_node();
});
println!("{}", second.debug(&res2, true));
}
#[test]
fn simple() {
let (first, res1) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
builder.finish_node();
});
let (second, res2) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
let initial = builder.checkpoint();
builder.token(SyntaxKind(1), "hi");
builder.revert_to(initial);
builder.finish_node();
});
assert_tree_eq((&first, &res1), (&second, &res2));
}
#[test]
fn nested() {
let (first, res1) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
builder.finish_node();
});
let (second, res2) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
let initial = builder.checkpoint();
builder.token(SyntaxKind(1), "hi");
builder.token(SyntaxKind(2), "hello");
builder.revert_to(initial);
builder.finish_node();
});
let (third, res3) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
let initial = builder.checkpoint();
builder.token(SyntaxKind(1), "hi");
let second = builder.checkpoint();
builder.token(SyntaxKind(2), "hello");
builder.revert_to(second);
builder.revert_to(initial);
builder.finish_node();
});
assert_tree_eq((&first, &res1), (&second, &res2));
assert_tree_eq((&first, &res1), (&third, &res3));
}
#[test]
fn unfinished_node() {
let (first, res1) = with_builder(|builder| {
builder.start_node(SyntaxKind(2));
builder.finish_node();
});
let (second, res2) = with_builder(|builder| {
builder.start_node(SyntaxKind(2));
let checkpoint = builder.checkpoint();
builder.start_node(SyntaxKind(0));
builder.token(SyntaxKind(1), "hi");
builder.revert_to(checkpoint);
builder.finish_node();
});
assert_tree_eq((&first, &res1), (&second, &res2));
}
#[test]
#[should_panic = "checkpoint no longer valid after reverting to an earlier checkpoint"]
fn misuse() {
let (first, res1) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
builder.finish_node();
});
let (second, res2) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
let initial = builder.checkpoint();
builder.token(SyntaxKind(1), "hi");
let new = builder.checkpoint();
builder.token(SyntaxKind(2), "hello");
builder.revert_to(initial);
builder.revert_to(new);
builder.finish_node();
});
assert_tree_eq((&first, &res1), (&second, &res2));
}
#[test]
#[should_panic = "did you already `revert_to`?"]
fn misuse2() {
with_builder(|builder| {
builder.start_node(SyntaxKind(0));
let initial = builder.checkpoint();
builder.start_node(SyntaxKind(3));
builder.token(SyntaxKind(1), "hi");
let new = builder.checkpoint();
builder.token(SyntaxKind(2), "hello");
builder.revert_to(initial);
builder.revert_to(new);
builder.finish_node();
});
}
#[test]
fn misuse3() {
let (first, res1) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
builder.token(SyntaxKind(3), "no");
builder.finish_node();
});
let (second, res2) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
let initial = builder.checkpoint();
builder.token(SyntaxKind(1), "hi");
let new = builder.checkpoint();
builder.token(SyntaxKind(2), "hello");
builder.revert_to(initial);
builder.token(SyntaxKind(3), "no");
builder.token(SyntaxKind(4), "bad");
builder.token(SyntaxKind(4), "wrong");
builder.revert_to(new);
builder.finish_node();
});
assert_tree_eq((&first, &res1), (&second, &res2));
}
#[test]
#[should_panic = "was `finish_node` called early or did you already `revert_to`"]
fn misuse_combined() {
with_builder(|builder| {
builder.start_node(SyntaxKind(0));
let initial = builder.checkpoint();
builder.start_node(SyntaxKind(3));
builder.token(SyntaxKind(1), "hi");
let new = builder.checkpoint();
builder.token(SyntaxKind(2), "hello");
builder.revert_to(initial);
builder.start_node_at(new, SyntaxKind(4));
builder.finish_node();
});
}
#[test]
#[should_panic = "reverting to an earlier checkpoint"]
fn misuse_combined2() {
with_builder(|builder| {
builder.start_node(SyntaxKind(0));
let initial = builder.checkpoint();
builder.token(SyntaxKind(1), "hi");
let new = builder.checkpoint();
builder.token(SyntaxKind(2), "hello");
builder.revert_to(initial);
builder.start_node_at(new, SyntaxKind(3));
builder.finish_node();
});
}
#[test]
fn revert_then_start() {
let (first, res1) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
builder.start_node(SyntaxKind(3));
builder.token(SyntaxKind(2), "hello");
builder.finish_node();
builder.finish_node();
});
let (second, res2) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
let initial = builder.checkpoint();
builder.token(SyntaxKind(1), "hi");
builder.revert_to(initial);
builder.start_node_at(initial, SyntaxKind(3));
builder.token(SyntaxKind(2), "hello");
builder.finish_node();
builder.finish_node();
});
assert_tree_eq((&first, &res1), (&second, &res2));
}
#[test]
fn start_then_revert() {
let (first, res1) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
builder.token(SyntaxKind(2), "hello");
builder.finish_node();
});
let (second, res2) = with_builder(|builder| {
builder.start_node(SyntaxKind(0));
let initial = builder.checkpoint();
builder.token(SyntaxKind(1), "hi");
builder.start_node_at(initial, SyntaxKind(3));
builder.revert_to(initial);
builder.token(SyntaxKind(2), "hello");
builder.finish_node();
});
assert_tree_eq((&first, &res1), (&second, &res2));
}