Skip to main content

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 next (named or unnamed) sibling
133    #[inline]
134    fn next_sibling(&self) -> Option<UntypedNode<'tree>> {
135        self.raw().next_sibling().map(UntypedNode::from)
136    }
137
138    /// Get the node's immediate previous (named or unnamed) sibling
139    #[inline]
140    fn prev_sibling(&self) -> Option<UntypedNode<'tree>> {
141        self.raw().prev_named_sibling().map(UntypedNode::from)
142    }
143
144    /// Get the number of (named and unnamed) children
145    #[inline]
146    fn child_count(&self) -> usize {
147        self.raw().child_count()
148    }
149
150    /// Get the node's immediate next named sibling
151    #[inline]
152    fn next_named_sibling(&self) -> Option<UntypedNode<'tree>> {
153        self.raw().next_named_sibling().map(UntypedNode::from)
154    }
155
156    /// Get the node's immediate previous named sibling
157    #[inline]
158    fn prev_named_sibling(&self) -> Option<UntypedNode<'tree>> {
159        self.raw().prev_named_sibling().map(UntypedNode::from)
160    }
161
162    /// Get the number of named children
163    #[inline]
164    fn named_child_count(&self) -> usize {
165        self.raw().named_child_count()
166    }
167
168    /// Print the node as an s-expression
169    #[inline]
170    fn to_sexp(&self) -> String {
171        self.raw().to_sexp()
172    }
173
174    /// Get this node's tree-sitter name. See [tree-sitter's `Node::kind`](raw::Node::kind)
175    #[inline]
176    fn kind(&self) -> &'static str {
177        self.raw().kind()
178    }
179
180    /// Check if this node is *named*. See [tree-sitter's `Node::is_named`](raw::Node::is_named)
181    #[inline]
182    fn is_named(&self) -> bool {
183        self.raw().is_named()
184    }
185
186    /// Check if this node has been edited
187    #[inline]
188    fn has_changes(&self) -> bool {
189        self.raw().has_changes()
190    }
191
192    /// Check if this node represents a syntax error or contains any syntax errors anywhere within
193    /// it
194    #[inline]
195    fn has_error(&self) -> bool {
196        self.raw().has_error()
197    }
198
199    /// Get the byte offset where this node starts
200    #[inline]
201    fn start_byte(&self) -> usize {
202        self.raw().start_byte()
203    }
204
205    /// Get the byte offset where this node ends
206    #[inline]
207    fn end_byte(&self) -> usize {
208        self.raw().end_byte()
209    }
210
211    /// Get the row and column where this node starts
212    #[inline]
213    fn start_position(&self) -> Point {
214        self.raw().start_position()
215    }
216
217    /// Get the row and column where this node ends
218    #[inline]
219    fn end_position(&self) -> Point {
220        self.raw().end_position()
221    }
222
223    /// Get the byte range and row and column range where this node is located
224    #[inline]
225    fn range(&self) -> Range {
226        self.raw().range()
227    }
228
229    /// Get the byte range where this node is located
230    #[inline]
231    fn byte_range(&self) -> std::ops::Range<usize> {
232        self.raw().byte_range()
233    }
234
235    /// Get the row and column range where this node is located
236    #[inline]
237    #[cfg(feature = "yak-sitter")]
238    fn position_range(&self) -> PointRange {
239        self.raw().position_range()
240    }
241
242    /// Edit this node to keep it in-sync with source code that has been edited. See
243    /// [tree-sitter's `Node::edit`](raw::Node::edit)
244    #[inline]
245    fn edit(&mut self, edit: &InputEdit) {
246        self.raw_mut().edit(edit)
247    }
248    // endregion
249}
250
251/// A node that has a single optional named child (besides [extras](tree_sitter::Node::is_extra))
252/// and no fields.
253///
254/// The trait mainly exists for the associated type, because usually these kinds of nodes' child
255/// type is anonymous.
256pub trait HasOptionalChild<'tree>: Node<'tree> {
257    type Child: Node<'tree>;
258
259    /// Gets the node's only not-extra named child, if it exists.
260    #[inline]
261    fn child(&self) -> Option<NodeResult<'tree, Self::Child>> {
262        optional_child(self)
263    }
264}
265
266/// A node that has a single named child (besides [extras](tree_sitter::Node::is_extra)) and no
267/// fields.
268///
269/// The trait mainly exists for the associated type, because usually these kinds of nodes' child
270/// type is anonymous.
271pub trait HasChild<'tree>: Node<'tree> {
272    type Child: Node<'tree>;
273
274    /// Gets the node's only not-extra named child.
275    #[inline]
276    fn child(&self) -> NodeResult<'tree, Self::Child> {
277        optional_child(self).expect(
278            "required child not present, there should at least be a MISSING node in its place",
279        )
280    }
281}
282
283#[inline]
284fn optional_child<'tree, Child: Node<'tree>>(
285    this: &impl Node<'tree>,
286) -> Option<NodeResult<'tree, Child>> {
287    (0..this.raw().named_child_count())
288        .map(|i| this.raw().named_child(i.try_into().unwrap()).unwrap())
289        .filter(|n| !n.is_extra())
290        .next()
291        .map(Child::try_from_raw)
292}
293
294/// A node that has multiple named children (besides [extras](tree_sitter::Node::is_extra)) and no
295/// fields.
296///
297/// The trait mainly exists for the associated type, because usually these kinds of nodes' child
298/// type is anonymous.
299pub trait HasChildren<'tree>: Node<'tree> {
300    type Child: Node<'tree>;
301
302    /// Gets the node's not-extra named children.
303    #[inline]
304    fn children<'a>(
305        &self,
306        c: &'a mut TreeCursor<'tree>,
307    ) -> impl Iterator<Item = NodeResult<'tree, Self::Child>> + 'a
308    where
309        Self: 'a,
310    {
311        self.raw()
312            .named_children(&mut c.0)
313            .filter(|n| !n.is_extra())
314            .map(Self::Child::try_from_raw)
315    }
316}
317
318struct Prefixes<'tree> {
319    cursor: raw::TreeCursor<'tree>,
320    end: raw::Node<'tree>,
321}
322
323struct Suffixes<'tree> {
324    cursor: raw::TreeCursor<'tree>,
325}
326
327impl<'tree> Prefixes<'tree> {
328    fn new(raw: raw::Node<'tree>) -> Self {
329        let Some(parent) = raw.parent() else {
330            return Self {
331                cursor: raw.walk(),
332                end: raw,
333            };
334        };
335
336        let mut cursor = parent.walk();
337        cursor.goto_first_child();
338
339        'outer: loop {
340            if cursor.node() == raw {
341                break Self {
342                    cursor: raw.walk(),
343                    end: raw,
344                };
345            }
346
347            if cursor.node().is_extra() {
348                let mut cursor2 = cursor.clone();
349                while cursor2.node().is_extra() {
350                    if !cursor2.goto_next_sibling() {
351                        break 'outer Self {
352                            cursor: raw.walk(),
353                            end: raw,
354                        };
355                    }
356
357                    if cursor2.node() == raw {
358                        break 'outer Self { cursor, end: raw };
359                    }
360                }
361            }
362
363            if !cursor.goto_next_sibling() {
364                break Self {
365                    cursor: raw.walk(),
366                    end: raw,
367                };
368            }
369        }
370    }
371}
372
373impl<'tree> Suffixes<'tree> {
374    fn new(raw: raw::Node<'tree>) -> Self {
375        let Some(parent) = raw.parent() else {
376            return Self { cursor: raw.walk() };
377        };
378
379        let mut cursor = parent.walk();
380        cursor.goto_first_child();
381
382        while cursor.node() != raw {
383            let next = cursor.goto_next_sibling();
384            assert!(next, "node not found in parent");
385        }
386
387        Self { cursor }
388    }
389}
390
391impl<'tree> Iterator for Prefixes<'tree> {
392    type Item = UntypedNode<'tree>;
393
394    fn next(&mut self) -> Option<Self::Item> {
395        if self.cursor.node() == self.end {
396            return None;
397        }
398
399        let result = UntypedNode::new(self.cursor.node());
400        debug_assert!(
401            self.cursor.node().is_extra(),
402            "node before our iteration target isn't an extra, but we thought it would be"
403        );
404        let next = self.cursor.goto_next_sibling();
405        assert!(
406            next,
407            "node (that we've been iterating the prefixes of) not found in parent"
408        );
409        Some(result)
410    }
411}
412
413impl<'tree> Iterator for Suffixes<'tree> {
414    type Item = UntypedNode<'tree>;
415
416    fn next(&mut self) -> Option<Self::Item> {
417        if !self.cursor.goto_next_sibling() || !self.cursor.node().is_extra() {
418            return None;
419        }
420
421        Some(UntypedNode::new(self.cursor.node()))
422    }
423}