1use crate::cursor::{NodeData, SyntaxElement, SyntaxToken, SyntaxTrivia};
2use crate::green::{Child, Children, GreenElementRef, Slot};
3use crate::{
4 Direction, GreenNode, GreenNodeData, NodeOrToken, RawSyntaxKind, SyntaxNodeText, TokenAtOffset,
5 WalkEvent,
6};
7use biome_text_size::{TextRange, TextSize};
8use std::hash::{Hash, Hasher};
9use std::iter::FusedIterator;
10use std::ops;
11use std::ptr::NonNull;
12use std::rc::Rc;
13use std::{fmt, iter};
14
15use super::{GreenElement, NodeKind, WeakGreenElement};
16
17#[derive(Clone)]
18pub(crate) struct SyntaxNode {
19 pub(super) ptr: Rc<NodeData>,
20}
21
22impl SyntaxNode {
23 pub(crate) fn new_root(green: GreenNode) -> SyntaxNode {
24 SyntaxNode {
25 ptr: NodeData::new(
26 NodeKind::Root {
27 green: GreenElement::Node(green),
28 },
29 0,
30 0.into(),
31 ),
32 }
33 }
34
35 pub(super) fn new_child(
36 green: &GreenNodeData,
37 parent: SyntaxNode,
38 slot: u32,
39 offset: TextSize,
40 ) -> SyntaxNode {
41 SyntaxNode {
42 ptr: NodeData::new(
43 NodeKind::Child {
44 green: WeakGreenElement::new(GreenElementRef::Node(green)),
45 parent: parent.ptr,
46 },
47 slot,
48 offset,
49 ),
50 }
51 }
52
53 pub fn clone_subtree(&self) -> SyntaxNode {
54 SyntaxNode::new_root(self.green().into())
55 }
56
57 #[inline]
58 pub(super) fn data(&self) -> &NodeData {
59 self.ptr.as_ref()
60 }
61
62 #[inline]
63 pub fn kind(&self) -> RawSyntaxKind {
64 self.data().kind()
65 }
66
67 #[inline]
68 pub(super) fn offset(&self) -> TextSize {
69 self.data().offset()
70 }
71
72 pub(crate) fn element_in_slot(&self, slot_index: u32) -> Option<SyntaxElement> {
73 let slot = self
74 .slots()
75 .nth(slot_index as usize)
76 .expect("Slot index out of bounds");
77
78 slot.map(|element| element)
79 }
80
81 #[inline]
82 pub(crate) fn slots(&self) -> SyntaxSlots {
83 SyntaxSlots::new(self.clone())
84 }
85
86 #[inline]
87 pub fn text_range(&self) -> TextRange {
88 self.data().text_range()
89 }
90
91 pub fn text_trimmed_range(&self) -> TextRange {
92 let range = self.text_range();
93 let mut start = range.start();
94 let mut end = range.end();
95
96 let mut token = self.first_token();
98 while let Some(t) = token.take() {
99 let (leading_len, trailing_len, total_len) = t.green().leading_trailing_total_len();
100 let token_len: u32 = (total_len - leading_len - trailing_len).into();
101 if token_len == 0 {
102 start += total_len;
103 token = t.next_token();
104 } else {
105 start += leading_len;
106 }
107 }
108
109 let mut token = self.last_token();
111 while let Some(t) = token.take() {
112 let (leading_len, trailing_len, total_len) = t.green().leading_trailing_total_len();
113 let token_len: u32 = (total_len - leading_len - trailing_len).into();
114 if token_len == 0 {
115 end -= total_len;
116 token = t.prev_token();
117 } else {
118 end -= trailing_len;
119 }
120 }
121
122 TextRange::new(start, end.max(start))
123 }
124
125 pub fn first_leading_trivia(&self) -> Option<SyntaxTrivia> {
126 self.first_token().map(|x| x.leading_trivia())
127 }
128
129 pub fn last_trailing_trivia(&self) -> Option<SyntaxTrivia> {
130 self.last_token().map(|x| x.trailing_trivia())
131 }
132
133 #[inline]
134 pub fn index(&self) -> usize {
135 self.data().slot() as usize
136 }
137
138 #[inline]
139 pub fn text(&self) -> SyntaxNodeText {
140 SyntaxNodeText::new(self.clone())
141 }
142
143 #[inline]
144 pub fn text_trimmed(&self) -> SyntaxNodeText {
145 SyntaxNodeText::with_range(self.clone(), self.text_trimmed_range())
146 }
147
148 #[inline]
149 pub(crate) fn key(&self) -> (NonNull<()>, TextSize) {
150 self.data().key()
151 }
152
153 #[inline]
154 pub(crate) fn green(&self) -> &GreenNodeData {
155 self.data().green().into_node().unwrap()
156 }
157
158 #[inline]
159 pub fn parent(&self) -> Option<SyntaxNode> {
160 self.data().parent_node()
161 }
162
163 #[inline]
164 pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> {
165 iter::successors(Some(self.clone()), SyntaxNode::parent)
166 }
167
168 #[inline]
169 pub fn children(&self) -> SyntaxNodeChildren {
170 SyntaxNodeChildren::new(self.clone())
171 }
172
173 #[inline]
174 pub fn children_with_tokens(&self) -> SyntaxElementChildren {
175 SyntaxElementChildren::new(self.clone())
176 }
177
178 #[inline]
179 pub fn tokens(&self) -> impl DoubleEndedIterator<Item = SyntaxToken> + '_ {
180 self.green().children().filter_map(|child| {
181 child.element().into_token().map(|token| {
182 SyntaxToken::new(
183 token,
184 self.clone(),
185 child.slot(),
186 self.offset() + child.rel_offset(),
187 )
188 })
189 })
190 }
191
192 pub fn first_child(&self) -> Option<SyntaxNode> {
193 self.green().children().find_map(|child| {
194 child.element().into_node().map(|green| {
195 SyntaxNode::new_child(
196 green,
197 self.clone(),
198 child.slot(),
199 self.offset() + child.rel_offset(),
200 )
201 })
202 })
203 }
204
205 pub fn last_child(&self) -> Option<SyntaxNode> {
206 self.green().children().rev().find_map(|child| {
207 child.element().into_node().map(|green| {
208 SyntaxNode::new_child(
209 green,
210 self.clone(),
211 child.slot(),
212 self.offset() + child.rel_offset(),
213 )
214 })
215 })
216 }
217
218 pub fn first_child_or_token(&self) -> Option<SyntaxElement> {
219 self.green().children().next().map(|child| {
220 SyntaxElement::new(
221 child.element(),
222 self.clone(),
223 child.slot(),
224 self.offset() + child.rel_offset(),
225 )
226 })
227 }
228 pub fn last_child_or_token(&self) -> Option<SyntaxElement> {
229 self.green().children().next_back().map(|child| {
230 SyntaxElement::new(
231 child.element(),
232 self.clone(),
233 child.slot(),
234 self.offset() + child.rel_offset(),
235 )
236 })
237 }
238
239 pub fn next_sibling(&self) -> Option<SyntaxNode> {
240 self.data().next_sibling()
241 }
242 pub fn prev_sibling(&self) -> Option<SyntaxNode> {
243 self.data().prev_sibling()
244 }
245
246 pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
247 self.data().next_sibling_or_token()
248 }
249 pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
250 self.data().prev_sibling_or_token()
251 }
252
253 pub fn first_token(&self) -> Option<SyntaxToken> {
254 self.descendants_with_tokens(Direction::Next)
255 .find_map(|x| x.into_token())
256 }
257
258 pub fn last_token(&self) -> Option<SyntaxToken> {
259 PreorderWithTokens::new(self.clone(), Direction::Prev)
260 .filter_map(|event| match event {
261 WalkEvent::Enter(it) => Some(it),
262 WalkEvent::Leave(_) => None,
263 })
264 .find_map(|x| x.into_token())
265 }
266
267 #[inline]
268 pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = SyntaxNode> {
269 iter::successors(Some(self.clone()), move |node| match direction {
270 Direction::Next => node.next_sibling(),
271 Direction::Prev => node.prev_sibling(),
272 })
273 }
274
275 #[inline]
276 pub fn siblings_with_tokens(
277 &self,
278 direction: Direction,
279 ) -> impl Iterator<Item = SyntaxElement> {
280 let me: SyntaxElement = self.clone().into();
281 iter::successors(Some(me), move |el| match direction {
282 Direction::Next => el.next_sibling_or_token(),
283 Direction::Prev => el.prev_sibling_or_token(),
284 })
285 }
286
287 #[inline]
288 pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode> {
289 self.preorder().filter_map(|event| match event {
290 WalkEvent::Enter(node) => Some(node),
291 WalkEvent::Leave(_) => None,
292 })
293 }
294
295 #[inline]
296 pub fn descendants_with_tokens(
297 &self,
298 direction: Direction,
299 ) -> impl Iterator<Item = SyntaxElement> {
300 self.preorder_with_tokens(direction)
301 .filter_map(|event| match event {
302 WalkEvent::Enter(it) => Some(it),
303 WalkEvent::Leave(_) => None,
304 })
305 }
306
307 #[inline]
308 pub fn preorder(&self) -> Preorder {
309 Preorder::new(self.clone())
310 }
311
312 #[inline]
313 pub fn preorder_with_tokens(&self, direction: Direction) -> PreorderWithTokens {
314 PreorderWithTokens::new(self.clone(), direction)
315 }
316
317 pub(crate) fn preorder_slots(&self) -> SlotsPreorder {
318 SlotsPreorder::new(self.clone())
319 }
320
321 pub fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
322 let range = self.text_range();
326 assert!(
327 range.start() <= offset && offset <= range.end(),
328 "Bad offset: range {range:?} offset {offset:?}"
329 );
330 if range.is_empty() {
331 return TokenAtOffset::None;
332 }
333
334 let mut children = self.children_with_tokens().filter(|child| {
335 let child_range = child.text_range();
336 !child_range.is_empty() && child_range.contains_inclusive(offset)
337 });
338
339 let left = children.next().unwrap();
340 let right = children.next();
341 assert!(children.next().is_none());
342
343 if let Some(right) = right {
344 match (left.token_at_offset(offset), right.token_at_offset(offset)) {
345 (TokenAtOffset::Single(left), TokenAtOffset::Single(right)) => {
346 TokenAtOffset::Between(left, right)
347 }
348 _ => unreachable!(),
349 }
350 } else {
351 left.token_at_offset(offset)
352 }
353 }
354
355 pub fn covering_element(&self, range: TextRange) -> SyntaxElement {
356 let mut res: SyntaxElement = self.clone().into();
357 loop {
358 assert!(
359 res.text_range().contains_range(range),
360 "Bad range: node range {:?}, range {:?}",
361 res.text_range(),
362 range,
363 );
364 res = match &res {
365 NodeOrToken::Token(_) => return res,
366 NodeOrToken::Node(node) => match node.child_or_token_at_range(range) {
367 Some(it) => it,
368 None => return res,
369 },
370 };
371 }
372 }
373
374 pub fn child_or_token_at_range(&self, range: TextRange) -> Option<SyntaxElement> {
375 let rel_range = range - self.offset();
376 self.green()
377 .slot_at_range(rel_range)
378 .and_then(|(index, rel_offset, slot)| {
379 slot.as_ref().map(|green| {
380 SyntaxElement::new(
381 green,
382 self.clone(),
383 index as u32,
384 self.offset() + rel_offset,
385 )
386 })
387 })
388 }
389
390 #[must_use = "syntax elements are immutable, the result of update methods must be propagated to have any effect"]
391 pub fn detach(self) -> Self {
392 Self {
393 ptr: self.ptr.detach(),
394 }
395 }
396
397 #[must_use = "syntax elements are immutable, the result of update methods must be propagated to have any effect"]
398 pub fn splice_slots<R, I>(self, range: R, replace_with: I) -> Self
399 where
400 R: ops::RangeBounds<usize>,
401 I: Iterator<Item = Option<SyntaxElement>>,
402 {
403 Self {
404 ptr: self.ptr.splice_slots(
405 range,
406 replace_with.into_iter().map(|element| {
407 element.map(|child| match child.detach() {
408 NodeOrToken::Node(it) => it.ptr.into_green(),
409 NodeOrToken::Token(it) => it.into_green(),
410 })
411 }),
412 ),
413 }
414 }
415
416 #[must_use = "syntax elements are immutable, the result of update methods must be propagated to have any effect"]
417 pub fn replace_child(self, prev_elem: SyntaxElement, next_elem: SyntaxElement) -> Option<Self> {
418 Some(Self {
419 ptr: self.ptr.replace_child(prev_elem, next_elem)?,
420 })
421 }
422}
423
424impl PartialEq for SyntaxNode {
426 #[inline]
427 fn eq(&self, other: &SyntaxNode) -> bool {
428 self.data().key() == other.data().key()
429 }
430}
431
432impl Eq for SyntaxNode {}
433
434impl Hash for SyntaxNode {
435 #[inline]
436 fn hash<H: Hasher>(&self, state: &mut H) {
437 self.data().key().hash(state);
438 }
439}
440
441impl fmt::Debug for SyntaxNode {
442 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
443 f.debug_struct("SyntaxNode")
444 .field("kind", &self.kind())
445 .field("text_range", &self.text_range())
446 .finish()
447 }
448}
449
450impl fmt::Display for SyntaxNode {
451 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
452 self.preorder_with_tokens(Direction::Next)
453 .filter_map(|event| match event {
454 WalkEvent::Enter(NodeOrToken::Token(token)) => Some(token),
455 _ => None,
456 })
457 .try_for_each(|it| fmt::Display::fmt(&it, f))
458 }
459}
460
461#[derive(Clone, Debug)]
464pub(crate) struct SyntaxNodeChildren {
465 next: Option<SyntaxNode>,
466}
467
468impl SyntaxNodeChildren {
469 fn new(parent: SyntaxNode) -> SyntaxNodeChildren {
470 SyntaxNodeChildren {
471 next: parent.first_child(),
472 }
473 }
474}
475
476impl Iterator for SyntaxNodeChildren {
477 type Item = SyntaxNode;
478 fn next(&mut self) -> Option<SyntaxNode> {
479 self.next.take().inspect(|next| {
480 self.next = next.next_sibling();
481 })
482 }
483}
484
485impl FusedIterator for SyntaxNodeChildren {}
486
487#[derive(Clone, Debug, Default)]
488pub(crate) struct SyntaxElementChildren {
489 next: Option<SyntaxElement>,
490}
491
492impl SyntaxElementChildren {
493 fn new(parent: SyntaxNode) -> SyntaxElementChildren {
494 SyntaxElementChildren {
495 next: parent.first_child_or_token(),
496 }
497 }
498}
499
500impl Iterator for SyntaxElementChildren {
501 type Item = SyntaxElement;
502 fn next(&mut self) -> Option<SyntaxElement> {
503 self.next.take().inspect(|next| {
504 self.next = next.next_sibling_or_token();
505 })
506 }
507}
508
509impl FusedIterator for SyntaxElementChildren {}
510
511pub(crate) struct Preorder {
512 start: SyntaxNode,
513 next: Option<WalkEvent<SyntaxNode>>,
514 skip_subtree: bool,
515}
516
517impl Preorder {
518 fn new(start: SyntaxNode) -> Preorder {
519 let next = Some(WalkEvent::Enter(start.clone()));
520 Preorder {
521 start,
522 next,
523 skip_subtree: false,
524 }
525 }
526
527 pub fn skip_subtree(&mut self) {
528 self.skip_subtree = true;
529 }
530
531 #[cold]
532 fn do_skip(&mut self) {
533 self.next = self.next.take().map(|next| match next {
534 WalkEvent::Enter(first_child) => WalkEvent::Leave(first_child.parent().unwrap()),
535 WalkEvent::Leave(parent) => WalkEvent::Leave(parent),
536 })
537 }
538}
539
540impl Iterator for Preorder {
541 type Item = WalkEvent<SyntaxNode>;
542
543 fn next(&mut self) -> Option<WalkEvent<SyntaxNode>> {
544 if self.skip_subtree {
545 self.do_skip();
546 self.skip_subtree = false;
547 }
548 let next = self.next.take();
549 self.next = next.as_ref().and_then(|next| {
550 Some(match next {
551 WalkEvent::Enter(node) => match node.first_child() {
552 Some(child) => WalkEvent::Enter(child),
553 None => WalkEvent::Leave(node.clone()),
554 },
555 WalkEvent::Leave(node) => {
556 if node == &self.start {
557 return None;
558 }
559 match node.next_sibling() {
560 Some(sibling) => WalkEvent::Enter(sibling),
561 None => WalkEvent::Leave(node.parent()?),
562 }
563 }
564 })
565 });
566 next
567 }
568}
569
570impl FusedIterator for Preorder {}
571
572pub(crate) struct PreorderWithTokens {
573 start: SyntaxElement,
574 next: Option<WalkEvent<SyntaxElement>>,
575 skip_subtree: bool,
576 direction: Direction,
577}
578
579impl PreorderWithTokens {
580 fn new(start: SyntaxNode, direction: Direction) -> PreorderWithTokens {
581 let next = Some(WalkEvent::Enter(start.clone().into()));
582 PreorderWithTokens {
583 start: start.into(),
584 next,
585 direction,
586 skip_subtree: false,
587 }
588 }
589
590 pub fn skip_subtree(&mut self) {
591 self.skip_subtree = true;
592 }
593
594 #[cold]
595 fn do_skip(&mut self) {
596 self.next = self.next.take().map(|next| match next {
597 WalkEvent::Enter(first_child) => WalkEvent::Leave(first_child.parent().unwrap().into()),
598 WalkEvent::Leave(parent) => WalkEvent::Leave(parent),
599 })
600 }
601}
602
603impl Iterator for PreorderWithTokens {
604 type Item = WalkEvent<SyntaxElement>;
605
606 fn next(&mut self) -> Option<WalkEvent<SyntaxElement>> {
607 if self.skip_subtree {
608 self.do_skip();
609 self.skip_subtree = false;
610 }
611 let next = self.next.take();
612 self.next = next.as_ref().and_then(|next| {
613 Some(match next {
614 WalkEvent::Enter(el) => match el {
615 NodeOrToken::Node(node) => {
616 let next = match self.direction {
617 Direction::Next => node.first_child_or_token(),
618 Direction::Prev => node.last_child_or_token(),
619 };
620 match next {
621 Some(child) => WalkEvent::Enter(child),
622 None => WalkEvent::Leave(node.clone().into()),
623 }
624 }
625 NodeOrToken::Token(token) => WalkEvent::Leave(token.clone().into()),
626 },
627 WalkEvent::Leave(el) if el == &self.start => return None,
628 WalkEvent::Leave(el) => {
629 let next = match self.direction {
630 Direction::Next => el.next_sibling_or_token(),
631 Direction::Prev => el.prev_sibling_or_token(),
632 };
633
634 match next {
635 Some(sibling) => WalkEvent::Enter(sibling),
636 None => WalkEvent::Leave(el.parent()?.into()),
637 }
638 }
639 })
640 });
641 next
642 }
643}
644
645impl FusedIterator for PreorderWithTokens {}
646
647#[derive(Debug, Clone)]
650pub(crate) enum SyntaxSlot {
651 Node(SyntaxNode),
652 Token(SyntaxToken),
653 Empty { parent: SyntaxNode, index: u32 },
654}
655
656impl From<SyntaxElement> for SyntaxSlot {
657 fn from(element: SyntaxElement) -> Self {
658 match element {
659 SyntaxElement::Node(node) => SyntaxSlot::Node(node),
660 SyntaxElement::Token(token) => SyntaxSlot::Token(token),
661 }
662 }
663}
664
665impl SyntaxSlot {
666 #[inline]
667 pub fn map<F, R>(self, mapper: F) -> Option<R>
668 where
669 F: FnOnce(SyntaxElement) -> R,
670 {
671 match self {
672 SyntaxSlot::Node(node) => Some(mapper(SyntaxElement::Node(node))),
673 SyntaxSlot::Token(token) => Some(mapper(SyntaxElement::Token(token))),
674 SyntaxSlot::Empty { .. } => None,
675 }
676 }
677}
678
679#[derive(Debug, Clone)]
681pub(crate) struct SyntaxSlots {
682 pos: u32,
684
685 back_pos: u32,
690 parent: SyntaxNode,
691}
692
693impl SyntaxSlots {
694 #[inline]
695 fn new(parent: SyntaxNode) -> Self {
696 Self {
697 pos: 0,
698 back_pos: parent.green().slice().len() as u32,
699 parent,
700 }
701 }
702
703 #[inline]
706 fn slice(&self) -> &[Slot] {
707 if self.pos < self.back_pos {
708 &self.parent.green().slice()[self.pos as usize..self.back_pos as usize]
709 } else {
710 &[]
711 }
712 }
713
714 fn map_slot(&self, slot: &Slot, slot_index: u32) -> SyntaxSlot {
715 match slot {
716 Slot::Empty { .. } => SyntaxSlot::Empty {
717 parent: self.parent.clone(),
718 index: slot_index,
719 },
720 Slot::Token { rel_offset, token } => SyntaxSlot::Token(SyntaxToken::new(
721 token,
722 self.parent.clone(),
723 slot_index,
724 self.parent.offset() + rel_offset,
725 )),
726 Slot::Node { rel_offset, node } => SyntaxSlot::Node(SyntaxNode::new_child(
727 node,
728 self.parent.clone(),
729 slot_index,
730 self.parent.offset() + rel_offset,
731 )),
732 }
733 }
734}
735
736impl Iterator for SyntaxSlots {
737 type Item = SyntaxSlot;
738
739 #[inline]
740 fn next(&mut self) -> Option<Self::Item> {
741 let slot = self.slice().first()?;
742 let mapped = self.map_slot(slot, self.pos);
743 self.pos += 1;
744 Some(mapped)
745 }
746
747 #[inline(always)]
748 fn size_hint(&self) -> (usize, Option<usize>) {
749 let len = self.slice().len();
750 (len, Some(len))
751 }
752
753 #[inline(always)]
754 fn count(self) -> usize
755 where
756 Self: Sized,
757 {
758 self.len()
759 }
760
761 #[inline]
762 fn last(mut self) -> Option<Self::Item>
763 where
764 Self: Sized,
765 {
766 self.next_back()
767 }
768
769 #[inline]
770 fn nth(&mut self, n: usize) -> Option<Self::Item> {
771 self.pos += n as u32;
772 self.next()
773 }
774}
775
776impl ExactSizeIterator for SyntaxSlots {
777 #[inline(always)]
778 fn len(&self) -> usize {
779 self.slice().len()
780 }
781}
782
783impl FusedIterator for SyntaxSlots {}
784
785impl DoubleEndedIterator for SyntaxSlots {
786 #[inline]
787 fn next_back(&mut self) -> Option<Self::Item> {
788 let slot = self.slice().last()?;
789 let mapped = self.map_slot(slot, self.back_pos - 1);
790 self.back_pos -= 1;
791 Some(mapped)
792 }
793
794 #[inline]
795 fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
796 self.back_pos -= n as u32;
797 self.next_back()
798 }
799}
800
801pub(crate) struct SlotsPreorder {
803 start: SyntaxNode,
804 next: Option<WalkEvent<SyntaxSlot>>,
805}
806
807impl SlotsPreorder {
808 fn new(start: SyntaxNode) -> Self {
809 let next = Some(WalkEvent::Enter(SyntaxSlot::Node(start.clone())));
810 SlotsPreorder { start, next }
811 }
812}
813
814impl Iterator for SlotsPreorder {
815 type Item = WalkEvent<SyntaxSlot>;
816
817 fn next(&mut self) -> Option<WalkEvent<SyntaxSlot>> {
818 let next = self.next.take();
819 self.next = next.as_ref().and_then(|next| {
820 Some(match next {
821 WalkEvent::Enter(slot) => match slot {
822 SyntaxSlot::Empty { .. } | SyntaxSlot::Token(_) => {
823 WalkEvent::Leave(slot.clone())
824 }
825 SyntaxSlot::Node(node) => match node.slots().next() {
826 None => WalkEvent::Leave(SyntaxSlot::Node(node.clone())),
827 Some(first_slot) => WalkEvent::Enter(first_slot),
828 },
829 },
830 WalkEvent::Leave(slot) => {
831 let (parent, slot_index) = match slot {
832 SyntaxSlot::Empty { parent, index } => (parent.clone(), *index as usize),
833 SyntaxSlot::Token(token) => (token.parent()?, token.index()),
834 SyntaxSlot::Node(node) => {
835 if node == &self.start {
836 return None;
837 }
838
839 (node.parent()?, node.index())
840 }
841 };
842
843 let next_slot = parent.slots().nth(slot_index + 1);
844 match next_slot {
845 Some(slot) => WalkEvent::Enter(slot),
846 None => WalkEvent::Leave(SyntaxSlot::Node(parent)),
847 }
848 }
849 })
850 });
851 next
852 }
853}
854
855impl FusedIterator for SlotsPreorder {}
856
857#[derive(Debug, Clone)]
858pub(crate) struct Siblings<'a> {
859 parent: &'a GreenNodeData,
860 start_slot: u32,
861}
862
863impl<'a> Siblings<'a> {
864 pub fn new(parent: &'a GreenNodeData, start_slot: u32) -> Self {
865 assert!(
866 (start_slot as usize) < parent.slots().len(),
867 "Start slot {} out of bounds {}",
868 start_slot,
869 parent.slots().len()
870 );
871
872 Self { parent, start_slot }
873 }
874
875 pub fn following(&self) -> Children<'a> {
880 let mut slots = self.parent.slots().enumerate();
881
882 slots.nth(self.start_slot as usize);
884
885 Children::new(slots)
886 }
887
888 pub fn previous(&self) -> impl Iterator<Item = Child<'a>> {
893 let mut slots = self.parent.slots().enumerate();
894
895 slots.nth_back(slots.len() - 1 - self.start_slot as usize);
898
899 Children::new(slots).rev()
900 }
901}
902
903#[cfg(test)]
906mod tests {
907 use crate::raw_language::{RawLanguageKind, RawSyntaxTreeBuilder};
908
909 #[test]
910 fn slots_iter() {
911 let mut builder = RawSyntaxTreeBuilder::new();
912 builder.start_node(RawLanguageKind::EXPRESSION_LIST);
913
914 for number in [1, 2, 3, 4] {
915 builder.start_node(RawLanguageKind::LITERAL_EXPRESSION);
916 builder.token(RawLanguageKind::NUMBER_TOKEN, &number.to_string());
917 builder.finish_node();
918 }
919 builder.finish_node();
920
921 let list = builder.finish();
922
923 let mut iter = list.slots();
924
925 assert_eq!(iter.size_hint(), (4, Some(4)));
926
927 assert_eq!(
928 iter.next()
929 .and_then(|slot| slot.into_node())
930 .map(|node| node.text().to_string())
931 .as_deref(),
932 Some("1")
933 );
934
935 assert_eq!(iter.size_hint(), (3, Some(3)));
936
937 assert_eq!(
938 iter.next_back()
939 .and_then(|slot| slot.into_node())
940 .map(|node| node.text().to_string())
941 .as_deref(),
942 Some("4")
943 );
944
945 assert_eq!(iter.size_hint(), (2, Some(2)));
946
947 assert_eq!(
948 iter.last()
949 .and_then(|slot| slot.into_node())
950 .map(|node| node.text().to_string())
951 .as_deref(),
952 Some("3")
953 );
954 }
955}