aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/libsyntax2/src/yellow/red.rs51
1 files changed, 35 insertions, 16 deletions
diff --git a/crates/libsyntax2/src/yellow/red.rs b/crates/libsyntax2/src/yellow/red.rs
index 13ad44c65..1ee6bdf18 100644
--- a/crates/libsyntax2/src/yellow/red.rs
+++ b/crates/libsyntax2/src/yellow/red.rs
@@ -5,7 +5,28 @@ use {yellow::{GreenNode, RedPtr}, TextUnit};
5pub(crate) struct RedNode { 5pub(crate) struct RedNode {
6 green: GreenNode, 6 green: GreenNode,
7 parent: Option<ParentData>, 7 parent: Option<ParentData>,
8 children: RwLock<Box<[Option<RedNode>]>>, 8 children: RwLock<Box<[RedChild]>>,
9}
10
11#[derive(Debug)]
12enum RedChild {
13 Zigot(TextUnit),
14 Child(RedNode)
15}
16
17impl RedChild {
18 fn set(&mut self, node: RedNode) -> &RedNode {
19 match self {
20 RedChild::Child(node) => return node,
21 RedChild::Zigot(_) => {
22 *self = RedChild::Child(node);
23 match self {
24 RedChild::Child(node) => return node,
25 RedChild::Zigot(_) => unreachable!()
26 }
27 }
28 }
29 }
9} 30}
10 31
11#[derive(Debug)] 32#[derive(Debug)]
@@ -35,9 +56,14 @@ impl RedNode {
35 } 56 }
36 57
37 fn new(green: GreenNode, parent: Option<ParentData>) -> RedNode { 58 fn new(green: GreenNode, parent: Option<ParentData>) -> RedNode {
38 let n_children = green.children().len(); 59 let start_offset = parent.as_ref().map(|it| it.start_offset).unwrap_or(0.into());
39 let children = (0..n_children) 60 let children = green.children()
40 .map(|_| None) 61 .iter()
62 .scan(start_offset, |start_offset, child| {
63 let res = RedChild::Zigot(*start_offset);
64 *start_offset += child.text_len();
65 Some(res)
66 })
41 .collect::<Vec<_>>() 67 .collect::<Vec<_>>()
42 .into_boxed_slice(); 68 .into_boxed_slice();
43 RedNode { 69 RedNode {
@@ -66,23 +92,16 @@ impl RedNode {
66 if idx >= self.n_children() { 92 if idx >= self.n_children() {
67 return None; 93 return None;
68 } 94 }
69 match &self.children.read()[idx] { 95 let start_offset = match &self.children.read()[idx] {
70 Some(child) => return Some(RedPtr::new(child)), 96 RedChild::Child(child) => return Some(RedPtr::new(child)),
71 None => (), 97 RedChild::Zigot(start_offset) => *start_offset,
72 }; 98 };
73 let green_children = self.green.children(); 99 let green_children = self.green.children();
74 let start_offset = self.start_offset()
75 + green_children[..idx]
76 .iter()
77 .map(|x| x.text_len())
78 .sum::<TextUnit>();
79 let child = 100 let child =
80 RedNode::new_child(green_children[idx].clone(), RedPtr::new(self), start_offset, idx); 101 RedNode::new_child(green_children[idx].clone(), RedPtr::new(self), start_offset, idx);
81 let mut children = self.children.write(); 102 let mut children = self.children.write();
82 if children[idx].is_none() { 103 let child = children[idx].set(child);
83 children[idx] = Some(child) 104 Some(RedPtr::new(child))
84 }
85 Some(RedPtr::new(children[idx].as_ref().unwrap()))
86 } 105 }
87 106
88 pub(crate) fn parent(&self) -> Option<RedPtr> { 107 pub(crate) fn parent(&self) -> Option<RedPtr> {