1 | use std::{ |
2 | borrow::{Borrow, Cow}, |
3 | fmt, |
4 | iter::{self, FusedIterator}, |
5 | mem::{self, ManuallyDrop}, |
6 | ops, ptr, slice, |
7 | }; |
8 | |
9 | use countme::Count; |
10 | |
11 | use crate::{ |
12 | arc::{Arc, HeaderSlice, ThinArc}, |
13 | green::{GreenElement, GreenElementRef, SyntaxKind}, |
14 | utility_types::static_assert, |
15 | GreenToken, NodeOrToken, TextRange, TextSize, |
16 | }; |
17 | |
18 | #[derive (Debug, Clone, PartialEq, Eq, Hash)] |
19 | pub(super) struct GreenNodeHead { |
20 | kind: SyntaxKind, |
21 | text_len: TextSize, |
22 | _c: Count<GreenNode>, |
23 | } |
24 | |
25 | #[derive (Debug, Clone, PartialEq, Eq, Hash)] |
26 | pub(crate) enum GreenChild { |
27 | Node { rel_offset: TextSize, node: GreenNode }, |
28 | Token { rel_offset: TextSize, token: GreenToken }, |
29 | } |
30 | #[cfg (target_pointer_width = "64" )] |
31 | static_assert!(mem::size_of::<GreenChild>() == mem::size_of::<usize>() * 2); |
32 | |
33 | type Repr = HeaderSlice<GreenNodeHead, [GreenChild]>; |
34 | type ReprThin = HeaderSlice<GreenNodeHead, [GreenChild; 0]>; |
35 | #[repr (transparent)] |
36 | pub struct GreenNodeData { |
37 | data: ReprThin, |
38 | } |
39 | |
40 | impl PartialEq for GreenNodeData { |
41 | fn eq(&self, other: &Self) -> bool { |
42 | self.header() == other.header() && self.slice() == other.slice() |
43 | } |
44 | } |
45 | |
46 | /// Internal node in the immutable tree. |
47 | /// It has other nodes and tokens as children. |
48 | #[derive (Clone, PartialEq, Eq, Hash)] |
49 | #[repr (transparent)] |
50 | pub struct GreenNode { |
51 | ptr: ThinArc<GreenNodeHead, GreenChild>, |
52 | } |
53 | |
54 | impl ToOwned for GreenNodeData { |
55 | type Owned = GreenNode; |
56 | |
57 | #[inline ] |
58 | fn to_owned(&self) -> GreenNode { |
59 | let green: GreenNode = unsafe { GreenNode::from_raw(ptr:ptr::NonNull::from(self)) }; |
60 | let green: ManuallyDrop = ManuallyDrop::new(green); |
61 | GreenNode::clone(&green) |
62 | } |
63 | } |
64 | |
65 | impl Borrow<GreenNodeData> for GreenNode { |
66 | #[inline ] |
67 | fn borrow(&self) -> &GreenNodeData { |
68 | &*self |
69 | } |
70 | } |
71 | |
72 | impl From<Cow<'_, GreenNodeData>> for GreenNode { |
73 | #[inline ] |
74 | fn from(cow: Cow<'_, GreenNodeData>) -> Self { |
75 | cow.into_owned() |
76 | } |
77 | } |
78 | |
79 | impl fmt::Debug for GreenNodeData { |
80 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
81 | f&mut DebugStruct<'_, '_>.debug_struct("GreenNode" ) |
82 | .field("kind" , &self.kind()) |
83 | .field("text_len" , &self.text_len()) |
84 | .field(name:"n_children" , &self.children().len()) |
85 | .finish() |
86 | } |
87 | } |
88 | |
89 | impl fmt::Debug for GreenNode { |
90 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
91 | let data: &GreenNodeData = &*self; |
92 | fmt::Debug::fmt(self:data, f) |
93 | } |
94 | } |
95 | |
96 | impl fmt::Display for GreenNode { |
97 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
98 | let data: &GreenNodeData = &*self; |
99 | fmt::Display::fmt(self:data, f) |
100 | } |
101 | } |
102 | |
103 | impl fmt::Display for GreenNodeData { |
104 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
105 | for child: NodeOrToken<&GreenNodeData, …> in self.children() { |
106 | write!(f, " {}" , child)?; |
107 | } |
108 | Ok(()) |
109 | } |
110 | } |
111 | |
112 | impl GreenNodeData { |
113 | #[inline ] |
114 | fn header(&self) -> &GreenNodeHead { |
115 | &self.data.header |
116 | } |
117 | |
118 | #[inline ] |
119 | fn slice(&self) -> &[GreenChild] { |
120 | self.data.slice() |
121 | } |
122 | |
123 | /// Kind of this node. |
124 | #[inline ] |
125 | pub fn kind(&self) -> SyntaxKind { |
126 | self.header().kind |
127 | } |
128 | |
129 | /// Returns the length of the text covered by this node. |
130 | #[inline ] |
131 | pub fn text_len(&self) -> TextSize { |
132 | self.header().text_len |
133 | } |
134 | |
135 | /// Children of this node. |
136 | #[inline ] |
137 | pub fn children(&self) -> Children<'_> { |
138 | Children { raw: self.slice().iter() } |
139 | } |
140 | |
141 | pub(crate) fn child_at_range( |
142 | &self, |
143 | rel_range: TextRange, |
144 | ) -> Option<(usize, TextSize, GreenElementRef<'_>)> { |
145 | let idx = self |
146 | .slice() |
147 | .binary_search_by(|it| { |
148 | let child_range = it.rel_range(); |
149 | TextRange::ordering(child_range, rel_range) |
150 | }) |
151 | // XXX: this handles empty ranges |
152 | .unwrap_or_else(|it| it.saturating_sub(1)); |
153 | let child = &self.slice().get(idx).filter(|it| it.rel_range().contains_range(rel_range))?; |
154 | Some((idx, child.rel_offset(), child.as_ref())) |
155 | } |
156 | |
157 | #[must_use ] |
158 | pub fn replace_child(&self, index: usize, new_child: GreenElement) -> GreenNode { |
159 | let mut replacement = Some(new_child); |
160 | let children = self.children().enumerate().map(|(i, child)| { |
161 | if i == index { |
162 | replacement.take().unwrap() |
163 | } else { |
164 | child.to_owned() |
165 | } |
166 | }); |
167 | GreenNode::new(self.kind(), children) |
168 | } |
169 | #[must_use ] |
170 | pub fn insert_child(&self, index: usize, new_child: GreenElement) -> GreenNode { |
171 | // https://github.com/rust-lang/rust/issues/34433 |
172 | self.splice_children(index..index, iter::once(new_child)) |
173 | } |
174 | #[must_use ] |
175 | pub fn remove_child(&self, index: usize) -> GreenNode { |
176 | self.splice_children(index..=index, iter::empty()) |
177 | } |
178 | #[must_use ] |
179 | pub fn splice_children<R, I>(&self, range: R, replace_with: I) -> GreenNode |
180 | where |
181 | R: ops::RangeBounds<usize>, |
182 | I: IntoIterator<Item = GreenElement>, |
183 | { |
184 | let mut children: Vec<_> = self.children().map(|it| it.to_owned()).collect(); |
185 | children.splice(range, replace_with); |
186 | GreenNode::new(self.kind(), children) |
187 | } |
188 | } |
189 | |
190 | impl ops::Deref for GreenNode { |
191 | type Target = GreenNodeData; |
192 | |
193 | #[inline ] |
194 | fn deref(&self) -> &GreenNodeData { |
195 | let repr: &Repr = &self.ptr; |
196 | unsafe { |
197 | let repr: &ReprThin = &*(repr as *const Repr as *const ReprThin); |
198 | mem::transmute::<&ReprThin, &GreenNodeData>(src:repr) |
199 | } |
200 | } |
201 | } |
202 | |
203 | impl GreenNode { |
204 | /// Creates new Node. |
205 | #[inline ] |
206 | pub fn new<I>(kind: SyntaxKind, children: I) -> GreenNode |
207 | where |
208 | I: IntoIterator<Item = GreenElement>, |
209 | I::IntoIter: ExactSizeIterator, |
210 | { |
211 | let mut text_len: TextSize = 0.into(); |
212 | let children = children.into_iter().map(|el| { |
213 | let rel_offset = text_len; |
214 | text_len += el.text_len(); |
215 | match el { |
216 | NodeOrToken::Node(node) => GreenChild::Node { rel_offset, node }, |
217 | NodeOrToken::Token(token) => GreenChild::Token { rel_offset, token }, |
218 | } |
219 | }); |
220 | |
221 | let data = ThinArc::from_header_and_iter( |
222 | GreenNodeHead { kind, text_len: 0.into(), _c: Count::new() }, |
223 | children, |
224 | ); |
225 | |
226 | // XXX: fixup `text_len` after construction, because we can't iterate |
227 | // `children` twice. |
228 | let data = { |
229 | let mut data = Arc::from_thin(data); |
230 | Arc::get_mut(&mut data).unwrap().header.text_len = text_len; |
231 | Arc::into_thin(data) |
232 | }; |
233 | |
234 | GreenNode { ptr: data } |
235 | } |
236 | |
237 | #[inline ] |
238 | pub(crate) fn into_raw(this: GreenNode) -> ptr::NonNull<GreenNodeData> { |
239 | let green = ManuallyDrop::new(this); |
240 | let green: &GreenNodeData = &*green; |
241 | ptr::NonNull::from(&*green) |
242 | } |
243 | |
244 | #[inline ] |
245 | pub(crate) unsafe fn from_raw(ptr: ptr::NonNull<GreenNodeData>) -> GreenNode { |
246 | let arc = Arc::from_raw(&ptr.as_ref().data as *const ReprThin); |
247 | let arc = mem::transmute::<Arc<ReprThin>, ThinArc<GreenNodeHead, GreenChild>>(arc); |
248 | GreenNode { ptr: arc } |
249 | } |
250 | } |
251 | |
252 | impl GreenChild { |
253 | #[inline ] |
254 | pub(crate) fn as_ref(&self) -> GreenElementRef { |
255 | match self { |
256 | GreenChild::Node { node: &GreenNode, .. } => NodeOrToken::Node(node), |
257 | GreenChild::Token { token: &GreenToken, .. } => NodeOrToken::Token(token), |
258 | } |
259 | } |
260 | #[inline ] |
261 | pub(crate) fn rel_offset(&self) -> TextSize { |
262 | match self { |
263 | GreenChild::Node { rel_offset: &TextSize, .. } | GreenChild::Token { rel_offset: &TextSize, .. } => { |
264 | *rel_offset |
265 | } |
266 | } |
267 | } |
268 | #[inline ] |
269 | fn rel_range(&self) -> TextRange { |
270 | let len: TextSize = self.as_ref().text_len(); |
271 | TextRange::at(self.rel_offset(), len) |
272 | } |
273 | } |
274 | |
275 | #[derive (Debug, Clone)] |
276 | pub struct Children<'a> { |
277 | pub(crate) raw: slice::Iter<'a, GreenChild>, |
278 | } |
279 | |
280 | // NB: forward everything stable that iter::Slice specializes as of Rust 1.39.0 |
281 | impl ExactSizeIterator for Children<'_> { |
282 | #[inline (always)] |
283 | fn len(&self) -> usize { |
284 | self.raw.len() |
285 | } |
286 | } |
287 | |
288 | impl<'a> Iterator for Children<'a> { |
289 | type Item = GreenElementRef<'a>; |
290 | |
291 | #[inline ] |
292 | fn next(&mut self) -> Option<GreenElementRef<'a>> { |
293 | self.raw.next().map(GreenChild::as_ref) |
294 | } |
295 | |
296 | #[inline ] |
297 | fn size_hint(&self) -> (usize, Option<usize>) { |
298 | self.raw.size_hint() |
299 | } |
300 | |
301 | #[inline ] |
302 | fn count(self) -> usize |
303 | where |
304 | Self: Sized, |
305 | { |
306 | self.raw.count() |
307 | } |
308 | |
309 | #[inline ] |
310 | fn nth(&mut self, n: usize) -> Option<Self::Item> { |
311 | self.raw.nth(n).map(GreenChild::as_ref) |
312 | } |
313 | |
314 | #[inline ] |
315 | fn last(mut self) -> Option<Self::Item> |
316 | where |
317 | Self: Sized, |
318 | { |
319 | self.next_back() |
320 | } |
321 | |
322 | #[inline ] |
323 | fn fold<Acc, Fold>(mut self, init: Acc, mut f: Fold) -> Acc |
324 | where |
325 | Fold: FnMut(Acc, Self::Item) -> Acc, |
326 | { |
327 | let mut accum = init; |
328 | while let Some(x) = self.next() { |
329 | accum = f(accum, x); |
330 | } |
331 | accum |
332 | } |
333 | } |
334 | |
335 | impl<'a> DoubleEndedIterator for Children<'a> { |
336 | #[inline ] |
337 | fn next_back(&mut self) -> Option<Self::Item> { |
338 | self.raw.next_back().map(GreenChild::as_ref) |
339 | } |
340 | |
341 | #[inline ] |
342 | fn nth_back(&mut self, n: usize) -> Option<Self::Item> { |
343 | self.raw.nth_back(n).map(GreenChild::as_ref) |
344 | } |
345 | |
346 | #[inline ] |
347 | fn rfold<Acc, Fold>(mut self, init: Acc, mut f: Fold) -> Acc |
348 | where |
349 | Fold: FnMut(Acc, Self::Item) -> Acc, |
350 | { |
351 | let mut accum: Acc = init; |
352 | while let Some(x: NodeOrToken<&'a GreenNodeData, …>) = self.next_back() { |
353 | accum = f(accum, x); |
354 | } |
355 | accum |
356 | } |
357 | } |
358 | |
359 | impl FusedIterator for Children<'_> {} |
360 | |