aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/yellow/red.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/yellow/red.rs')
-rw-r--r--crates/ra_syntax/src/yellow/red.rs113
1 files changed, 113 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/yellow/red.rs b/crates/ra_syntax/src/yellow/red.rs
new file mode 100644
index 000000000..84cfe4fba
--- /dev/null
+++ b/crates/ra_syntax/src/yellow/red.rs
@@ -0,0 +1,113 @@
1use parking_lot::RwLock;
2use {yellow::{GreenNode, RedPtr}, TextUnit};
3
4#[derive(Debug)]
5pub(crate) struct RedNode {
6 green: GreenNode,
7 parent: Option<ParentData>,
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 }
30}
31
32#[derive(Debug)]
33struct ParentData {
34 parent: RedPtr,
35 start_offset: TextUnit,
36 index_in_parent: usize,
37}
38
39impl RedNode {
40 pub fn new_root(green: GreenNode) -> RedNode {
41 RedNode::new(green, None)
42 }
43
44 fn new_child(
45 green: GreenNode,
46 parent: RedPtr,
47 start_offset: TextUnit,
48 index_in_parent: usize,
49 ) -> RedNode {
50 let parent_data = ParentData {
51 parent,
52 start_offset,
53 index_in_parent,
54 };
55 RedNode::new(green, Some(parent_data))
56 }
57
58 fn new(green: GreenNode, parent: Option<ParentData>) -> RedNode {
59 let mut start_offset = parent.as_ref().map(|it| it.start_offset).unwrap_or(0.into());
60 let children = green.children()
61 .iter()
62 .map(|child| {
63 let off = start_offset;
64 start_offset += child.text_len();
65 RedChild::Zigot(off)
66 })
67 .collect::<Vec<_>>()
68 .into_boxed_slice();
69 RedNode {
70 green,
71 parent,
72 children: RwLock::new(children),
73 }
74 }
75
76 pub(crate) fn green(&self) -> &GreenNode {
77 &self.green
78 }
79
80 pub(crate) fn start_offset(&self) -> TextUnit {
81 match &self.parent {
82 None => 0.into(),
83 Some(p) => p.start_offset,
84 }
85 }
86
87 pub(crate) fn n_children(&self) -> usize {
88 self.green.children().len()
89 }
90
91 pub(crate) fn get_child(&self, idx: usize) -> Option<RedPtr> {
92 if idx >= self.n_children() {
93 return None;
94 }
95 let start_offset = match &self.children.read()[idx] {
96 RedChild::Child(child) => return Some(RedPtr::new(child)),
97 RedChild::Zigot(start_offset) => *start_offset,
98 };
99 let green_children = self.green.children();
100 let child =
101 RedNode::new_child(green_children[idx].clone(), RedPtr::new(self), start_offset, idx);
102 let mut children = self.children.write();
103 let child = children[idx].set(child);
104 Some(RedPtr::new(child))
105 }
106
107 pub(crate) fn parent(&self) -> Option<RedPtr> {
108 Some(self.parent.as_ref()?.parent)
109 }
110 pub(crate) fn index_in_parent(&self) -> Option<usize> {
111 Some(self.parent.as_ref()?.index_in_parent)
112 }
113}