1 | //! Implementation of the cursors -- API for convenient access to syntax trees. |
2 | //! |
3 | //! Functional programmers will recognize that this module implements a zipper |
4 | //! for a purely functional (green) tree. |
5 | //! |
6 | //! A cursor node (`SyntaxNode`) points to a `GreenNode` and a parent |
7 | //! `SyntaxNode`. This allows cursor to provide iteration over both ancestors |
8 | //! and descendants, as well as a cheep access to absolute offset of the node in |
9 | //! file. |
10 | //! |
11 | //! By default `SyntaxNode`s are immutable, but you can get a mutable copy of |
12 | //! the tree by calling `clone_for_update`. Mutation is based on interior |
13 | //! mutability and doesn't need `&mut`. You can have two `SyntaxNode`s pointing |
14 | //! at different parts of the same tree; mutations via the first node will be |
15 | //! reflected in the other. |
16 | |
17 | // Implementation notes: |
18 | // |
19 | // The implementation is utterly and horribly unsafe. This whole module is an |
20 | // unsafety boundary. It is believed that the API here is, in principle, sound, |
21 | // but the implementation might have bugs. |
22 | // |
23 | // The core type is `NodeData` -- a heap-allocated reference counted object, |
24 | // which points to a green node or a green token, and to the parent `NodeData`. |
25 | // Publicly-exposed `SyntaxNode` and `SyntaxToken` own a reference to |
26 | // `NodeData`. |
27 | // |
28 | // `NodeData`s are transient, and are created and destroyed during tree |
29 | // traversals. In general, only currently referenced nodes and their ancestors |
30 | // are alive at any given moment. |
31 | // |
32 | // More specifically, `NodeData`'s ref count is equal to the number of |
33 | // outstanding `SyntaxNode` and `SyntaxToken` plus the number of children with |
34 | // non-zero ref counts. For example, if the user has only a single `SyntaxNode` |
35 | // pointing somewhere in the middle of the tree, then all `NodeData` on the path |
36 | // from that point towards the root have ref count equal to one. |
37 | // |
38 | // `NodeData` which doesn't have a parent (is a root) owns the corresponding |
39 | // green node or token, and is responsible for freeing it. |
40 | // |
41 | // That's mostly it for the immutable subset of the API. Mutation is fun though, |
42 | // you'll like it! |
43 | // |
44 | // Mutability is a run-time property of a tree of `NodeData`. The whole tree is |
45 | // either mutable or immutable. `clone_for_update` clones the whole tree of |
46 | // `NodeData`s, making it mutable (note that the green tree is re-used). |
47 | // |
48 | // If the tree is mutable, then all live `NodeData` are additionally liked to |
49 | // each other via intrusive liked lists. Specifically, there are two pointers to |
50 | // siblings, as well as a pointer to the first child. Note that only live nodes |
51 | // are considered. If the user only has `SyntaxNode`s for the first and last |
52 | // children of some particular node, then their `NodeData` will point at each |
53 | // other. |
54 | // |
55 | // The links are used to propagate mutations across the tree. Specifically, each |
56 | // `NodeData` remembers it's index in parent. When the node is detached from or |
57 | // attached to the tree, we need to adjust the indices of all subsequent |
58 | // siblings. That's what makes the `for c in node.children() { c.detach() }` |
59 | // pattern work despite the apparent iterator invalidation. |
60 | // |
61 | // This code is encapsulated into the sorted linked list (`sll`) module. |
62 | // |
63 | // The actual mutation consist of functionally "mutating" (creating a |
64 | // structurally shared copy) the green node, and then re-spinning the tree. This |
65 | // is a delicate process: `NodeData` point directly to the green nodes, so we |
66 | // must make sure that those nodes don't move. Additionally, during mutation a |
67 | // node might become or might stop being a root, so we must take care to not |
68 | // double free / leak its green node. |
69 | // |
70 | // Because we can change green nodes using only shared references, handing out |
71 | // references into green nodes in the public API would be unsound. We don't do |
72 | // that, but we do use such references internally a lot. Additionally, for |
73 | // tokens the underlying green token actually is immutable, so we can, and do |
74 | // return `&str`. |
75 | // |
76 | // Invariants [must not leak outside of the module]: |
77 | // - Mutability is the property of the whole tree. Intermixing elements that |
78 | // differ in mutability is not allowed. |
79 | // - Mutability property is persistent. |
80 | // - References to the green elements' data are not exposed into public API |
81 | // when the tree is mutable. |
82 | // - TBD |
83 | |
84 | use std::{ |
85 | borrow::Cow, |
86 | cell::Cell, |
87 | fmt, |
88 | hash::{Hash, Hasher}, |
89 | iter, |
90 | mem::{self, ManuallyDrop}, |
91 | ops::Range, |
92 | ptr, slice, |
93 | }; |
94 | |
95 | use countme::Count; |
96 | |
97 | use crate::{ |
98 | green::{GreenChild, GreenElementRef, GreenNodeData, GreenTokenData, SyntaxKind}, |
99 | sll, |
100 | utility_types::Delta, |
101 | Direction, GreenNode, GreenToken, NodeOrToken, SyntaxText, TextRange, TextSize, TokenAtOffset, |
102 | WalkEvent, |
103 | }; |
104 | |
105 | enum Green { |
106 | Node { ptr: Cell<ptr::NonNull<GreenNodeData>> }, |
107 | Token { ptr: ptr::NonNull<GreenTokenData> }, |
108 | } |
109 | |
110 | struct _SyntaxElement; |
111 | |
112 | struct NodeData { |
113 | _c: Count<_SyntaxElement>, |
114 | |
115 | rc: Cell<u32>, |
116 | parent: Cell<Option<ptr::NonNull<NodeData>>>, |
117 | index: Cell<u32>, |
118 | green: Green, |
119 | |
120 | /// Invariant: never changes after NodeData is created. |
121 | mutable: bool, |
122 | /// Absolute offset for immutable nodes, unused for mutable nodes. |
123 | offset: TextSize, |
124 | // The following links only have meaning when `mutable` is true. |
125 | first: Cell<*const NodeData>, |
126 | /// Invariant: never null if mutable. |
127 | next: Cell<*const NodeData>, |
128 | /// Invariant: never null if mutable. |
129 | prev: Cell<*const NodeData>, |
130 | } |
131 | |
132 | unsafe impl sll::Elem for NodeData { |
133 | fn prev(&self) -> &Cell<*const Self> { |
134 | &self.prev |
135 | } |
136 | fn next(&self) -> &Cell<*const Self> { |
137 | &self.next |
138 | } |
139 | fn key(&self) -> &Cell<u32> { |
140 | &self.index |
141 | } |
142 | } |
143 | |
144 | pub type SyntaxElement = NodeOrToken<SyntaxNode, SyntaxToken>; |
145 | |
146 | pub struct SyntaxNode { |
147 | ptr: ptr::NonNull<NodeData>, |
148 | } |
149 | |
150 | impl Clone for SyntaxNode { |
151 | #[inline ] |
152 | fn clone(&self) -> Self { |
153 | self.data().inc_rc(); |
154 | SyntaxNode { ptr: self.ptr } |
155 | } |
156 | } |
157 | |
158 | impl Drop for SyntaxNode { |
159 | #[inline ] |
160 | fn drop(&mut self) { |
161 | if self.data().dec_rc() { |
162 | unsafe { free(self.ptr) } |
163 | } |
164 | } |
165 | } |
166 | |
167 | #[derive (Debug)] |
168 | pub struct SyntaxToken { |
169 | ptr: ptr::NonNull<NodeData>, |
170 | } |
171 | |
172 | impl Clone for SyntaxToken { |
173 | #[inline ] |
174 | fn clone(&self) -> Self { |
175 | self.data().inc_rc(); |
176 | SyntaxToken { ptr: self.ptr } |
177 | } |
178 | } |
179 | |
180 | impl Drop for SyntaxToken { |
181 | #[inline ] |
182 | fn drop(&mut self) { |
183 | if self.data().dec_rc() { |
184 | unsafe { free(self.ptr) } |
185 | } |
186 | } |
187 | } |
188 | |
189 | #[inline (never)] |
190 | unsafe fn free(mut data: ptr::NonNull<NodeData>) { |
191 | loop { |
192 | debug_assert_eq!(data.as_ref().rc.get(), 0); |
193 | debug_assert!(data.as_ref().first.get().is_null()); |
194 | let node = Box::from_raw(data.as_ptr()); |
195 | match node.parent.take() { |
196 | Some(parent) => { |
197 | debug_assert!(parent.as_ref().rc.get() > 0); |
198 | if node.mutable { |
199 | sll::unlink(&parent.as_ref().first, &*node) |
200 | } |
201 | if parent.as_ref().dec_rc() { |
202 | data = parent; |
203 | } else { |
204 | break; |
205 | } |
206 | } |
207 | None => { |
208 | match &node.green { |
209 | Green::Node { ptr } => { |
210 | let _ = GreenNode::from_raw(ptr.get()); |
211 | } |
212 | Green::Token { ptr } => { |
213 | let _ = GreenToken::from_raw(*ptr); |
214 | } |
215 | } |
216 | break; |
217 | } |
218 | } |
219 | } |
220 | } |
221 | |
222 | impl NodeData { |
223 | #[inline ] |
224 | fn new( |
225 | parent: Option<SyntaxNode>, |
226 | index: u32, |
227 | offset: TextSize, |
228 | green: Green, |
229 | mutable: bool, |
230 | ) -> ptr::NonNull<NodeData> { |
231 | let parent = ManuallyDrop::new(parent); |
232 | let res = NodeData { |
233 | _c: Count::new(), |
234 | rc: Cell::new(1), |
235 | parent: Cell::new(parent.as_ref().map(|it| it.ptr)), |
236 | index: Cell::new(index), |
237 | green, |
238 | |
239 | mutable, |
240 | offset, |
241 | first: Cell::new(ptr::null()), |
242 | next: Cell::new(ptr::null()), |
243 | prev: Cell::new(ptr::null()), |
244 | }; |
245 | unsafe { |
246 | if mutable { |
247 | let res_ptr: *const NodeData = &res; |
248 | match sll::init((*res_ptr).parent().map(|it| &it.first), res_ptr.as_ref().unwrap()) |
249 | { |
250 | sll::AddToSllResult::AlreadyInSll(node) => { |
251 | if cfg!(debug_assertions) { |
252 | assert_eq!((*node).index(), (*res_ptr).index()); |
253 | match ((*node).green(), (*res_ptr).green()) { |
254 | (NodeOrToken::Node(lhs), NodeOrToken::Node(rhs)) => { |
255 | assert!(ptr::eq(lhs, rhs)) |
256 | } |
257 | (NodeOrToken::Token(lhs), NodeOrToken::Token(rhs)) => { |
258 | assert!(ptr::eq(lhs, rhs)) |
259 | } |
260 | it => { |
261 | panic!("node/token confusion: {:?}" , it) |
262 | } |
263 | } |
264 | } |
265 | |
266 | ManuallyDrop::into_inner(parent); |
267 | let res = node as *mut NodeData; |
268 | (*res).inc_rc(); |
269 | return ptr::NonNull::new_unchecked(res); |
270 | } |
271 | it => { |
272 | let res = Box::into_raw(Box::new(res)); |
273 | it.add_to_sll(res); |
274 | return ptr::NonNull::new_unchecked(res); |
275 | } |
276 | } |
277 | } |
278 | ptr::NonNull::new_unchecked(Box::into_raw(Box::new(res))) |
279 | } |
280 | } |
281 | |
282 | #[inline ] |
283 | fn inc_rc(&self) { |
284 | let rc = match self.rc.get().checked_add(1) { |
285 | Some(it) => it, |
286 | None => std::process::abort(), |
287 | }; |
288 | self.rc.set(rc) |
289 | } |
290 | |
291 | #[inline ] |
292 | fn dec_rc(&self) -> bool { |
293 | let rc = self.rc.get() - 1; |
294 | self.rc.set(rc); |
295 | rc == 0 |
296 | } |
297 | |
298 | #[inline ] |
299 | fn key(&self) -> (ptr::NonNull<()>, TextSize) { |
300 | let ptr = match &self.green { |
301 | Green::Node { ptr } => ptr.get().cast(), |
302 | Green::Token { ptr } => ptr.cast(), |
303 | }; |
304 | (ptr, self.offset()) |
305 | } |
306 | |
307 | #[inline ] |
308 | fn parent_node(&self) -> Option<SyntaxNode> { |
309 | let parent = self.parent()?; |
310 | debug_assert!(matches!(parent.green, Green::Node { .. })); |
311 | parent.inc_rc(); |
312 | Some(SyntaxNode { ptr: ptr::NonNull::from(parent) }) |
313 | } |
314 | |
315 | #[inline ] |
316 | fn parent(&self) -> Option<&NodeData> { |
317 | self.parent.get().map(|it| unsafe { &*it.as_ptr() }) |
318 | } |
319 | |
320 | #[inline ] |
321 | fn green(&self) -> GreenElementRef<'_> { |
322 | match &self.green { |
323 | Green::Node { ptr } => GreenElementRef::Node(unsafe { &*ptr.get().as_ptr() }), |
324 | Green::Token { ptr } => GreenElementRef::Token(unsafe { &*ptr.as_ref() }), |
325 | } |
326 | } |
327 | #[inline ] |
328 | fn green_siblings(&self) -> slice::Iter<GreenChild> { |
329 | match &self.parent().map(|it| &it.green) { |
330 | Some(Green::Node { ptr }) => unsafe { &*ptr.get().as_ptr() }.children().raw, |
331 | Some(Green::Token { .. }) => { |
332 | debug_assert!(false); |
333 | [].iter() |
334 | } |
335 | None => [].iter(), |
336 | } |
337 | } |
338 | #[inline ] |
339 | fn index(&self) -> u32 { |
340 | self.index.get() |
341 | } |
342 | |
343 | #[inline ] |
344 | fn offset(&self) -> TextSize { |
345 | if self.mutable { |
346 | self.offset_mut() |
347 | } else { |
348 | self.offset |
349 | } |
350 | } |
351 | |
352 | #[cold ] |
353 | fn offset_mut(&self) -> TextSize { |
354 | let mut res = TextSize::from(0); |
355 | |
356 | let mut node = self; |
357 | while let Some(parent) = node.parent() { |
358 | let green = parent.green().into_node().unwrap(); |
359 | res += green.children().raw.nth(node.index() as usize).unwrap().rel_offset(); |
360 | node = parent; |
361 | } |
362 | |
363 | res |
364 | } |
365 | |
366 | #[inline ] |
367 | fn text_range(&self) -> TextRange { |
368 | let offset = self.offset(); |
369 | let len = self.green().text_len(); |
370 | TextRange::at(offset, len) |
371 | } |
372 | |
373 | #[inline ] |
374 | fn kind(&self) -> SyntaxKind { |
375 | self.green().kind() |
376 | } |
377 | |
378 | fn next_sibling(&self) -> Option<SyntaxNode> { |
379 | let siblings = self.green_siblings().enumerate(); |
380 | let index = self.index() as usize; |
381 | |
382 | siblings.skip(index + 1).find_map(|(index, child)| { |
383 | child.as_ref().into_node().and_then(|green| { |
384 | let parent = self.parent_node()?; |
385 | let offset = parent.offset() + child.rel_offset(); |
386 | Some(SyntaxNode::new_child(green, parent, index as u32, offset)) |
387 | }) |
388 | }) |
389 | } |
390 | |
391 | fn next_sibling_by_kind(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option<SyntaxNode> { |
392 | let siblings = self.green_siblings().enumerate(); |
393 | let index = self.index() as usize; |
394 | |
395 | siblings.skip(index + 1).find_map(|(index, child)| { |
396 | if !matcher(child.as_ref().kind()) { |
397 | return None; |
398 | } |
399 | child.as_ref().into_node().and_then(|green| { |
400 | let parent = self.parent_node()?; |
401 | let offset = parent.offset() + child.rel_offset(); |
402 | Some(SyntaxNode::new_child(green, parent, index as u32, offset)) |
403 | }) |
404 | }) |
405 | } |
406 | |
407 | fn prev_sibling(&self) -> Option<SyntaxNode> { |
408 | let rev_siblings = self.green_siblings().enumerate().rev(); |
409 | let index = rev_siblings.len().checked_sub(self.index() as usize)?; |
410 | |
411 | rev_siblings.skip(index).find_map(|(index, child)| { |
412 | child.as_ref().into_node().and_then(|green| { |
413 | let parent = self.parent_node()?; |
414 | let offset = parent.offset() + child.rel_offset(); |
415 | Some(SyntaxNode::new_child(green, parent, index as u32, offset)) |
416 | }) |
417 | }) |
418 | } |
419 | |
420 | fn next_sibling_or_token(&self) -> Option<SyntaxElement> { |
421 | let mut siblings = self.green_siblings().enumerate(); |
422 | let index = self.index() as usize + 1; |
423 | |
424 | siblings.nth(index).and_then(|(index, child)| { |
425 | let parent = self.parent_node()?; |
426 | let offset = parent.offset() + child.rel_offset(); |
427 | Some(SyntaxElement::new(child.as_ref(), parent, index as u32, offset)) |
428 | }) |
429 | } |
430 | |
431 | fn next_sibling_or_token_by_kind( |
432 | &self, |
433 | matcher: &impl Fn(SyntaxKind) -> bool, |
434 | ) -> Option<SyntaxElement> { |
435 | let siblings = self.green_siblings().enumerate(); |
436 | let index = self.index() as usize; |
437 | |
438 | siblings.skip(index + 1).find_map(|(index, child)| { |
439 | if !matcher(child.as_ref().kind()) { |
440 | return None; |
441 | } |
442 | let parent = self.parent_node()?; |
443 | let offset = parent.offset() + child.rel_offset(); |
444 | Some(SyntaxElement::new(child.as_ref(), parent, index as u32, offset)) |
445 | }) |
446 | } |
447 | |
448 | fn prev_sibling_or_token(&self) -> Option<SyntaxElement> { |
449 | let mut siblings = self.green_siblings().enumerate(); |
450 | let index = self.index().checked_sub(1)? as usize; |
451 | |
452 | siblings.nth(index).and_then(|(index, child)| { |
453 | let parent = self.parent_node()?; |
454 | let offset = parent.offset() + child.rel_offset(); |
455 | Some(SyntaxElement::new(child.as_ref(), parent, index as u32, offset)) |
456 | }) |
457 | } |
458 | |
459 | fn detach(&self) { |
460 | assert!(self.mutable); |
461 | assert!(self.rc.get() > 0); |
462 | let parent_ptr = match self.parent.take() { |
463 | Some(parent) => parent, |
464 | None => return, |
465 | }; |
466 | |
467 | sll::adjust(self, self.index() + 1, Delta::Sub(1)); |
468 | let parent = unsafe { parent_ptr.as_ref() }; |
469 | sll::unlink(&parent.first, self); |
470 | |
471 | // Add strong ref to green |
472 | match self.green().to_owned() { |
473 | NodeOrToken::Node(it) => { |
474 | GreenNode::into_raw(it); |
475 | } |
476 | NodeOrToken::Token(it) => { |
477 | GreenToken::into_raw(it); |
478 | } |
479 | } |
480 | |
481 | match parent.green() { |
482 | NodeOrToken::Node(green) => { |
483 | let green = green.remove_child(self.index() as usize); |
484 | unsafe { parent.respine(green) } |
485 | } |
486 | NodeOrToken::Token(_) => unreachable!(), |
487 | } |
488 | |
489 | if parent.dec_rc() { |
490 | unsafe { free(parent_ptr) } |
491 | } |
492 | } |
493 | fn attach_child(&self, index: usize, child: &NodeData) { |
494 | assert!(self.mutable && child.mutable && child.parent().is_none()); |
495 | assert!(self.rc.get() > 0 && child.rc.get() > 0); |
496 | |
497 | child.index.set(index as u32); |
498 | child.parent.set(Some(self.into())); |
499 | self.inc_rc(); |
500 | |
501 | if !self.first.get().is_null() { |
502 | sll::adjust(unsafe { &*self.first.get() }, index as u32, Delta::Add(1)); |
503 | } |
504 | |
505 | match sll::link(&self.first, child) { |
506 | sll::AddToSllResult::AlreadyInSll(_) => { |
507 | panic!("Child already in sorted linked list" ) |
508 | } |
509 | it => it.add_to_sll(child), |
510 | } |
511 | |
512 | match self.green() { |
513 | NodeOrToken::Node(green) => { |
514 | // Child is root, so it owns the green node. Steal it! |
515 | let child_green = match &child.green { |
516 | Green::Node { ptr } => unsafe { GreenNode::from_raw(ptr.get()).into() }, |
517 | Green::Token { ptr } => unsafe { GreenToken::from_raw(*ptr).into() }, |
518 | }; |
519 | |
520 | let green = green.insert_child(index, child_green); |
521 | unsafe { self.respine(green) }; |
522 | } |
523 | NodeOrToken::Token(_) => unreachable!(), |
524 | } |
525 | } |
526 | unsafe fn respine(&self, mut new_green: GreenNode) { |
527 | let mut node = self; |
528 | loop { |
529 | let old_green = match &node.green { |
530 | Green::Node { ptr } => ptr.replace(ptr::NonNull::from(&*new_green)), |
531 | Green::Token { .. } => unreachable!(), |
532 | }; |
533 | match node.parent() { |
534 | Some(parent) => match parent.green() { |
535 | NodeOrToken::Node(parent_green) => { |
536 | new_green = |
537 | parent_green.replace_child(node.index() as usize, new_green.into()); |
538 | node = parent; |
539 | } |
540 | _ => unreachable!(), |
541 | }, |
542 | None => { |
543 | mem::forget(new_green); |
544 | let _ = GreenNode::from_raw(old_green); |
545 | break; |
546 | } |
547 | } |
548 | } |
549 | } |
550 | } |
551 | |
552 | impl SyntaxNode { |
553 | pub fn new_root(green: GreenNode) -> SyntaxNode { |
554 | let green = GreenNode::into_raw(green); |
555 | let green = Green::Node { ptr: Cell::new(green) }; |
556 | SyntaxNode { ptr: NodeData::new(None, 0, 0.into(), green, false) } |
557 | } |
558 | |
559 | pub fn new_root_mut(green: GreenNode) -> SyntaxNode { |
560 | let green = GreenNode::into_raw(green); |
561 | let green = Green::Node { ptr: Cell::new(green) }; |
562 | SyntaxNode { ptr: NodeData::new(None, 0, 0.into(), green, true) } |
563 | } |
564 | |
565 | fn new_child( |
566 | green: &GreenNodeData, |
567 | parent: SyntaxNode, |
568 | index: u32, |
569 | offset: TextSize, |
570 | ) -> SyntaxNode { |
571 | let mutable = parent.data().mutable; |
572 | let green = Green::Node { ptr: Cell::new(green.into()) }; |
573 | SyntaxNode { ptr: NodeData::new(Some(parent), index, offset, green, mutable) } |
574 | } |
575 | |
576 | pub fn is_mutable(&self) -> bool { |
577 | self.data().mutable |
578 | } |
579 | |
580 | pub fn clone_for_update(&self) -> SyntaxNode { |
581 | assert!(!self.data().mutable); |
582 | match self.parent() { |
583 | Some(parent) => { |
584 | let parent = parent.clone_for_update(); |
585 | SyntaxNode::new_child(self.green_ref(), parent, self.data().index(), self.offset()) |
586 | } |
587 | None => SyntaxNode::new_root_mut(self.green_ref().to_owned()), |
588 | } |
589 | } |
590 | |
591 | pub fn clone_subtree(&self) -> SyntaxNode { |
592 | SyntaxNode::new_root(self.green().into()) |
593 | } |
594 | |
595 | #[inline ] |
596 | fn data(&self) -> &NodeData { |
597 | unsafe { self.ptr.as_ref() } |
598 | } |
599 | |
600 | #[inline ] |
601 | fn can_take_ptr(&self) -> bool { |
602 | self.data().rc.get() == 1 && !self.data().mutable |
603 | } |
604 | |
605 | #[inline ] |
606 | fn take_ptr(self) -> ptr::NonNull<NodeData> { |
607 | assert!(self.can_take_ptr()); |
608 | let ret = self.ptr; |
609 | // don't change the refcount when self gets dropped |
610 | std::mem::forget(self); |
611 | ret |
612 | } |
613 | |
614 | pub fn replace_with(&self, replacement: GreenNode) -> GreenNode { |
615 | assert_eq!(self.kind(), replacement.kind()); |
616 | match &self.parent() { |
617 | None => replacement, |
618 | Some(parent) => { |
619 | let new_parent = parent |
620 | .green_ref() |
621 | .replace_child(self.data().index() as usize, replacement.into()); |
622 | parent.replace_with(new_parent) |
623 | } |
624 | } |
625 | } |
626 | |
627 | #[inline ] |
628 | pub fn kind(&self) -> SyntaxKind { |
629 | self.data().kind() |
630 | } |
631 | |
632 | #[inline ] |
633 | fn offset(&self) -> TextSize { |
634 | self.data().offset() |
635 | } |
636 | |
637 | #[inline ] |
638 | pub fn text_range(&self) -> TextRange { |
639 | self.data().text_range() |
640 | } |
641 | |
642 | #[inline ] |
643 | pub fn index(&self) -> usize { |
644 | self.data().index() as usize |
645 | } |
646 | |
647 | #[inline ] |
648 | pub fn text(&self) -> SyntaxText { |
649 | SyntaxText::new(self.clone()) |
650 | } |
651 | |
652 | #[inline ] |
653 | pub fn green(&self) -> Cow<'_, GreenNodeData> { |
654 | let green_ref = self.green_ref(); |
655 | match self.data().mutable { |
656 | false => Cow::Borrowed(green_ref), |
657 | true => Cow::Owned(green_ref.to_owned()), |
658 | } |
659 | } |
660 | #[inline ] |
661 | fn green_ref(&self) -> &GreenNodeData { |
662 | self.data().green().into_node().unwrap() |
663 | } |
664 | |
665 | #[inline ] |
666 | pub fn parent(&self) -> Option<SyntaxNode> { |
667 | self.data().parent_node() |
668 | } |
669 | |
670 | #[inline ] |
671 | pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> { |
672 | iter::successors(Some(self.clone()), SyntaxNode::parent) |
673 | } |
674 | |
675 | #[inline ] |
676 | pub fn children(&self) -> SyntaxNodeChildren { |
677 | SyntaxNodeChildren::new(self.clone()) |
678 | } |
679 | |
680 | #[inline ] |
681 | pub fn children_with_tokens(&self) -> SyntaxElementChildren { |
682 | SyntaxElementChildren::new(self.clone()) |
683 | } |
684 | |
685 | pub fn first_child(&self) -> Option<SyntaxNode> { |
686 | self.green_ref().children().raw.enumerate().find_map(|(index, child)| { |
687 | child.as_ref().into_node().map(|green| { |
688 | SyntaxNode::new_child( |
689 | green, |
690 | self.clone(), |
691 | index as u32, |
692 | self.offset() + child.rel_offset(), |
693 | ) |
694 | }) |
695 | }) |
696 | } |
697 | |
698 | pub fn first_child_by_kind(&self, matcher: &impl Fn(SyntaxKind) -> bool) -> Option<SyntaxNode> { |
699 | self.green_ref().children().raw.enumerate().find_map(|(index, child)| { |
700 | if !matcher(child.as_ref().kind()) { |
701 | return None; |
702 | } |
703 | child.as_ref().into_node().map(|green| { |
704 | SyntaxNode::new_child( |
705 | green, |
706 | self.clone(), |
707 | index as u32, |
708 | self.offset() + child.rel_offset(), |
709 | ) |
710 | }) |
711 | }) |
712 | } |
713 | |
714 | pub fn last_child(&self) -> Option<SyntaxNode> { |
715 | self.green_ref().children().raw.enumerate().rev().find_map(|(index, child)| { |
716 | child.as_ref().into_node().map(|green| { |
717 | SyntaxNode::new_child( |
718 | green, |
719 | self.clone(), |
720 | index as u32, |
721 | self.offset() + child.rel_offset(), |
722 | ) |
723 | }) |
724 | }) |
725 | } |
726 | |
727 | pub fn first_child_or_token(&self) -> Option<SyntaxElement> { |
728 | self.green_ref().children().raw.next().map(|child| { |
729 | SyntaxElement::new(child.as_ref(), self.clone(), 0, self.offset() + child.rel_offset()) |
730 | }) |
731 | } |
732 | |
733 | pub fn first_child_or_token_by_kind( |
734 | &self, |
735 | matcher: &impl Fn(SyntaxKind) -> bool, |
736 | ) -> Option<SyntaxElement> { |
737 | self.green_ref().children().raw.enumerate().find_map(|(index, child)| { |
738 | if !matcher(child.as_ref().kind()) { |
739 | return None; |
740 | } |
741 | Some(SyntaxElement::new( |
742 | child.as_ref(), |
743 | self.clone(), |
744 | index as u32, |
745 | self.offset() + child.rel_offset(), |
746 | )) |
747 | }) |
748 | } |
749 | |
750 | pub fn last_child_or_token(&self) -> Option<SyntaxElement> { |
751 | self.green_ref().children().raw.enumerate().next_back().map(|(index, child)| { |
752 | SyntaxElement::new( |
753 | child.as_ref(), |
754 | self.clone(), |
755 | index as u32, |
756 | self.offset() + child.rel_offset(), |
757 | ) |
758 | }) |
759 | } |
760 | |
761 | // if possible (i.e. unshared), consume self and advance it to point to the next sibling |
762 | // this way, we can reuse the previously allocated buffer |
763 | pub fn to_next_sibling(self) -> Option<SyntaxNode> { |
764 | if !self.can_take_ptr() { |
765 | // cannot mutate in-place |
766 | return self.next_sibling(); |
767 | } |
768 | |
769 | let mut ptr = self.take_ptr(); |
770 | let data = unsafe { ptr.as_mut() }; |
771 | assert!(data.rc.get() == 1); |
772 | |
773 | let parent = data.parent_node()?; |
774 | let parent_offset = parent.offset(); |
775 | let siblings = parent.green_ref().children().raw.enumerate(); |
776 | let index = data.index() as usize; |
777 | |
778 | siblings |
779 | .skip(index + 1) |
780 | .find_map(|(index, child)| { |
781 | child |
782 | .as_ref() |
783 | .into_node() |
784 | .and_then(|green| Some((green, index as u32, child.rel_offset()))) |
785 | }) |
786 | .and_then(|(green, index, rel_offset)| { |
787 | data.index.set(index); |
788 | data.offset = parent_offset + rel_offset; |
789 | data.green = Green::Node { ptr: Cell::new(green.into()) }; |
790 | Some(SyntaxNode { ptr }) |
791 | }) |
792 | .or_else(|| { |
793 | data.dec_rc(); |
794 | unsafe { free(ptr) }; |
795 | None |
796 | }) |
797 | } |
798 | |
799 | pub fn next_sibling(&self) -> Option<SyntaxNode> { |
800 | self.data().next_sibling() |
801 | } |
802 | |
803 | pub fn next_sibling_by_kind( |
804 | &self, |
805 | matcher: &impl Fn(SyntaxKind) -> bool, |
806 | ) -> Option<SyntaxNode> { |
807 | self.data().next_sibling_by_kind(matcher) |
808 | } |
809 | |
810 | pub fn prev_sibling(&self) -> Option<SyntaxNode> { |
811 | self.data().prev_sibling() |
812 | } |
813 | |
814 | pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> { |
815 | self.data().next_sibling_or_token() |
816 | } |
817 | |
818 | pub fn next_sibling_or_token_by_kind( |
819 | &self, |
820 | matcher: &impl Fn(SyntaxKind) -> bool, |
821 | ) -> Option<SyntaxElement> { |
822 | self.data().next_sibling_or_token_by_kind(matcher) |
823 | } |
824 | |
825 | pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> { |
826 | self.data().prev_sibling_or_token() |
827 | } |
828 | |
829 | pub fn first_token(&self) -> Option<SyntaxToken> { |
830 | self.first_child_or_token()?.first_token() |
831 | } |
832 | pub fn last_token(&self) -> Option<SyntaxToken> { |
833 | self.last_child_or_token()?.last_token() |
834 | } |
835 | |
836 | #[inline ] |
837 | pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = SyntaxNode> { |
838 | iter::successors(Some(self.clone()), move |node| match direction { |
839 | Direction::Next => node.next_sibling(), |
840 | Direction::Prev => node.prev_sibling(), |
841 | }) |
842 | } |
843 | |
844 | #[inline ] |
845 | pub fn siblings_with_tokens( |
846 | &self, |
847 | direction: Direction, |
848 | ) -> impl Iterator<Item = SyntaxElement> { |
849 | let me: SyntaxElement = self.clone().into(); |
850 | iter::successors(Some(me), move |el| match direction { |
851 | Direction::Next => el.next_sibling_or_token(), |
852 | Direction::Prev => el.prev_sibling_or_token(), |
853 | }) |
854 | } |
855 | |
856 | #[inline ] |
857 | pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode> { |
858 | self.preorder().filter_map(|event| match event { |
859 | WalkEvent::Enter(node) => Some(node), |
860 | WalkEvent::Leave(_) => None, |
861 | }) |
862 | } |
863 | |
864 | #[inline ] |
865 | pub fn descendants_with_tokens(&self) -> impl Iterator<Item = SyntaxElement> { |
866 | self.preorder_with_tokens().filter_map(|event| match event { |
867 | WalkEvent::Enter(it) => Some(it), |
868 | WalkEvent::Leave(_) => None, |
869 | }) |
870 | } |
871 | |
872 | #[inline ] |
873 | pub fn preorder(&self) -> Preorder { |
874 | Preorder::new(self.clone()) |
875 | } |
876 | |
877 | #[inline ] |
878 | pub fn preorder_with_tokens(&self) -> PreorderWithTokens { |
879 | PreorderWithTokens::new(self.clone()) |
880 | } |
881 | |
882 | pub fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> { |
883 | // TODO: this could be faster if we first drill-down to node, and only |
884 | // then switch to token search. We should also replace explicit |
885 | // recursion with a loop. |
886 | let range = self.text_range(); |
887 | assert!( |
888 | range.start() <= offset && offset <= range.end(), |
889 | "Bad offset: range {:?} offset {:?}" , |
890 | range, |
891 | offset |
892 | ); |
893 | if range.is_empty() { |
894 | return TokenAtOffset::None; |
895 | } |
896 | |
897 | let mut children = self.children_with_tokens().filter(|child| { |
898 | let child_range = child.text_range(); |
899 | !child_range.is_empty() |
900 | && (child_range.start() <= offset && offset <= child_range.end()) |
901 | }); |
902 | |
903 | let left = children.next().unwrap(); |
904 | let right = children.next(); |
905 | assert!(children.next().is_none()); |
906 | |
907 | if let Some(right) = right { |
908 | match (left.token_at_offset(offset), right.token_at_offset(offset)) { |
909 | (TokenAtOffset::Single(left), TokenAtOffset::Single(right)) => { |
910 | TokenAtOffset::Between(left, right) |
911 | } |
912 | _ => unreachable!(), |
913 | } |
914 | } else { |
915 | left.token_at_offset(offset) |
916 | } |
917 | } |
918 | |
919 | pub fn covering_element(&self, range: TextRange) -> SyntaxElement { |
920 | let mut res: SyntaxElement = self.clone().into(); |
921 | loop { |
922 | assert!( |
923 | res.text_range().contains_range(range), |
924 | "Bad range: node range {:?}, range {:?}" , |
925 | res.text_range(), |
926 | range, |
927 | ); |
928 | res = match &res { |
929 | NodeOrToken::Token(_) => return res, |
930 | NodeOrToken::Node(node) => match node.child_or_token_at_range(range) { |
931 | Some(it) => it, |
932 | None => return res, |
933 | }, |
934 | }; |
935 | } |
936 | } |
937 | |
938 | pub fn child_or_token_at_range(&self, range: TextRange) -> Option<SyntaxElement> { |
939 | let rel_range = range - self.offset(); |
940 | self.green_ref().child_at_range(rel_range).map(|(index, rel_offset, green)| { |
941 | SyntaxElement::new(green, self.clone(), index as u32, self.offset() + rel_offset) |
942 | }) |
943 | } |
944 | |
945 | pub fn splice_children<I: IntoIterator<Item = SyntaxElement>>( |
946 | &self, |
947 | to_delete: Range<usize>, |
948 | to_insert: I, |
949 | ) { |
950 | assert!(self.data().mutable, "immutable tree: {}" , self); |
951 | for (i, child) in self.children_with_tokens().enumerate() { |
952 | if to_delete.contains(&i) { |
953 | child.detach(); |
954 | } |
955 | } |
956 | let mut index = to_delete.start; |
957 | for child in to_insert { |
958 | self.attach_child(index, child); |
959 | index += 1; |
960 | } |
961 | } |
962 | |
963 | pub fn detach(&self) { |
964 | assert!(self.data().mutable, "immutable tree: {}" , self); |
965 | self.data().detach() |
966 | } |
967 | |
968 | fn attach_child(&self, index: usize, child: SyntaxElement) { |
969 | assert!(self.data().mutable, "immutable tree: {}" , self); |
970 | child.detach(); |
971 | let data = match &child { |
972 | NodeOrToken::Node(it) => it.data(), |
973 | NodeOrToken::Token(it) => it.data(), |
974 | }; |
975 | self.data().attach_child(index, data) |
976 | } |
977 | } |
978 | |
979 | impl SyntaxToken { |
980 | fn new( |
981 | green: &GreenTokenData, |
982 | parent: SyntaxNode, |
983 | index: u32, |
984 | offset: TextSize, |
985 | ) -> SyntaxToken { |
986 | let mutable = parent.data().mutable; |
987 | let green = Green::Token { ptr: green.into() }; |
988 | SyntaxToken { ptr: NodeData::new(Some(parent), index, offset, green, mutable) } |
989 | } |
990 | |
991 | #[inline ] |
992 | fn data(&self) -> &NodeData { |
993 | unsafe { self.ptr.as_ref() } |
994 | } |
995 | |
996 | #[inline ] |
997 | fn can_take_ptr(&self) -> bool { |
998 | self.data().rc.get() == 1 && !self.data().mutable |
999 | } |
1000 | |
1001 | #[inline ] |
1002 | fn take_ptr(self) -> ptr::NonNull<NodeData> { |
1003 | assert!(self.can_take_ptr()); |
1004 | let ret = self.ptr; |
1005 | // don't change the refcount when self gets dropped |
1006 | std::mem::forget(self); |
1007 | ret |
1008 | } |
1009 | |
1010 | pub fn replace_with(&self, replacement: GreenToken) -> GreenNode { |
1011 | assert_eq!(self.kind(), replacement.kind()); |
1012 | let parent = self.parent().unwrap(); |
1013 | let me: u32 = self.data().index(); |
1014 | |
1015 | let new_parent = parent.green_ref().replace_child(me as usize, replacement.into()); |
1016 | parent.replace_with(new_parent) |
1017 | } |
1018 | |
1019 | #[inline ] |
1020 | pub fn kind(&self) -> SyntaxKind { |
1021 | self.data().kind() |
1022 | } |
1023 | |
1024 | #[inline ] |
1025 | pub fn text_range(&self) -> TextRange { |
1026 | self.data().text_range() |
1027 | } |
1028 | |
1029 | #[inline ] |
1030 | pub fn index(&self) -> usize { |
1031 | self.data().index() as usize |
1032 | } |
1033 | |
1034 | #[inline ] |
1035 | pub fn text(&self) -> &str { |
1036 | match self.data().green().as_token() { |
1037 | Some(it) => it.text(), |
1038 | None => { |
1039 | debug_assert!( |
1040 | false, |
1041 | "corrupted tree: a node thinks it is a token: {:?}" , |
1042 | self.data().green().as_node().unwrap().to_string() |
1043 | ); |
1044 | "" |
1045 | } |
1046 | } |
1047 | } |
1048 | |
1049 | #[inline ] |
1050 | pub fn green(&self) -> &GreenTokenData { |
1051 | self.data().green().into_token().unwrap() |
1052 | } |
1053 | |
1054 | #[inline ] |
1055 | pub fn parent(&self) -> Option<SyntaxNode> { |
1056 | self.data().parent_node() |
1057 | } |
1058 | |
1059 | #[inline ] |
1060 | pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> { |
1061 | std::iter::successors(self.parent(), SyntaxNode::parent) |
1062 | } |
1063 | |
1064 | pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> { |
1065 | self.data().next_sibling_or_token() |
1066 | } |
1067 | |
1068 | pub fn next_sibling_or_token_by_kind( |
1069 | &self, |
1070 | matcher: &impl Fn(SyntaxKind) -> bool, |
1071 | ) -> Option<SyntaxElement> { |
1072 | self.data().next_sibling_or_token_by_kind(matcher) |
1073 | } |
1074 | |
1075 | pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> { |
1076 | self.data().prev_sibling_or_token() |
1077 | } |
1078 | |
1079 | #[inline ] |
1080 | pub fn siblings_with_tokens( |
1081 | &self, |
1082 | direction: Direction, |
1083 | ) -> impl Iterator<Item = SyntaxElement> { |
1084 | let me: SyntaxElement = self.clone().into(); |
1085 | iter::successors(Some(me), move |el| match direction { |
1086 | Direction::Next => el.next_sibling_or_token(), |
1087 | Direction::Prev => el.prev_sibling_or_token(), |
1088 | }) |
1089 | } |
1090 | |
1091 | pub fn next_token(&self) -> Option<SyntaxToken> { |
1092 | match self.next_sibling_or_token() { |
1093 | Some(element) => element.first_token(), |
1094 | None => self |
1095 | .ancestors() |
1096 | .find_map(|it| it.next_sibling_or_token()) |
1097 | .and_then(|element| element.first_token()), |
1098 | } |
1099 | } |
1100 | pub fn prev_token(&self) -> Option<SyntaxToken> { |
1101 | match self.prev_sibling_or_token() { |
1102 | Some(element) => element.last_token(), |
1103 | None => self |
1104 | .ancestors() |
1105 | .find_map(|it| it.prev_sibling_or_token()) |
1106 | .and_then(|element| element.last_token()), |
1107 | } |
1108 | } |
1109 | |
1110 | pub fn detach(&self) { |
1111 | assert!(self.data().mutable, "immutable tree: {}" , self); |
1112 | self.data().detach() |
1113 | } |
1114 | } |
1115 | |
1116 | impl SyntaxElement { |
1117 | fn new( |
1118 | element: GreenElementRef<'_>, |
1119 | parent: SyntaxNode, |
1120 | index: u32, |
1121 | offset: TextSize, |
1122 | ) -> SyntaxElement { |
1123 | match element { |
1124 | NodeOrToken::Node(node) => { |
1125 | SyntaxNode::new_child(node, parent, index as u32, offset).into() |
1126 | } |
1127 | NodeOrToken::Token(token) => { |
1128 | SyntaxToken::new(token, parent, index as u32, offset).into() |
1129 | } |
1130 | } |
1131 | } |
1132 | |
1133 | #[inline ] |
1134 | pub fn text_range(&self) -> TextRange { |
1135 | match self { |
1136 | NodeOrToken::Node(it) => it.text_range(), |
1137 | NodeOrToken::Token(it) => it.text_range(), |
1138 | } |
1139 | } |
1140 | |
1141 | #[inline ] |
1142 | pub fn index(&self) -> usize { |
1143 | match self { |
1144 | NodeOrToken::Node(it) => it.index(), |
1145 | NodeOrToken::Token(it) => it.index(), |
1146 | } |
1147 | } |
1148 | |
1149 | #[inline ] |
1150 | pub fn kind(&self) -> SyntaxKind { |
1151 | match self { |
1152 | NodeOrToken::Node(it) => it.kind(), |
1153 | NodeOrToken::Token(it) => it.kind(), |
1154 | } |
1155 | } |
1156 | |
1157 | #[inline ] |
1158 | pub fn parent(&self) -> Option<SyntaxNode> { |
1159 | match self { |
1160 | NodeOrToken::Node(it) => it.parent(), |
1161 | NodeOrToken::Token(it) => it.parent(), |
1162 | } |
1163 | } |
1164 | |
1165 | #[inline ] |
1166 | pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> { |
1167 | let first = match self { |
1168 | NodeOrToken::Node(it) => Some(it.clone()), |
1169 | NodeOrToken::Token(it) => it.parent(), |
1170 | }; |
1171 | iter::successors(first, SyntaxNode::parent) |
1172 | } |
1173 | |
1174 | pub fn first_token(&self) -> Option<SyntaxToken> { |
1175 | match self { |
1176 | NodeOrToken::Node(it) => it.first_token(), |
1177 | NodeOrToken::Token(it) => Some(it.clone()), |
1178 | } |
1179 | } |
1180 | pub fn last_token(&self) -> Option<SyntaxToken> { |
1181 | match self { |
1182 | NodeOrToken::Node(it) => it.last_token(), |
1183 | NodeOrToken::Token(it) => Some(it.clone()), |
1184 | } |
1185 | } |
1186 | |
1187 | pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> { |
1188 | match self { |
1189 | NodeOrToken::Node(it) => it.next_sibling_or_token(), |
1190 | NodeOrToken::Token(it) => it.next_sibling_or_token(), |
1191 | } |
1192 | } |
1193 | |
1194 | fn can_take_ptr(&self) -> bool { |
1195 | match self { |
1196 | NodeOrToken::Node(it) => it.can_take_ptr(), |
1197 | NodeOrToken::Token(it) => it.can_take_ptr(), |
1198 | } |
1199 | } |
1200 | |
1201 | fn take_ptr(self) -> ptr::NonNull<NodeData> { |
1202 | match self { |
1203 | NodeOrToken::Node(it) => it.take_ptr(), |
1204 | NodeOrToken::Token(it) => it.take_ptr(), |
1205 | } |
1206 | } |
1207 | |
1208 | // if possible (i.e. unshared), consume self and advance it to point to the next sibling |
1209 | // this way, we can reuse the previously allocated buffer |
1210 | pub fn to_next_sibling_or_token(self) -> Option<SyntaxElement> { |
1211 | if !self.can_take_ptr() { |
1212 | // cannot mutate in-place |
1213 | return self.next_sibling_or_token(); |
1214 | } |
1215 | |
1216 | let mut ptr = self.take_ptr(); |
1217 | let data = unsafe { ptr.as_mut() }; |
1218 | |
1219 | let parent = data.parent_node()?; |
1220 | let parent_offset = parent.offset(); |
1221 | let siblings = parent.green_ref().children().raw.enumerate(); |
1222 | let index = data.index() as usize; |
1223 | |
1224 | siblings |
1225 | .skip(index + 1) |
1226 | .find_map(|(index, green)| { |
1227 | data.index.set(index as u32); |
1228 | data.offset = parent_offset + green.rel_offset(); |
1229 | |
1230 | match green.as_ref() { |
1231 | NodeOrToken::Node(node) => { |
1232 | data.green = Green::Node { ptr: Cell::new(node.into()) }; |
1233 | Some(SyntaxElement::Node(SyntaxNode { ptr })) |
1234 | } |
1235 | NodeOrToken::Token(token) => { |
1236 | data.green = Green::Token { ptr: token.into() }; |
1237 | Some(SyntaxElement::Token(SyntaxToken { ptr })) |
1238 | } |
1239 | } |
1240 | }) |
1241 | .or_else(|| { |
1242 | data.dec_rc(); |
1243 | unsafe { free(ptr) }; |
1244 | None |
1245 | }) |
1246 | } |
1247 | |
1248 | pub fn next_sibling_or_token_by_kind( |
1249 | &self, |
1250 | matcher: &impl Fn(SyntaxKind) -> bool, |
1251 | ) -> Option<SyntaxElement> { |
1252 | match self { |
1253 | NodeOrToken::Node(it) => it.next_sibling_or_token_by_kind(matcher), |
1254 | NodeOrToken::Token(it) => it.next_sibling_or_token_by_kind(matcher), |
1255 | } |
1256 | } |
1257 | |
1258 | pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> { |
1259 | match self { |
1260 | NodeOrToken::Node(it) => it.prev_sibling_or_token(), |
1261 | NodeOrToken::Token(it) => it.prev_sibling_or_token(), |
1262 | } |
1263 | } |
1264 | |
1265 | fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> { |
1266 | assert!(self.text_range().start() <= offset && offset <= self.text_range().end()); |
1267 | match self { |
1268 | NodeOrToken::Token(token) => TokenAtOffset::Single(token.clone()), |
1269 | NodeOrToken::Node(node) => node.token_at_offset(offset), |
1270 | } |
1271 | } |
1272 | |
1273 | pub fn detach(&self) { |
1274 | match self { |
1275 | NodeOrToken::Node(it) => it.detach(), |
1276 | NodeOrToken::Token(it) => it.detach(), |
1277 | } |
1278 | } |
1279 | } |
1280 | |
1281 | // region: impls |
1282 | |
1283 | // Identity semantics for hash & eq |
1284 | impl PartialEq for SyntaxNode { |
1285 | #[inline ] |
1286 | fn eq(&self, other: &SyntaxNode) -> bool { |
1287 | self.data().key() == other.data().key() |
1288 | } |
1289 | } |
1290 | |
1291 | impl Eq for SyntaxNode {} |
1292 | |
1293 | impl Hash for SyntaxNode { |
1294 | #[inline ] |
1295 | fn hash<H: Hasher>(&self, state: &mut H) { |
1296 | self.data().key().hash(state); |
1297 | } |
1298 | } |
1299 | |
1300 | impl fmt::Debug for SyntaxNode { |
1301 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1302 | f&mut DebugStruct<'_, '_>.debug_struct("SyntaxNode" ) |
1303 | .field("kind" , &self.kind()) |
1304 | .field(name:"text_range" , &self.text_range()) |
1305 | .finish() |
1306 | } |
1307 | } |
1308 | |
1309 | impl fmt::Display for SyntaxNode { |
1310 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1311 | self.preorder_with_tokens() |
1312 | .filter_map(|event: WalkEvent>| match event { |
1313 | WalkEvent::Enter(NodeOrToken::Token(token: SyntaxToken)) => Some(token), |
1314 | _ => None, |
1315 | }) |
1316 | .try_for_each(|it: SyntaxToken| fmt::Display::fmt(&it, f)) |
1317 | } |
1318 | } |
1319 | |
1320 | // Identity semantics for hash & eq |
1321 | impl PartialEq for SyntaxToken { |
1322 | #[inline ] |
1323 | fn eq(&self, other: &SyntaxToken) -> bool { |
1324 | self.data().key() == other.data().key() |
1325 | } |
1326 | } |
1327 | |
1328 | impl Eq for SyntaxToken {} |
1329 | |
1330 | impl Hash for SyntaxToken { |
1331 | #[inline ] |
1332 | fn hash<H: Hasher>(&self, state: &mut H) { |
1333 | self.data().key().hash(state); |
1334 | } |
1335 | } |
1336 | |
1337 | impl fmt::Display for SyntaxToken { |
1338 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1339 | fmt::Display::fmt(self.text(), f) |
1340 | } |
1341 | } |
1342 | |
1343 | impl From<SyntaxNode> for SyntaxElement { |
1344 | #[inline ] |
1345 | fn from(node: SyntaxNode) -> SyntaxElement { |
1346 | NodeOrToken::Node(node) |
1347 | } |
1348 | } |
1349 | |
1350 | impl From<SyntaxToken> for SyntaxElement { |
1351 | #[inline ] |
1352 | fn from(token: SyntaxToken) -> SyntaxElement { |
1353 | NodeOrToken::Token(token) |
1354 | } |
1355 | } |
1356 | |
1357 | // endregion |
1358 | |
1359 | // region: iterators |
1360 | |
1361 | #[derive (Clone, Debug)] |
1362 | pub struct SyntaxNodeChildren { |
1363 | parent: SyntaxNode, |
1364 | next: Option<SyntaxNode>, |
1365 | next_initialized: bool, |
1366 | } |
1367 | |
1368 | impl SyntaxNodeChildren { |
1369 | fn new(parent: SyntaxNode) -> SyntaxNodeChildren { |
1370 | SyntaxNodeChildren { parent, next: None, next_initialized: false } |
1371 | } |
1372 | |
1373 | pub fn by_kind<F: Fn(SyntaxKind) -> bool>(self, matcher: F) -> SyntaxNodeChildrenByKind<F> { |
1374 | if !self.next_initialized { |
1375 | SyntaxNodeChildrenByKind { next: self.parent.first_child_by_kind(&matcher), matcher } |
1376 | } else { |
1377 | SyntaxNodeChildrenByKind { |
1378 | next: self.next.and_then(|node: SyntaxNode| { |
1379 | if matcher(node.kind()) { |
1380 | Some(node) |
1381 | } else { |
1382 | node.next_sibling_by_kind(&matcher) |
1383 | } |
1384 | }), |
1385 | matcher, |
1386 | } |
1387 | } |
1388 | } |
1389 | } |
1390 | |
1391 | impl Iterator for SyntaxNodeChildren { |
1392 | type Item = SyntaxNode; |
1393 | fn next(&mut self) -> Option<SyntaxNode> { |
1394 | if !self.next_initialized { |
1395 | self.next = self.parent.first_child(); |
1396 | self.next_initialized = true; |
1397 | } else { |
1398 | self.next = self.next.take().and_then(|next: SyntaxNode| next.to_next_sibling()); |
1399 | } |
1400 | |
1401 | self.next.clone() |
1402 | } |
1403 | } |
1404 | |
1405 | #[derive (Clone, Debug)] |
1406 | pub struct SyntaxNodeChildrenByKind<F: Fn(SyntaxKind) -> bool> { |
1407 | next: Option<SyntaxNode>, |
1408 | matcher: F, |
1409 | } |
1410 | |
1411 | impl<F: Fn(SyntaxKind) -> bool> Iterator for SyntaxNodeChildrenByKind<F> { |
1412 | type Item = SyntaxNode; |
1413 | fn next(&mut self) -> Option<SyntaxNode> { |
1414 | self.next.take().map(|next: SyntaxNode| { |
1415 | self.next = next.next_sibling_by_kind(&self.matcher); |
1416 | next |
1417 | }) |
1418 | } |
1419 | } |
1420 | |
1421 | #[derive (Clone, Debug)] |
1422 | pub struct SyntaxElementChildren { |
1423 | parent: SyntaxNode, |
1424 | next: Option<SyntaxElement>, |
1425 | next_initialized: bool, |
1426 | } |
1427 | |
1428 | impl SyntaxElementChildren { |
1429 | fn new(parent: SyntaxNode) -> SyntaxElementChildren { |
1430 | SyntaxElementChildren { parent, next: None, next_initialized: false } |
1431 | } |
1432 | |
1433 | pub fn by_kind<F: Fn(SyntaxKind) -> bool>(self, matcher: F) -> SyntaxElementChildrenByKind<F> { |
1434 | if !self.next_initialized { |
1435 | SyntaxElementChildrenByKind { |
1436 | next: self.parent.first_child_or_token_by_kind(&matcher), |
1437 | matcher, |
1438 | } |
1439 | } else { |
1440 | SyntaxElementChildrenByKind { |
1441 | next: self.next.and_then(|node| { |
1442 | if matcher(node.kind()) { |
1443 | Some(node) |
1444 | } else { |
1445 | node.next_sibling_or_token_by_kind(&matcher) |
1446 | } |
1447 | }), |
1448 | matcher, |
1449 | } |
1450 | } |
1451 | } |
1452 | } |
1453 | |
1454 | impl Iterator for SyntaxElementChildren { |
1455 | type Item = SyntaxElement; |
1456 | fn next(&mut self) -> Option<SyntaxElement> { |
1457 | if !self.next_initialized { |
1458 | self.next = self.parent.first_child_or_token(); |
1459 | self.next_initialized = true; |
1460 | } else { |
1461 | self.next = self.next.take().and_then(|next: NodeOrToken| next.to_next_sibling_or_token()); |
1462 | } |
1463 | |
1464 | self.next.clone() |
1465 | } |
1466 | } |
1467 | |
1468 | #[derive (Clone, Debug)] |
1469 | pub struct SyntaxElementChildrenByKind<F: Fn(SyntaxKind) -> bool> { |
1470 | next: Option<SyntaxElement>, |
1471 | matcher: F, |
1472 | } |
1473 | |
1474 | impl<F: Fn(SyntaxKind) -> bool> Iterator for SyntaxElementChildrenByKind<F> { |
1475 | type Item = SyntaxElement; |
1476 | fn next(&mut self) -> Option<SyntaxElement> { |
1477 | self.next.take().map(|next: NodeOrToken| { |
1478 | self.next = next.next_sibling_or_token_by_kind(&self.matcher); |
1479 | next |
1480 | }) |
1481 | } |
1482 | } |
1483 | |
1484 | pub struct Preorder { |
1485 | start: SyntaxNode, |
1486 | next: Option<WalkEvent<SyntaxNode>>, |
1487 | skip_subtree: bool, |
1488 | } |
1489 | |
1490 | impl Preorder { |
1491 | fn new(start: SyntaxNode) -> Preorder { |
1492 | let next: Option> = Some(WalkEvent::Enter(start.clone())); |
1493 | Preorder { start, next, skip_subtree: false } |
1494 | } |
1495 | |
1496 | pub fn skip_subtree(&mut self) { |
1497 | self.skip_subtree = true; |
1498 | } |
1499 | |
1500 | #[cold ] |
1501 | fn do_skip(&mut self) { |
1502 | self.next = self.next.take().map(|next: WalkEvent| match next { |
1503 | WalkEvent::Enter(first_child: SyntaxNode) => WalkEvent::Leave(first_child.parent().unwrap()), |
1504 | WalkEvent::Leave(parent: SyntaxNode) => WalkEvent::Leave(parent), |
1505 | }) |
1506 | } |
1507 | } |
1508 | |
1509 | impl Iterator for Preorder { |
1510 | type Item = WalkEvent<SyntaxNode>; |
1511 | |
1512 | fn next(&mut self) -> Option<WalkEvent<SyntaxNode>> { |
1513 | if self.skip_subtree { |
1514 | self.do_skip(); |
1515 | self.skip_subtree = false; |
1516 | } |
1517 | let next = self.next.take(); |
1518 | self.next = next.as_ref().and_then(|next| { |
1519 | Some(match next { |
1520 | WalkEvent::Enter(node) => match node.first_child() { |
1521 | Some(child) => WalkEvent::Enter(child), |
1522 | None => WalkEvent::Leave(node.clone()), |
1523 | }, |
1524 | WalkEvent::Leave(node) => { |
1525 | if node == &self.start { |
1526 | return None; |
1527 | } |
1528 | match node.next_sibling() { |
1529 | Some(sibling) => WalkEvent::Enter(sibling), |
1530 | None => WalkEvent::Leave(node.parent()?), |
1531 | } |
1532 | } |
1533 | }) |
1534 | }); |
1535 | next |
1536 | } |
1537 | } |
1538 | |
1539 | pub struct PreorderWithTokens { |
1540 | start: SyntaxElement, |
1541 | next: Option<WalkEvent<SyntaxElement>>, |
1542 | skip_subtree: bool, |
1543 | } |
1544 | |
1545 | impl PreorderWithTokens { |
1546 | fn new(start: SyntaxNode) -> PreorderWithTokens { |
1547 | let next: Option>> = Some(WalkEvent::Enter(start.clone().into())); |
1548 | PreorderWithTokens { start: start.into(), next, skip_subtree: false } |
1549 | } |
1550 | |
1551 | pub fn skip_subtree(&mut self) { |
1552 | self.skip_subtree = true; |
1553 | } |
1554 | |
1555 | #[cold ] |
1556 | fn do_skip(&mut self) { |
1557 | self.next = self.next.take().map(|next: WalkEvent>| match next { |
1558 | WalkEvent::Enter(first_child: NodeOrToken) => WalkEvent::Leave(first_child.parent().unwrap().into()), |
1559 | WalkEvent::Leave(parent: NodeOrToken) => WalkEvent::Leave(parent), |
1560 | }) |
1561 | } |
1562 | } |
1563 | |
1564 | impl Iterator for PreorderWithTokens { |
1565 | type Item = WalkEvent<SyntaxElement>; |
1566 | |
1567 | fn next(&mut self) -> Option<WalkEvent<SyntaxElement>> { |
1568 | if self.skip_subtree { |
1569 | self.do_skip(); |
1570 | self.skip_subtree = false; |
1571 | } |
1572 | let next = self.next.take(); |
1573 | self.next = next.as_ref().and_then(|next| { |
1574 | Some(match next { |
1575 | WalkEvent::Enter(el) => match el { |
1576 | NodeOrToken::Node(node) => match node.first_child_or_token() { |
1577 | Some(child) => WalkEvent::Enter(child), |
1578 | None => WalkEvent::Leave(node.clone().into()), |
1579 | }, |
1580 | NodeOrToken::Token(token) => WalkEvent::Leave(token.clone().into()), |
1581 | }, |
1582 | WalkEvent::Leave(el) if el == &self.start => return None, |
1583 | WalkEvent::Leave(el) => match el.next_sibling_or_token() { |
1584 | Some(sibling) => WalkEvent::Enter(sibling), |
1585 | None => WalkEvent::Leave(el.parent()?.into()), |
1586 | }, |
1587 | }) |
1588 | }); |
1589 | next |
1590 | } |
1591 | } |
1592 | // endregion |
1593 | |