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 pub fn new(root: &'a GreenNode<'a, L>) -> Self {
57 Self::Node(RedNode { green: root, offset: 0 })
58 }
59
60 #[inline]
64 pub fn span(&self) -> Range<usize> {
65 match self {
66 RedTree::Node(n) => n.span(),
67 RedTree::Leaf(t) => t.span,
68 }
69 }
70
71 pub fn kind<T>(&self) -> T
77 where
78 T: From<L::ElementType> + From<L::TokenType>,
79 {
80 match self {
81 RedTree::Node(n) => T::from(n.green.kind),
82 RedTree::Leaf(l) => T::from(l.kind),
83 }
84 }
85
86 pub fn text<'s, S: crate::source::Source + ?Sized>(&self, source: &'s S) -> std::borrow::Cow<'s, str> {
92 source.get_text_in(self.span())
93 }
94
95 pub fn children(&self) -> RedChildren<'a, L> {
99 match self {
100 RedTree::Node(n) => n.children(),
101 RedTree::Leaf(_) => RedChildren::empty(),
102 }
103 }
104
105 pub fn as_node(&self) -> Option<RedNode<'a, L>> {
107 match self {
108 RedTree::Node(n) => Some(*n),
109 RedTree::Leaf(_) => None,
110 }
111 }
112
113 pub fn as_token(&self) -> Option<RedLeaf<L>> {
115 match self {
116 RedTree::Node(_) => None,
117 RedTree::Leaf(l) => Some(*l),
118 }
119 }
120
121 #[deprecated(note = "Use `as_token` instead")]
123 pub fn as_leaf(&self) -> Option<RedLeaf<L>> {
124 self.as_token()
125 }
126}
127
128pub struct RedNode<'a, L: Language> {
139 pub green: &'a GreenNode<'a, L>,
141 pub offset: usize,
143}
144
145impl<'a, L: Language> Clone for RedNode<'a, L> {
147 fn clone(&self) -> Self {
148 *self
149 }
150}
151
152impl<'a, L: Language> Copy for RedNode<'a, L> {}
153
154impl<'a, L: Language> PartialEq for RedNode<'a, L> {
155 fn eq(&self, other: &Self) -> bool {
156 self.green == other.green && self.offset == other.offset
157 }
158}
159
160impl<'a, L: Language> Eq for RedNode<'a, L> {}
161
162impl<'a, L: Language> fmt::Debug for RedNode<'a, L> {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 f.debug_struct("RedNode").field("green", &self.green).field("offset", &self.offset).finish()
165 }
166}
167
168pub struct RedLeaf<L: Language> {
172 pub kind: L::TokenType,
174 pub span: Range<usize>,
176}
177
178impl<L: Language> Clone for RedLeaf<L> {
180 fn clone(&self) -> Self {
181 *self
182 }
183}
184
185impl<L: Language> Copy for RedLeaf<L> {}
186
187impl<L: Language> RedLeaf<L> {
188 #[inline]
190 pub fn kind(&self) -> L::TokenType {
191 self.kind
192 }
193
194 #[inline]
196 pub fn span(&self) -> Range<usize> {
197 self.span.clone()
198 }
199
200 pub fn text<'s, S: crate::source::Source + ?Sized>(&self, source: &'s S) -> std::borrow::Cow<'s, str> {
202 source.get_text_in(self.span())
203 }
204}
205
206impl<L: Language> PartialEq for RedLeaf<L> {
207 fn eq(&self, other: &Self) -> bool {
208 self.kind == other.kind && self.span == other.span
209 }
210}
211
212impl<L: Language> Eq for RedLeaf<L> {}
213
214impl<L: Language> fmt::Debug for RedLeaf<L> {
215 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216 f.debug_struct("RedLeaf").field("kind", &self.kind).field("span", &self.span).finish()
217 }
218}
219
220pub struct RedChildren<'a, L: Language> {
225 node: Option<RedNode<'a, L>>,
227 index: usize,
229 offset: usize,
231}
232
233impl<'a, L: Language> RedChildren<'a, L> {
234 pub fn empty() -> Self {
236 Self { node: None, index: 0, offset: 0 }
237 }
238}
239
240impl<'a, L: Language> RedNode<'a, L> {
241 pub fn text<'s, S: crate::source::Source + ?Sized>(&self, source: &'s S) -> std::borrow::Cow<'s, str> {
243 source.get_text_in(self.span())
244 }
245
246 #[inline]
248 pub fn new(green: &'a GreenNode<'a, L>, offset: usize) -> Self {
249 Self { green, offset }
250 }
251
252 #[inline]
254 pub fn span(&self) -> Range<usize> {
255 Range { start: self.offset, end: self.offset + self.green.text_len() as usize }
256 }
257
258 #[inline]
260 pub fn element_type(&self) -> L::ElementType {
261 self.green.kind
262 }
263
264 #[inline]
266 pub fn green(&self) -> &'a GreenNode<'a, L> {
267 self.green
268 }
269
270 pub fn kind<T>(&self) -> T
272 where
273 T: From<L::ElementType>,
274 {
275 T::from(self.green.kind)
276 }
277
278 pub fn child_at(&self, idx: usize) -> RedTree<'a, L> {
288 let children = self.green.children();
289 let green_child = &children[idx];
290
291 let mut offset = self.offset;
293 for i in 0..idx {
294 offset += children[i].len() as usize
295 }
296
297 match green_child {
298 GreenTree::Node(n) => RedTree::Node(RedNode::new(n, offset)),
299 GreenTree::Leaf(t) => RedTree::Leaf(RedLeaf { kind: t.kind, span: Range { start: offset, end: offset + t.length as usize } }),
300 }
301 }
302
303 pub fn children(&self) -> RedChildren<'a, L> {
305 RedChildren { node: Some(*self), index: 0, offset: self.offset }
306 }
307
308 pub fn child_index_at_offset(&self, offset: usize) -> Option<usize> {
314 if offset < self.offset || offset >= self.offset + self.green.text_len() as usize {
315 return None;
316 }
317
318 let relative_offset = (offset - self.offset) as u32;
319 let mut current_pos = 0;
320
321 for (idx, child) in self.green.children().iter().enumerate() {
322 let len = child.len();
323 if relative_offset < current_pos + len {
324 return Some(idx);
325 }
326 current_pos += len
327 }
328
329 None
330 }
331
332 pub fn child_at_offset(&self, offset: usize) -> Option<RedTree<'a, L>> {
338 self.child_index_at_offset(offset).map(|idx| self.child_at(idx))
339 }
340
341 pub fn leaf_at_offset(&self, offset: usize) -> Option<RedLeaf<L>> {
349 let mut current = *self;
350 loop {
351 match current.child_at_offset(offset)? {
352 RedTree::Node(n) => current = n,
353 RedTree::Leaf(l) => return Some(l),
354 }
355 }
356 }
357
358 pub fn first_token(&self) -> Option<RedLeaf<L>> {
360 for child in self.children() {
361 match child {
362 RedTree::Node(_) => continue,
363 RedTree::Leaf(l) => return Some(l),
364 }
365 }
366 None
367 }
368}
369
370impl<'a, L: Language> Iterator for RedChildren<'a, L> {
371 type Item = RedTree<'a, L>;
372
373 fn next(&mut self) -> Option<Self::Item> {
374 let node = self.node.as_ref()?;
375 let children = node.green.children();
376 if self.index >= children.len() {
377 return None;
378 }
379
380 let ch = &children[self.index];
381 let offset = self.offset;
382 let elem = match ch {
383 GreenTree::Node(n) => RedTree::Node(RedNode::new(n, offset)),
384 GreenTree::Leaf(t) => RedTree::Leaf(RedLeaf { kind: t.kind, span: Range { start: offset, end: offset + t.length as usize } }),
385 };
386
387 self.offset += ch.len() as usize;
388 self.index += 1;
389 Some(elem)
390 }
391}