1use super::{element::SyntaxElement, traversal::Descendants};
2use crate::{
3 AmberNode, GreenNode, GreenToken, NodeOrToken, SyntaxKind, SyntaxKindMatch, SyntaxNodeChildren, SyntaxToken,
4 TokenAtOffset, green::GreenChild,
5};
6use std::{fmt, ptr::NonNull, rc::Rc};
7use text_size::{TextRange, TextSize};
8
9#[derive(Clone, PartialEq, Eq, Hash)]
10pub struct SyntaxNode {
12 pub(crate) data: Rc<NodeData>,
13}
14
15impl SyntaxNode {
16 #[inline]
17 pub fn new_root(green: GreenNode) -> Self {
19 SyntaxNode {
20 data: Rc::new(NodeData {
21 range: TextRange::new(0.into(), green.text_len()),
22 level: NodeLevel::Root { green },
23 index: 0,
24 }),
25 }
26 }
27
28 #[inline]
29 pub(crate) fn new(index: u32, green: &GreenNode, offset: TextSize, parent: Rc<NodeData>) -> Self {
30 SyntaxNode {
31 data: Rc::new(NodeData {
32 range: TextRange::new(offset, offset + green.text_len()),
33 level: NodeLevel::Child {
34 green: NonNull::from(green),
35 parent,
36 },
37 index,
38 }),
39 }
40 }
41 #[inline]
42 pub(crate) fn new_child(&self, index: u32, green: &GreenNode, offset: TextSize) -> Self {
43 SyntaxNode::new(index, green, self.data.range.start() + offset, Rc::clone(&self.data))
44 }
45 #[inline]
46 pub(crate) fn new_token(&self, index: u32, green: &GreenToken, offset: TextSize) -> SyntaxToken {
47 SyntaxToken::new(index, green, self.data.range.start() + offset, Rc::clone(&self.data))
48 }
49
50 #[inline]
51 pub fn kind(&self) -> SyntaxKind {
53 self.green().kind()
54 }
55
56 #[inline]
57 pub fn text_range(&self) -> TextRange {
59 self.data.range
60 }
61
62 #[inline]
63 pub fn green(&self) -> &GreenNode {
65 self.data.green()
66 }
67
68 #[inline]
69 pub fn amber(&self) -> AmberNode<'_> {
71 self.into()
72 }
73
74 #[inline]
75 pub fn parent(&self) -> Option<SyntaxNode> {
77 match &self.data.level {
78 NodeLevel::Root { .. } => None,
79 NodeLevel::Child { parent, .. } => Some(SyntaxNode {
80 data: Rc::clone(parent),
81 }),
82 }
83 }
84
85 #[inline]
86 pub fn ancestors(&self) -> impl Iterator<Item = SyntaxNode> {
88 std::iter::successors(Some(self.clone()), SyntaxNode::parent)
89 }
90
91 #[inline]
92 pub fn children(&self) -> SyntaxNodeChildren {
99 SyntaxNodeChildren {
100 parent: self.clone(),
101 green: match &self.data.level {
102 NodeLevel::Root { green } => NonNull::from(green),
103 NodeLevel::Child { green, .. } => *green,
104 },
105 index: 0,
106 }
107 }
108
109 #[inline]
110 pub fn children_by_kind<M>(&self, matcher: M) -> impl DoubleEndedIterator<Item = SyntaxNode> + use<'_, M>
113 where
114 M: SyntaxKindMatch,
115 {
116 self.green()
117 .slice()
118 .iter()
119 .enumerate()
120 .filter_map(move |(i, child)| match child {
121 GreenChild::Node { offset, node } if matcher.matches(node.kind()) => {
122 Some(self.new_child(i as u32, node, *offset))
123 }
124 _ => None,
125 })
126 }
127
128 #[inline]
129 pub fn tokens_by_kind<M>(&self, matcher: M) -> impl DoubleEndedIterator<Item = SyntaxToken> + use<'_, M>
131 where
132 M: SyntaxKindMatch,
133 {
134 self.green()
135 .slice()
136 .iter()
137 .enumerate()
138 .filter_map(move |(i, child)| match child {
139 GreenChild::Token { offset, token } if matcher.matches(token.kind()) => {
140 Some(self.new_token(i as u32, token, *offset))
141 }
142 _ => None,
143 })
144 }
145
146 #[inline]
147 pub fn children_with_tokens(&self) -> impl DoubleEndedIterator<Item = SyntaxElement> {
149 self.green().slice().iter().enumerate().map(|(i, child)| match child {
150 GreenChild::Node { offset, node } => self.new_child(i as u32, node, *offset).into(),
151 GreenChild::Token { offset, token } => self.new_token(i as u32, token, *offset).into(),
152 })
153 }
154
155 #[inline]
156 pub fn has_child_or_token_by_kind<M>(&self, matcher: M) -> bool
161 where
162 M: SyntaxKindMatch,
163 {
164 self.green().slice().iter().any(|child| match child {
165 GreenChild::Node { node, .. } => matcher.matches(node.kind()),
166 GreenChild::Token { token, .. } => matcher.matches(token.kind()),
167 })
168 }
169
170 #[inline]
171 pub fn next_siblings(&self) -> impl Iterator<Item = SyntaxNode> {
177 match &self.data.level {
178 NodeLevel::Root { .. } => None,
179 NodeLevel::Child { parent, .. } => Some(parent),
180 }
181 .into_iter()
182 .flat_map(|parent| parent.next_children(self.data.index))
183 }
184
185 #[inline]
186 pub fn next_sibling_or_token(&self) -> Option<SyntaxElement> {
188 match &self.data.level {
189 NodeLevel::Root { .. } => None,
190 NodeLevel::Child { parent, .. } => parent.next_child_or_token(self.data.index),
191 }
192 }
193
194 #[inline]
195 pub fn next_siblings_with_tokens(&self) -> impl Iterator<Item = SyntaxElement> {
199 match &self.data.level {
200 NodeLevel::Root { .. } => None,
201 NodeLevel::Child { parent, .. } => Some(parent),
202 }
203 .into_iter()
204 .flat_map(|parent| parent.next_children_with_tokens(self.data.index))
205 }
206
207 #[inline]
208 pub fn next_consecutive_tokens(&self) -> impl Iterator<Item = SyntaxToken> {
210 match &self.data.level {
211 NodeLevel::Root { .. } => None,
212 NodeLevel::Child { parent, .. } => Some(parent),
213 }
214 .into_iter()
215 .flat_map(|parent| parent.next_consecutive_tokens(self.data.index))
216 }
217
218 #[inline]
219 pub fn prev_siblings(&self) -> impl Iterator<Item = SyntaxNode> {
225 match &self.data.level {
226 NodeLevel::Root { .. } => None,
227 NodeLevel::Child { parent, .. } => Some(parent),
228 }
229 .into_iter()
230 .flat_map(|parent| parent.prev_children(self.data.index))
231 }
232
233 #[inline]
234 pub fn prev_sibling_or_token(&self) -> Option<SyntaxElement> {
236 match &self.data.level {
237 NodeLevel::Root { .. } => None,
238 NodeLevel::Child { parent, .. } => parent.prev_child_or_token(self.data.index),
239 }
240 }
241
242 #[inline]
243 pub fn prev_siblings_with_tokens(&self) -> impl Iterator<Item = SyntaxElement> {
247 match &self.data.level {
248 NodeLevel::Root { .. } => None,
249 NodeLevel::Child { parent, .. } => Some(parent),
250 }
251 .into_iter()
252 .flat_map(|parent| parent.prev_children_with_tokens(self.data.index))
253 }
254
255 #[inline]
256 pub fn prev_consecutive_tokens(&self) -> impl Iterator<Item = SyntaxToken> {
258 match &self.data.level {
259 NodeLevel::Root { .. } => None,
260 NodeLevel::Child { parent, .. } => Some(parent),
261 }
262 .into_iter()
263 .flat_map(|parent| parent.prev_consecutive_tokens(self.data.index))
264 }
265
266 #[inline]
267 pub fn descendants(&self) -> impl Iterator<Item = SyntaxNode> {
269 Descendants::new(self.clone())
270 }
271
272 pub fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset {
275 let range = self.data.range;
276 let relative_offset = offset - range.start();
277 let mut children = self
278 .green()
279 .slice()
280 .iter()
281 .enumerate()
282 .filter(|(_, child)| {
283 let (start, end) = match child {
284 GreenChild::Node { offset, node } => (*offset, offset + node.text_len()),
285 GreenChild::Token { offset, token } => (*offset, offset + token.text_len()),
286 };
287 start <= relative_offset && relative_offset <= end
288 })
289 .map(|(i, child)| match child {
290 GreenChild::Node { offset, node } => NodeOrToken::Node(self.new_child(i as u32, node, *offset)),
291 GreenChild::Token { offset, token } => NodeOrToken::Token(self.new_token(i as u32, token, *offset)),
292 });
293
294 let Some(left) = children.next() else {
295 return TokenAtOffset::None;
296 };
297 let right = children.next();
298 if let Some(right) = right {
299 match (left.token_at_offset(offset), right.token_at_offset(offset)) {
300 (TokenAtOffset::Single(left), TokenAtOffset::Single(right)) => TokenAtOffset::Between(left, right),
301 _ => TokenAtOffset::None,
302 }
303 } else {
304 left.token_at_offset(offset)
305 }
306 }
307
308 #[inline]
309 pub fn child_at_range(&self, range: TextRange) -> Option<SyntaxNode> {
311 if !self.data.range.contains_range(range) {
312 return None;
313 }
314 let relative_range = range - self.data.range.start();
315 let slice = self.green().slice();
316 let i = slice
317 .binary_search_by(|child| match child {
318 GreenChild::Node { offset, node } => {
319 TextRange::new(*offset, offset + node.text_len()).ordering(relative_range)
320 }
321 GreenChild::Token { offset, token } => {
322 TextRange::new(*offset, offset + token.text_len()).ordering(relative_range)
323 }
324 })
325 .unwrap_or_else(|i| i.saturating_sub(1)); slice.get(i).and_then(|child| match child {
327 GreenChild::Node { offset, node } => {
328 if TextRange::new(*offset, offset + node.text_len()).contains_range(relative_range) {
329 Some(self.new_child(i as u32, node, *offset))
330 } else {
331 None
332 }
333 }
334 GreenChild::Token { .. } => None,
335 })
336 }
337
338 #[inline]
339 pub fn replace_with(&self, replacement: GreenNode) -> GreenNode {
341 match &self.data.level {
342 NodeLevel::Root { .. } => replacement,
343 NodeLevel::Child { parent, .. } => {
344 let parent = SyntaxNode {
345 data: Rc::clone(parent),
346 };
347 let new_parent = parent.green().replace_child(self.data.index as usize, replacement);
348 parent.replace_with(new_parent)
349 }
350 }
351 }
352}
353
354impl fmt::Debug for SyntaxNode {
355 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356 debug_print_node(self, f, 0)
357 }
358}
359fn debug_print_node(node: &SyntaxNode, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
360 writeln!(f, "{}{:?}@{:?}", " ".repeat(level), node.kind(), node.text_range())?;
361 node.children_with_tokens()
362 .try_for_each(|node_or_token| match node_or_token {
363 NodeOrToken::Node(node) => debug_print_node(&node, f, level + 1),
364 NodeOrToken::Token(token) => writeln!(f, "{}{token:?}", " ".repeat(level + 1)),
365 })
366}
367
368impl fmt::Display for SyntaxNode {
369 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370 self.green().fmt(f)
371 }
372}
373
374#[derive(PartialEq, Eq, Hash)]
375pub(crate) struct NodeData {
376 range: TextRange,
377 level: NodeLevel,
378 index: u32,
379}
380
381impl NodeData {
382 #[inline]
383 fn green(&self) -> &GreenNode {
384 match &self.level {
385 NodeLevel::Root { green } => green,
386 NodeLevel::Child { green, .. } => unsafe { green.as_ref() },
387 }
388 }
389
390 #[inline]
391 pub fn next_children(self: &Rc<Self>, index: u32) -> impl Iterator<Item = SyntaxNode> {
392 self.green()
393 .slice()
394 .iter()
395 .enumerate()
396 .skip(index as usize + 1)
397 .filter_map(|(i, child)| match child {
398 GreenChild::Node { offset, node } => Some(SyntaxNode::new(
399 i as u32,
400 node,
401 self.range.start() + offset,
402 Rc::clone(self),
403 )),
404 _ => None,
405 })
406 }
407
408 #[inline]
409 pub fn next_child_or_token(self: &Rc<Self>, index: u32) -> Option<SyntaxElement> {
410 let i = index + 1;
411 self.green().slice().get(i as usize).map(|child| match child {
412 GreenChild::Node { offset, node } => {
413 SyntaxNode::new(i, node, self.range.start() + offset, Rc::clone(self)).into()
414 }
415 GreenChild::Token { offset, token } => {
416 SyntaxToken::new(i, token, self.range.start() + offset, Rc::clone(self)).into()
417 }
418 })
419 }
420
421 #[inline]
422 pub fn next_children_with_tokens(self: &Rc<Self>, index: u32) -> impl Iterator<Item = SyntaxElement> {
423 self.green()
424 .slice()
425 .iter()
426 .enumerate()
427 .skip(index as usize + 1)
428 .map(|(i, child)| match child {
429 GreenChild::Node { offset, node } => {
430 SyntaxNode::new(i as u32, node, self.range.start() + offset, Rc::clone(self)).into()
431 }
432 GreenChild::Token { offset, token } => {
433 SyntaxToken::new(i as u32, token, self.range.start() + offset, Rc::clone(self)).into()
434 }
435 })
436 }
437
438 #[inline]
439 pub fn next_consecutive_tokens(self: &Rc<Self>, index: u32) -> impl Iterator<Item = SyntaxToken> {
440 self.green()
441 .slice()
442 .iter()
443 .enumerate()
444 .skip(index as usize + 1)
445 .map_while(|(i, child)| match child {
446 GreenChild::Node { .. } => None,
447 GreenChild::Token { offset, token } => Some(SyntaxToken::new(
448 i as u32,
449 token,
450 self.range.start() + offset,
451 Rc::clone(self),
452 )),
453 })
454 }
455
456 #[inline]
457 pub fn prev_children(self: &Rc<Self>, index: u32) -> impl Iterator<Item = SyntaxNode> {
458 let slice = self.green().slice();
459 slice
460 .iter()
461 .enumerate()
462 .rev()
463 .skip(slice.len() - index as usize)
464 .filter_map(|(i, child)| match child {
465 GreenChild::Node { offset, node } => Some(SyntaxNode::new(
466 i as u32,
467 node,
468 self.range.start() + offset,
469 Rc::clone(self),
470 )),
471 _ => None,
472 })
473 }
474
475 #[inline]
476 pub fn prev_child_or_token(self: &Rc<Self>, index: u32) -> Option<SyntaxElement> {
477 let i = index.checked_sub(1)?;
478 self.green().slice().get(i as usize).map(|child| match child {
479 GreenChild::Node { offset, node } => {
480 SyntaxNode::new(i, node, self.range.start() + offset, Rc::clone(self)).into()
481 }
482 GreenChild::Token { offset, token } => {
483 SyntaxToken::new(i, token, self.range.start() + offset, Rc::clone(self)).into()
484 }
485 })
486 }
487
488 #[inline]
489 pub fn prev_children_with_tokens(self: &Rc<Self>, index: u32) -> impl Iterator<Item = SyntaxElement> {
490 let slice = self.green().slice();
491 slice
492 .iter()
493 .enumerate()
494 .rev()
495 .skip(slice.len() - index as usize)
496 .map(|(i, child)| match child {
497 GreenChild::Node { offset, node } => {
498 SyntaxNode::new(i as u32, node, self.range.start() + offset, Rc::clone(self)).into()
499 }
500 GreenChild::Token { offset, token } => {
501 SyntaxToken::new(i as u32, token, self.range.start() + offset, Rc::clone(self)).into()
502 }
503 })
504 }
505
506 #[inline]
507 pub fn prev_consecutive_tokens(self: &Rc<Self>, index: u32) -> impl Iterator<Item = SyntaxToken> {
508 let slice = self.green().slice();
509 slice
510 .iter()
511 .enumerate()
512 .rev()
513 .skip(slice.len() - index as usize)
514 .map_while(|(i, child)| match child {
515 GreenChild::Node { .. } => None,
516 GreenChild::Token { offset, token } => Some(SyntaxToken::new(
517 i as u32,
518 token,
519 self.range.start() + offset,
520 Rc::clone(self),
521 )),
522 })
523 }
524}
525
526#[derive(PartialEq, Eq, Hash)]
527enum NodeLevel {
528 Root {
529 green: GreenNode,
530 },
531 Child {
532 green: NonNull<GreenNode>,
533 parent: Rc<NodeData>,
534 },
535}