1use crate::{
6 Language,
7 tree::green_tree::{GreenNode, GreenTree},
8};
9use core::range::Range;
10use std::fmt;
11
12pub enum RedTree<'a, L: Language> {
18 Node(RedNode<'a, L>),
20 Leaf(RedLeaf<L>),
22}
23
24impl<'a, L: Language> Clone for RedTree<'a, L> {
26 fn clone(&self) -> Self {
27 *self
28 }
29}
30
31impl<'a, L: Language> Copy for RedTree<'a, L> {}
32
33impl<'a, L: Language> fmt::Debug for RedTree<'a, L> {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 match self {
36 Self::Node(node) => fmt::Debug::fmt(node, f),
37 Self::Leaf(leaf) => fmt::Debug::fmt(leaf, f),
38 }
39 }
40}
41
42impl<'a, L: Language> PartialEq for RedTree<'a, L> {
43 fn eq(&self, other: &Self) -> bool {
44 match (self, other) {
45 (Self::Node(l0), Self::Node(r0)) => l0 == r0,
46 (Self::Leaf(l0), Self::Leaf(r0)) => l0 == r0,
47 _ => false,
48 }
49 }
50}
51
52impl<'a, L: Language> Eq for RedTree<'a, L> {}
53
54impl<'a, L: Language> RedTree<'a, L> {
55 #[inline]
59 pub fn span(&self) -> Range<usize> {
60 match self {
61 RedTree::Node(n) => n.span(),
62 RedTree::Leaf(t) => t.span,
63 }
64 }
65
66 pub fn kind<T>(&self) -> T
72 where
73 T: From<L::ElementType> + From<L::TokenType>,
74 {
75 match self {
76 RedTree::Node(n) => T::from(n.green.kind),
77 RedTree::Leaf(l) => T::from(l.kind),
78 }
79 }
80
81 pub fn text<'s, S: crate::source::Source + ?Sized>(&self, source: &'s S) -> std::borrow::Cow<'s, str> {
87 source.get_text_in(self.span())
88 }
89
90 pub fn children(&self) -> RedChildren<'a, L> {
94 match self {
95 RedTree::Node(n) => n.children(),
96 RedTree::Leaf(_) => RedChildren::empty(),
97 }
98 }
99
100 pub fn as_node(&self) -> Option<RedNode<'a, L>> {
102 match self {
103 RedTree::Node(n) => Some(*n),
104 RedTree::Leaf(_) => None,
105 }
106 }
107
108 pub fn as_token(&self) -> Option<RedLeaf<L>> {
110 match self {
111 RedTree::Node(_) => None,
112 RedTree::Leaf(l) => Some(*l),
113 }
114 }
115
116 #[deprecated(note = "Use `as_token` instead")]
118 pub fn as_leaf(&self) -> Option<RedLeaf<L>> {
119 self.as_token()
120 }
121}
122
123pub struct RedNode<'a, L: Language> {
134 pub green: &'a GreenNode<'a, L>,
136 pub offset: usize,
138}
139
140impl<'a, L: Language> Clone for RedNode<'a, L> {
142 fn clone(&self) -> Self {
143 *self
144 }
145}
146
147impl<'a, L: Language> Copy for RedNode<'a, L> {}
148
149impl<'a, L: Language> PartialEq for RedNode<'a, L> {
150 fn eq(&self, other: &Self) -> bool {
151 self.green == other.green && self.offset == other.offset
152 }
153}
154
155impl<'a, L: Language> Eq for RedNode<'a, L> {}
156
157impl<'a, L: Language> fmt::Debug for RedNode<'a, L> {
158 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159 f.debug_struct("RedNode").field("green", &self.green).field("offset", &self.offset).finish()
160 }
161}
162
163pub struct RedLeaf<L: Language> {
167 pub kind: L::TokenType,
169 pub span: Range<usize>,
171}
172
173impl<L: Language> Clone for RedLeaf<L> {
175 fn clone(&self) -> Self {
176 *self
177 }
178}
179
180impl<L: Language> Copy for RedLeaf<L> {}
181
182impl<L: Language> RedLeaf<L> {
183 #[inline]
185 pub fn kind(&self) -> L::TokenType {
186 self.kind
187 }
188
189 #[inline]
191 pub fn span(&self) -> Range<usize> {
192 self.span.clone()
193 }
194
195 pub fn text<'s, S: crate::source::Source + ?Sized>(&self, source: &'s S) -> std::borrow::Cow<'s, str> {
197 source.get_text_in(self.span())
198 }
199}
200
201impl<L: Language> PartialEq for RedLeaf<L> {
202 fn eq(&self, other: &Self) -> bool {
203 self.kind == other.kind && self.span == other.span
204 }
205}
206
207impl<L: Language> Eq for RedLeaf<L> {}
208
209impl<L: Language> fmt::Debug for RedLeaf<L> {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 f.debug_struct("RedLeaf").field("kind", &self.kind).field("span", &self.span).finish()
212 }
213}
214
215pub struct RedChildren<'a, L: Language> {
220 node: Option<RedNode<'a, L>>,
222 index: usize,
224 offset: usize,
226}
227
228impl<'a, L: Language> RedChildren<'a, L> {
229 pub fn empty() -> Self {
231 Self { node: None, index: 0, offset: 0 }
232 }
233}
234
235impl<'a, L: Language> RedNode<'a, L> {
236 pub fn text<'s, S: crate::source::Source + ?Sized>(&self, source: &'s S) -> std::borrow::Cow<'s, str> {
238 source.get_text_in(self.span())
239 }
240
241 #[inline]
243 pub fn new(green: &'a GreenNode<'a, L>, offset: usize) -> Self {
244 Self { green, offset }
245 }
246
247 #[inline]
249 pub fn span(&self) -> Range<usize> {
250 Range { start: self.offset, end: self.offset + self.green.text_len() as usize }
251 }
252
253 #[inline]
255 pub fn element_type(&self) -> L::ElementType {
256 self.green.kind
257 }
258
259 #[inline]
261 pub fn green(&self) -> &'a GreenNode<'a, L> {
262 self.green
263 }
264
265 pub fn kind<T>(&self) -> T
267 where
268 T: From<L::ElementType>,
269 {
270 T::from(self.green.kind)
271 }
272
273 pub fn child_at(&self, idx: usize) -> RedTree<'a, L> {
283 let children = self.green.children();
284 let green_child = &children[idx];
285
286 let mut offset = self.offset;
288 for i in 0..idx {
289 offset += children[i].len() as usize
290 }
291
292 match green_child {
293 GreenTree::Node(n) => RedTree::Node(RedNode::new(n, offset)),
294 GreenTree::Leaf(t) => RedTree::Leaf(RedLeaf { kind: t.kind, span: Range { start: offset, end: offset + t.length as usize } }),
295 }
296 }
297
298 pub fn children(&self) -> RedChildren<'a, L> {
300 RedChildren { node: Some(*self), index: 0, offset: self.offset }
301 }
302
303 pub fn child_index_at_offset(&self, offset: usize) -> Option<usize> {
309 if offset < self.offset || offset >= self.offset + self.green.text_len() as usize {
310 return None;
311 }
312
313 let relative_offset = (offset - self.offset) as u32;
314 let mut current_pos = 0;
315
316 for (idx, child) in self.green.children().iter().enumerate() {
317 let len = child.len();
318 if relative_offset < current_pos + len {
319 return Some(idx);
320 }
321 current_pos += len
322 }
323
324 None
325 }
326
327 pub fn child_at_offset(&self, offset: usize) -> Option<RedTree<'a, L>> {
333 self.child_index_at_offset(offset).map(|idx| self.child_at(idx))
334 }
335
336 pub fn leaf_at_offset(&self, offset: usize) -> Option<RedLeaf<L>> {
344 let mut current = *self;
345 loop {
346 match current.child_at_offset(offset)? {
347 RedTree::Node(n) => current = n,
348 RedTree::Leaf(l) => return Some(l),
349 }
350 }
351 }
352
353 pub fn first_token(&self) -> Option<RedLeaf<L>> {
355 for child in self.children() {
356 match child {
357 RedTree::Node(_) => continue,
358 RedTree::Leaf(l) => return Some(l),
359 }
360 }
361 None
362 }
363}
364
365impl<'a, L: Language> Iterator for RedChildren<'a, L> {
366 type Item = RedTree<'a, L>;
367
368 fn next(&mut self) -> Option<Self::Item> {
369 let node = self.node.as_ref()?;
370 let children = node.green.children();
371 if self.index >= children.len() {
372 return None;
373 }
374
375 let ch = &children[self.index];
376 let offset = self.offset;
377 let elem = match ch {
378 GreenTree::Node(n) => RedTree::Node(RedNode::new(n, offset)),
379 GreenTree::Leaf(t) => RedTree::Leaf(RedLeaf { kind: t.kind, span: Range { start: offset, end: offset + t.length as usize } }),
380 };
381
382 self.offset += ch.len() as usize;
383 self.index += 1;
384 Some(elem)
385 }
386}