type_sitter_lib/node/
mod.rs

1use crate::raw;
2#[cfg(feature = "yak-sitter")]
3use crate::PointRange;
4use crate::{InputEdit, Point, Range};
5pub use cursor::*;
6pub use incorrect_kind::*;
7pub use parser::*;
8use std::fmt::Debug;
9use std::hash::Hash;
10#[cfg(not(feature = "yak-sitter"))]
11use std::str::Utf8Error;
12pub use tree::*;
13pub use unwrap_and_flatten_multi::*;
14pub use wrappers::*;
15
16mod cursor;
17/// Errors when a node has the wrong kind so it can't be wrapped
18mod incorrect_kind;
19mod parser;
20mod tree;
21/// Unwrapping multiple `Try`-types at once
22mod unwrap_and_flatten_multi;
23/// Extra, missing, untyped nodes
24mod wrappers;
25
26/// Typed node wrapper.
27///
28/// This implements `TryFrom<tree_sitter::Node<'tree>>`, which will succeed iff the node is of the correct type.
29/// That is how you convert untyped nodes into types nodes. If you're absolutely sure the node is
30/// correct, you may also use [`Node::from_raw_unchecked`], though it's honestly probably not
31/// worth the possible performance gain.
32///
33/// You can get extra nodes (e.g. comments) that are before and after this node with [`prefixes`](
34/// Self::prefixes) and [`suffixes`](Self::suffixes).
35pub trait Node<'tree>: Debug + Clone + Copy + PartialEq + Eq + Hash {
36    /// The same type, but with a different lifetime.
37    type WithLifetime<'a>: Node<'a>;
38
39    /// Kind of nodes this wraps.
40    ///
41    /// For nodes that map directly to tree-sitter nodes, this is the tree-sitter node's name. For
42    /// nodes like unions, [`UntypedNode`], or [`NodeResult`]s, which don't have a simple kind
43    /// (especially static), this is `{...}`.
44    const KIND: &'static str;
45
46    /// Check that the tree-sitter node is the correct kind, and if it is, wrap.
47    ///
48    /// Returns `Err` if the node is not of the correct kind.
49    fn try_from_raw(node: raw::Node<'tree>) -> NodeResult<'tree, Self>;
50
51    /// Assume that tree-sitter node is the correct kind and wrap.
52    ///
53    /// # Safety
54    /// The node must be of the correct kind.
55    #[inline]
56    unsafe fn from_raw_unchecked(node: raw::Node<'tree>) -> Self {
57        Self::try_from_raw(node).expect("from_raw_unchecked failed")
58    }
59
60    /// The wrapped tree-sitter node.
61    ///
62    /// Note that most methods you should call on this struct directly.
63    fn raw(&self) -> &raw::Node<'tree>;
64
65    /// The wrapped tree-sitter node (mutable reference, rarely needed).
66    ///
67    /// Note that most methods you should call on this struct directly.
68    fn raw_mut(&mut self) -> &mut raw::Node<'tree>;
69
70    /// Destruct into the wrapped tree-sitter node.
71    ///
72    /// Note that most methods you should call on this struct directly.
73    fn into_raw(self) -> raw::Node<'tree>;
74
75    /// Upcast into an untyped node.
76    ///
77    /// The inverse is [`UntypedNode::downcast`].
78    #[inline]
79    fn upcast(self) -> UntypedNode<'tree> {
80        UntypedNode::new(self.into_raw())
81    }
82
83    // region [Node] delegate
84    /// See [tree-sitter's `Node::text`](raw::Node::text)
85    #[cfg(feature = "yak-sitter")]
86    fn text(&self) -> &'tree str {
87        self.raw().text()
88    }
89
90    /// See [tree-sitter's `Node::utf8_text`](raw::Node::utf8_text)
91    #[inline]
92    #[cfg(not(feature = "yak-sitter"))]
93    fn utf8_text<'a>(&self, source: &'a [u8]) -> Result<&'a str, Utf8Error> {
94        self.raw().utf8_text(source)
95    }
96
97    /// See [tree-sitter's `Node::utf16_text`](raw::Node::utf16_text)
98    #[inline]
99    #[cfg(not(feature = "yak-sitter"))]
100    fn utf16_text<'a>(&self, source: &'a [u16]) -> &'a [u16] {
101        self.raw().utf16_text(source)
102    }
103
104    /// Returns any [extra](raw::Node::is_extra) nodes before this one, e.g., comments.
105    ///
106    /// Nodes are iterated first to last (by source location).
107    #[inline]
108    fn prefixes(&self) -> impl Iterator<Item = UntypedNode<'tree>> {
109        Prefixes::new(*self.raw())
110    }
111
112    /// Returns any [extra](raw::Node::is_extra) nodes after this one, e.g., comments.
113    ///
114    /// Nodes are iterated first to last (by source location).
115    #[inline]
116    fn suffixes(&self) -> impl Iterator<Item = UntypedNode<'tree>> {
117        Suffixes::new(*self.raw())
118    }
119
120    /// Get a cursor for this node
121    #[inline]
122    fn walk(&self) -> TreeCursor<'tree> {
123        TreeCursor(self.raw().walk())
124    }
125
126    /// Get the node's immediate parent
127    #[inline]
128    fn parent(&self) -> Option<UntypedNode<'tree>> {
129        self.raw().parent().map(UntypedNode::from)
130    }
131
132    /// Get the node's immediate named next sibling
133    #[inline]
134    fn next_named_sibling(&self) -> Option<UntypedNode<'tree>> {
135        self.raw().next_named_sibling().map(UntypedNode::from)
136    }
137
138    /// Get the node's immediate named previous sibling
139    #[inline]
140    fn prev_named_sibling(&self) -> Option<UntypedNode<'tree>> {
141        self.raw().prev_named_sibling().map(UntypedNode::from)
142    }
143
144    /// Get the number of named children
145    #[inline]
146    fn named_child_count(&self) -> usize {
147        self.raw().named_child_count()
148    }
149
150    /// Print the node as an s-expression
151    #[inline]
152    fn to_sexp(&self) -> String {
153        self.raw().to_sexp()
154    }
155
156    /// Get this node's tree-sitter name. See [tree-sitter's `Node::kind`](raw::Node::kind)
157    #[inline]
158    fn kind(&self) -> &'static str {
159        self.raw().kind()
160    }
161
162    /// Check if this node is *named*. See [tree-sitter's `Node::is_named`](raw::Node::is_named)
163    #[inline]
164    fn is_named(&self) -> bool {
165        self.raw().is_named()
166    }
167
168    /// Check if this node has been edited
169    #[inline]
170    fn has_changes(&self) -> bool {
171        self.raw().has_changes()
172    }
173
174    /// Check if this node represents a syntax error or contains any syntax errors anywhere within
175    /// it
176    #[inline]
177    fn has_error(&self) -> bool {
178        self.raw().has_error()
179    }
180
181    /// Get the byte offset where this node starts
182    #[inline]
183    fn start_byte(&self) -> usize {
184        self.raw().start_byte()
185    }
186
187    /// Get the byte offset where this node ends
188    #[inline]
189    fn end_byte(&self) -> usize {
190        self.raw().end_byte()
191    }
192
193    /// Get the row and column where this node starts
194    #[inline]
195    fn start_position(&self) -> Point {
196        self.raw().start_position()
197    }
198
199    /// Get the row and column where this node ends
200    #[inline]
201    fn end_position(&self) -> Point {
202        self.raw().end_position()
203    }
204
205    /// Get the byte range and row and column range where this node is located
206    #[inline]
207    fn range(&self) -> Range {
208        self.raw().range()
209    }
210
211    /// Get the byte range where this node is located
212    #[inline]
213    fn byte_range(&self) -> std::ops::Range<usize> {
214        self.raw().byte_range()
215    }
216
217    /// Get the row and column range where this node is located
218    #[inline]
219    #[cfg(feature = "yak-sitter")]
220    fn position_range(&self) -> PointRange {
221        self.raw().position_range()
222    }
223
224    /// Edit this node to keep it in-sync with source code that has been edited. See
225    /// [tree-sitter's `Node::edit`](raw::Node::edit)
226    #[inline]
227    fn edit(&mut self, edit: &InputEdit) {
228        self.raw_mut().edit(edit)
229    }
230    // endregion
231}
232
233/// A node that has a single optional named child (besides [extras](tree_sitter::Node::is_extra))
234/// and no fields.
235///
236/// The trait mainly exists for the associated type, because usually these kinds of nodes' child
237/// type is anonymous.
238pub trait HasOptionalChild<'tree>: Node<'tree> {
239    type Child: Node<'tree>;
240
241    /// Gets the node's only not-extra named child, if it exists.
242    #[inline]
243    fn child(&self) -> Option<NodeResult<'tree, Self::Child>> {
244        optional_child(self)
245    }
246}
247
248/// A node that has a single named child (besides [extras](tree_sitter::Node::is_extra)) and no
249/// fields.
250///
251/// The trait mainly exists for the associated type, because usually these kinds of nodes' child
252/// type is anonymous.
253pub trait HasChild<'tree>: Node<'tree> {
254    type Child: Node<'tree>;
255
256    /// Gets the node's only not-extra named child.
257    #[inline]
258    fn child(&self) -> NodeResult<'tree, Self::Child> {
259        optional_child(self).expect(
260            "required child not present, there should at least be a MISSING node in its place",
261        )
262    }
263}
264
265#[inline]
266fn optional_child<'tree, Child: Node<'tree>>(
267    this: &impl Node<'tree>,
268) -> Option<NodeResult<'tree, Child>> {
269    (0..this.raw().named_child_count())
270        .map(|i| this.raw().named_child(i).unwrap())
271        .filter(|n| !n.is_extra())
272        .next()
273        .map(Child::try_from_raw)
274}
275
276/// A node that has multiple named children (besides [extras](tree_sitter::Node::is_extra)) and no
277/// fields.
278///
279/// The trait mainly exists for the associated type, because usually these kinds of nodes' child
280/// type is anonymous.
281pub trait HasChildren<'tree>: Node<'tree> {
282    type Child: Node<'tree>;
283
284    /// Gets the node's not-extra named children.
285    #[inline]
286    fn children<'a>(
287        &self,
288        c: &'a mut TreeCursor<'tree>,
289    ) -> impl Iterator<Item = NodeResult<'tree, Self::Child>> + 'a
290    where
291        Self: 'a,
292    {
293        self.raw()
294            .named_children(&mut c.0)
295            .filter(|n| !n.is_extra())
296            .map(Self::Child::try_from_raw)
297    }
298}
299
300struct Prefixes<'tree> {
301    cursor: raw::TreeCursor<'tree>,
302    end: raw::Node<'tree>,
303}
304
305struct Suffixes<'tree> {
306    cursor: raw::TreeCursor<'tree>,
307}
308
309impl<'tree> Prefixes<'tree> {
310    fn new(raw: raw::Node<'tree>) -> Self {
311        let Some(parent) = raw.parent() else {
312            return Self {
313                cursor: raw.walk(),
314                end: raw,
315            };
316        };
317
318        let mut cursor = parent.walk();
319        cursor.goto_first_child();
320
321        'outer: loop {
322            if cursor.node() == raw {
323                break Self {
324                    cursor: raw.walk(),
325                    end: raw,
326                };
327            }
328
329            if cursor.node().is_extra() {
330                let mut cursor2 = cursor.clone();
331                while cursor2.node().is_extra() {
332                    if !cursor2.goto_next_sibling() {
333                        break 'outer Self {
334                            cursor: raw.walk(),
335                            end: raw,
336                        };
337                    }
338
339                    if cursor2.node() == raw {
340                        break 'outer Self { cursor, end: raw };
341                    }
342                }
343            }
344
345            if !cursor.goto_next_sibling() {
346                break Self {
347                    cursor: raw.walk(),
348                    end: raw,
349                };
350            }
351        }
352    }
353}
354
355impl<'tree> Suffixes<'tree> {
356    fn new(raw: raw::Node<'tree>) -> Self {
357        let Some(parent) = raw.parent() else {
358            return Self { cursor: raw.walk() };
359        };
360
361        let mut cursor = parent.walk();
362        cursor.goto_first_child();
363
364        while cursor.node() != raw {
365            let next = cursor.goto_next_sibling();
366            assert!(next, "node not found in parent");
367        }
368
369        Self { cursor }
370    }
371}
372
373impl<'tree> Iterator for Prefixes<'tree> {
374    type Item = UntypedNode<'tree>;
375
376    fn next(&mut self) -> Option<Self::Item> {
377        if self.cursor.node() == self.end {
378            return None;
379        }
380
381        let result = UntypedNode::new(self.cursor.node());
382        debug_assert!(
383            self.cursor.node().is_extra(),
384            "node before our iteration target isn't an extra, but we thought it would be"
385        );
386        let next = self.cursor.goto_next_sibling();
387        assert!(
388            next,
389            "node (that we've been iterating the prefixes of) not found in parent"
390        );
391        Some(result)
392    }
393}
394
395impl<'tree> Iterator for Suffixes<'tree> {
396    type Item = UntypedNode<'tree>;
397
398    fn next(&mut self) -> Option<Self::Item> {
399        if !self.cursor.goto_next_sibling() || !self.cursor.node().is_extra() {
400            return None;
401        }
402
403        Some(UntypedNode::new(self.cursor.node()))
404    }
405}