ktrs_parser/builder/
sink.rs1use ktrs_syntax::{Parse, SyntaxKind, TreeBuilder};
5
6use super::chameleon_cache::ChameleonCache;
7use super::psi_builder::PsiBuilder;
8
9#[derive(Default)]
10pub struct TreeSink {
11 tree: TreeBuilder,
12 cache: Option<ChameleonCache>,
13 pub(super) errors: Vec<String>,
14}
15
16impl TreeSink {
17 pub fn new() -> TreeSink {
18 TreeSink::default()
19 }
20
21 pub(crate) fn for_file(builder: &PsiBuilder, cache: Option<ChameleonCache>) -> TreeSink {
23 let elements = 2 * builder.lexeme_count() + 1;
25 TreeSink { tree: TreeBuilder::with_capacity(elements, builder.text.len()), cache, errors: Vec::new() }
26 }
27
28 pub fn with_cache(cache: ChameleonCache) -> TreeSink {
29 TreeSink { cache: Some(cache), ..TreeSink::default() }
30 }
31
32 pub fn take_cache(&mut self) -> Option<ChameleonCache> {
33 self.cache.take()
34 }
35
36 pub fn finish(self) -> Parse {
37 Parse { tree: self.tree.finish().into(), error_messages: self.errors }
38 }
39
40 pub fn chameleon(&mut self, kind: SyntaxKind, text: &str, build: impl FnOnce(&mut TreeSink)) {
43 let Some(cache) = &self.cache else { return build(self) };
44 if let Some(subtree) = cache.get(kind, text) {
45 self.tree.push_tree(subtree);
46 return;
47 }
48 let (root, errors) = (self.tree.len(), self.errors.len());
49 build(self);
50 if self.errors.len() == errors {
51 let subtree = self.tree.extract(root);
52 self.cache.as_mut().expect("checked above").insert(subtree);
53 }
54 }
55
56 pub(super) fn token(&mut self, kind: SyntaxKind, text: &str) {
57 self.tree.token(kind, text);
58 }
59
60 pub(super) fn start_node(&mut self, kind: SyntaxKind) {
61 self.tree.start_node(kind);
62 }
63
64 pub(super) fn finish_node(&mut self) {
65 self.tree.finish_node();
66 }
67}