diff options
-rw-r--r-- | crates/libsyntax2/src/yellow/red.rs | 51 |
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}; | |||
5 | pub(crate) struct RedNode { | 5 | pub(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)] | ||
12 | enum RedChild { | ||
13 | Zigot(TextUnit), | ||
14 | Child(RedNode) | ||
15 | } | ||
16 | |||
17 | impl 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> { |