diff options
author | Aleksey Kladov <[email protected]> | 2018-07-29 14:19:16 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-07-29 14:19:16 +0100 |
commit | 13c6a5c4b02d6436e4197c3ca93a8a5c3112a967 (patch) | |
tree | efaeaedca21c1727976a1aa67e2c76b13feccd18 /src/yellow/green.rs | |
parent | 415c891d641fa305e7ddbbbcc78db990dd5d3564 (diff) |
Avoid optimizing trivia for now
Diffstat (limited to 'src/yellow/green.rs')
-rw-r--r-- | src/yellow/green.rs | 236 |
1 files changed, 104 insertions, 132 deletions
diff --git a/src/yellow/green.rs b/src/yellow/green.rs index dafe1bb22..cb9dff128 100644 --- a/src/yellow/green.rs +++ b/src/yellow/green.rs | |||
@@ -1,187 +1,159 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | use text_unit::TextUnit; | 2 | use {SyntaxKind::{self, *}, TextUnit}; |
3 | use SyntaxKind; | ||
4 | 3 | ||
5 | type TokenText = String; | 4 | #[derive(Clone, Debug)] |
6 | 5 | pub(crate) enum GreenNode { | |
7 | #[derive(Debug)] | 6 | Leaf(GreenLeaf), |
8 | pub(crate) struct GreenNode { | 7 | Branch(Arc<GreenBranch>), |
9 | kind: SyntaxKind, | ||
10 | data: GreenNodeData, | ||
11 | } | 8 | } |
12 | 9 | ||
13 | impl GreenNode { | 10 | impl GreenNode { |
14 | pub(crate) fn new_leaf(kind: SyntaxKind, text: TokenText) -> GreenNode { | 11 | pub fn kind(&self) -> SyntaxKind { |
15 | GreenNode { | 12 | match self { |
16 | kind, | 13 | GreenNode::Leaf(l) => l.kind(), |
17 | data: GreenNodeData::Leaf(GreenLeaf { text }), | 14 | GreenNode::Branch(b) => b.kind(), |
18 | } | 15 | } |
19 | } | 16 | } |
20 | 17 | ||
21 | pub(crate) fn new_branch( | 18 | pub fn text_len(&self) -> TextUnit { |
22 | kind: SyntaxKind, | 19 | match self { |
23 | ) -> GreenNode { | 20 | GreenNode::Leaf(l) => l.text_len(), |
24 | let branch = GreenBranch { | 21 | GreenNode::Branch(b) => b.text_len(), |
25 | text_len: 0.into(), | ||
26 | leading_trivia: Trivias::default(), | ||
27 | children: Vec::new(), | ||
28 | }; | ||
29 | GreenNode { | ||
30 | kind, | ||
31 | data: GreenNodeData::Branch(branch), | ||
32 | } | 22 | } |
33 | } | 23 | } |
34 | 24 | ||
35 | pub(crate) fn push_trivia(&mut self, kind: SyntaxKind, text: TokenText) { | 25 | pub fn children(&self) -> &[GreenNode] { |
36 | let branch = match &mut self.data { | 26 | match self { |
37 | GreenNodeData::Branch(branch) => branch, | 27 | GreenNode::Leaf(_) => &[], |
38 | _ => panic!() | 28 | GreenNode::Branch(b) => b.children(), |
39 | }; | ||
40 | branch.text_len += TextUnit::of_str(&text); | ||
41 | let leading = &mut branch.leading_trivia; | ||
42 | branch.children.last_mut().map(|(_, t)| t).unwrap_or(leading) | ||
43 | .push(Arc::new(GreenTrivia { kind, text })); | ||
44 | } | ||
45 | |||
46 | pub(crate) fn push_child(&mut self, node: Arc<GreenNode>) { | ||
47 | let branch = match &mut self.data { | ||
48 | GreenNodeData::Branch(branch) => branch, | ||
49 | _ => panic!() | ||
50 | }; | ||
51 | branch.text_len += node.text_len(); | ||
52 | branch.children.push((node, Trivias::default())); | ||
53 | } | ||
54 | |||
55 | pub(crate) fn kind(&self) -> SyntaxKind { | ||
56 | self.kind | ||
57 | } | ||
58 | |||
59 | pub(crate) fn text_len(&self) -> TextUnit { | ||
60 | match &self.data { | ||
61 | GreenNodeData::Leaf(l) => l.text_len(), | ||
62 | GreenNodeData::Branch(b) => b.text_len(), | ||
63 | } | 29 | } |
64 | } | 30 | } |
65 | 31 | ||
66 | pub(crate) fn text(&self) -> String { | 32 | pub fn text(&self) -> String { |
67 | let mut buff = String::new(); | 33 | let mut buff = String::new(); |
68 | go(self, &mut buff); | 34 | go(self, &mut buff); |
69 | return buff; | 35 | return buff; |
70 | fn go(node: &GreenNode, buff: &mut String) { | 36 | fn go(node: &GreenNode, buff: &mut String) { |
71 | match &node.data { | 37 | match node { |
72 | GreenNodeData::Leaf(l) => buff.push_str(&l.text), | 38 | GreenNode::Leaf(l) => buff.push_str(&l.text()), |
73 | GreenNodeData::Branch(branch) => { | 39 | GreenNode::Branch(b) => { |
74 | add_trivia(&branch.leading_trivia, buff); | 40 | b.children().iter().for_each(|child| go(child, buff)) |
75 | branch.children.iter().for_each(|(child, trivias)| { | ||
76 | go(child, buff); | ||
77 | add_trivia(trivias, buff); | ||
78 | }) | ||
79 | } | 41 | } |
80 | } | 42 | } |
81 | } | 43 | } |
82 | |||
83 | fn add_trivia(trivias: &Trivias, buff: &mut String) { | ||
84 | trivias.iter().for_each(|t| buff.push_str(&t.text)) | ||
85 | } | ||
86 | } | 44 | } |
45 | } | ||
87 | 46 | ||
88 | pub(crate) fn n_children(&self) -> usize { | 47 | pub(crate) struct GreenNodeBuilder { |
89 | match &self.data { | 48 | kind: SyntaxKind, |
90 | GreenNodeData::Leaf(_) => 0, | 49 | children: Vec<GreenNode>, |
91 | GreenNodeData::Branch(branch) => branch.children.len(), | 50 | } |
92 | } | ||
93 | } | ||
94 | 51 | ||
95 | pub(crate) fn nth_child(&self, idx: usize) -> &Arc<GreenNode> { | 52 | impl GreenNodeBuilder { |
96 | match &self.data { | 53 | pub(crate) fn new_leaf(kind: SyntaxKind, text: &str) -> GreenNode { |
97 | GreenNodeData::Leaf(_) => panic!("leaf nodes have no children"), | 54 | GreenNode::Leaf(GreenLeaf::new(kind, text)) |
98 | GreenNodeData::Branch(branch) => &branch.children[idx].0, | ||
99 | } | ||
100 | } | 55 | } |
101 | 56 | ||
102 | pub(crate) fn nth_trivias(&self, idx: usize) -> &Trivias { | 57 | pub(crate) fn new_internal(kind: SyntaxKind) -> GreenNodeBuilder { |
103 | match &self.data { | 58 | GreenNodeBuilder { |
104 | GreenNodeData::Leaf(_) => panic!("leaf nodes have no children"), | 59 | kind, |
105 | GreenNodeData::Branch(branch) => if idx == 0 { | 60 | children: Vec::new(), |
106 | &branch.leading_trivia | ||
107 | } else { | ||
108 | &branch.children[idx - 1].1 | ||
109 | }, | ||
110 | } | 61 | } |
111 | } | 62 | } |
112 | 63 | ||
113 | pub(crate) fn is_leaf(&self) -> bool { | 64 | pub(crate) fn push_child(&mut self, node: GreenNode) { |
114 | match self.data { | 65 | self.children.push(node) |
115 | GreenNodeData::Leaf(_) => true, | ||
116 | GreenNodeData::Branch(_) => false | ||
117 | } | ||
118 | } | 66 | } |
119 | } | ||
120 | 67 | ||
121 | #[derive(Debug)] | 68 | pub(crate) fn build(self) -> GreenNode { |
122 | enum GreenNodeData { | 69 | let branch = GreenBranch::new(self.kind, self.children); |
123 | Leaf(GreenLeaf), | 70 | GreenNode::Branch(Arc::new(branch)) |
124 | Branch(GreenBranch), | 71 | } |
125 | } | 72 | } |
126 | 73 | ||
127 | #[derive(Debug)] | ||
128 | struct GreenLeaf { | ||
129 | text: TokenText | ||
130 | } | ||
131 | 74 | ||
132 | #[derive(Debug)] | 75 | #[test] |
133 | struct GreenBranch { | 76 | fn assert_send_sync() { |
134 | text_len: TextUnit, | 77 | fn f<T: Send + Sync>() {} |
135 | leading_trivia: Trivias, | 78 | f::<GreenNode>(); |
136 | children: Vec<(Arc<GreenNode>, Trivias)>, | ||
137 | } | 79 | } |
138 | 80 | ||
139 | #[derive(Debug)] | 81 | #[derive(Clone, Debug)] |
140 | pub(crate) struct GreenTrivia { | 82 | pub(crate) enum GreenLeaf { |
141 | pub(crate) kind: SyntaxKind, | 83 | Whitespace { |
142 | pub(crate) text: TokenText, | 84 | newlines: u8, |
85 | spaces: u8, | ||
86 | }, | ||
87 | Token { | ||
88 | kind: SyntaxKind, | ||
89 | text: Arc<str>, | ||
90 | }, | ||
143 | } | 91 | } |
144 | 92 | ||
145 | type Trivias = Vec<Arc<GreenTrivia>>; | 93 | impl GreenLeaf { |
94 | fn new(kind: SyntaxKind, text: &str) -> Self { | ||
95 | if kind == WHITESPACE { | ||
96 | let newlines = text.bytes().take_while(|&b| b == b'\n').count(); | ||
97 | let spaces = text[newlines..].bytes().take_while(|&b| b == b' ').count(); | ||
98 | if newlines + spaces == text.len() && newlines <= N_NEWLINES && spaces <= N_SPACES { | ||
99 | return GreenLeaf::Whitespace { newlines: newlines as u8, spaces: spaces as u8 }; | ||
100 | } | ||
101 | } | ||
102 | GreenLeaf::Token { kind, text: text.to_owned().into_boxed_str().into() } | ||
103 | } | ||
146 | 104 | ||
105 | pub(crate) fn kind(&self) -> SyntaxKind { | ||
106 | match self { | ||
107 | GreenLeaf::Whitespace { .. } => WHITESPACE, | ||
108 | GreenLeaf::Token { kind, .. } => *kind, | ||
109 | } | ||
110 | } | ||
147 | 111 | ||
148 | pub(crate) trait TextLen { | 112 | pub(crate) fn text(&self) -> &str { |
149 | fn text_len(&self) -> TextUnit; | 113 | match self { |
150 | } | 114 | &GreenLeaf::Whitespace { newlines, spaces } => { |
115 | let newlines = newlines as usize; | ||
116 | let spaces = spaces as usize; | ||
117 | assert!(newlines <= N_NEWLINES && spaces <= N_SPACES); | ||
118 | &WS[N_NEWLINES - newlines..N_NEWLINES + spaces] | ||
119 | } | ||
120 | GreenLeaf::Token { text, .. } => text, | ||
121 | } | ||
122 | } | ||
151 | 123 | ||
152 | impl TextLen for GreenTrivia { | 124 | pub(crate) fn text_len(&self) -> TextUnit { |
153 | fn text_len(&self) -> TextUnit { | 125 | TextUnit::of_str(self.text()) |
154 | TextUnit::of_str(&self.text) | ||
155 | } | 126 | } |
156 | } | 127 | } |
157 | 128 | ||
158 | impl<T: TextLen> TextLen for Arc<T> { | 129 | const N_NEWLINES: usize = 16; |
159 | fn text_len(&self) -> TextUnit { | 130 | const N_SPACES: usize = 64; |
160 | let this: &T = self; | 131 | const WS: &str = |
161 | this.text_len() | 132 | "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n "; |
162 | } | 133 | |
134 | #[derive(Clone, Debug)] | ||
135 | pub(crate) struct GreenBranch { | ||
136 | text_len: TextUnit, | ||
137 | kind: SyntaxKind, | ||
138 | children: Vec<GreenNode>, | ||
163 | } | 139 | } |
164 | 140 | ||
165 | impl TextLen for GreenNode { | 141 | impl GreenBranch { |
166 | fn text_len(&self) -> TextUnit { | 142 | fn new(kind: SyntaxKind, children: Vec<GreenNode>) -> GreenBranch { |
167 | self.text_len() | 143 | let text_len = children.iter().map(|x| x.text_len()).sum::<TextUnit>(); |
144 | GreenBranch { text_len, kind, children } | ||
168 | } | 145 | } |
169 | } | ||
170 | 146 | ||
171 | impl TextLen for GreenLeaf { | 147 | pub fn kind(&self) -> SyntaxKind { |
172 | fn text_len(&self) -> TextUnit { | 148 | self.kind |
173 | TextUnit::of_str(&self.text) | ||
174 | } | 149 | } |
175 | } | ||
176 | 150 | ||
177 | impl TextLen for GreenBranch { | 151 | pub fn text_len(&self) -> TextUnit { |
178 | fn text_len(&self) -> TextUnit { | ||
179 | self.text_len | 152 | self.text_len |
180 | } | 153 | } |
181 | } | ||
182 | 154 | ||
183 | impl<T: TextLen> TextLen for [T] { | 155 | pub fn children(&self) -> &[GreenNode] { |
184 | fn text_len(&self) -> TextUnit { | 156 | self.children.as_slice() |
185 | self.iter().map(TextLen::text_len).sum() | ||
186 | } | 157 | } |
187 | } | 158 | } |
159 | |||