tree_house_bindings/
node.rs

1use std::ffi::{c_char, c_void, CStr};
2use std::fmt;
3use std::marker::PhantomData;
4use std::ops::Range;
5use std::ptr::NonNull;
6
7use crate::tree::Tree;
8use crate::tree_cursor::TreeCursor;
9use crate::Grammar;
10
11#[repr(C)]
12#[derive(Debug, Clone, Copy)]
13pub(super) struct NodeRaw {
14    context: [u32; 4],
15    id: *const c_void,
16    tree: *const c_void,
17}
18
19impl From<Node<'_>> for NodeRaw {
20    fn from(node: Node) -> NodeRaw {
21        NodeRaw {
22            context: node.context,
23            id: node.id.as_ptr(),
24            tree: node.tree.as_ptr(),
25        }
26    }
27}
28
29#[derive(Clone)]
30#[repr(C)]
31pub struct Node<'tree> {
32    context: [u32; 4],
33    id: NonNull<c_void>,
34    tree: NonNull<c_void>,
35    _phantom: PhantomData<&'tree Tree>,
36}
37
38impl fmt::Debug for Node<'_> {
39    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40        let range = self.byte_range();
41        write!(f, "{{Node {} {range:?}}}", self.kind())
42    }
43}
44
45impl<'tree> Node<'tree> {
46    #[inline]
47    pub(super) unsafe fn from_raw(raw: NodeRaw) -> Option<Self> {
48        Some(Node {
49            context: raw.context,
50            id: NonNull::new(raw.id as *mut _)?,
51            tree: unsafe { NonNull::new_unchecked(raw.tree as *mut _) },
52            _phantom: PhantomData,
53        })
54    }
55
56    #[inline]
57    pub(crate) fn as_raw(&self) -> NodeRaw {
58        NodeRaw {
59            context: self.context,
60            id: self.id.as_ptr(),
61            tree: self.tree.as_ptr(),
62        }
63    }
64
65    pub fn id(&self) -> usize {
66        self.id.as_ptr() as usize
67    }
68
69    /// Get this node's type as a string
70    #[inline]
71    pub fn kind(&self) -> &'tree str {
72        unsafe { CStr::from_ptr(ts_node_type(self.as_raw())) }
73            .to_str()
74            .unwrap()
75    }
76
77    /// Get this node's type as a numerical id.
78    #[inline]
79    pub fn kind_id(&self) -> u16 {
80        unsafe { ts_node_symbol(self.as_raw()) }
81    }
82
83    /// Get the [`Grammar`] that was used to parse this node's syntax tree.
84    #[inline]
85    pub fn grammar(&self) -> Grammar {
86        unsafe { ts_node_language(self.as_raw()) }
87    }
88
89    /// Check if this node is *named*.
90    ///
91    /// Named nodes correspond to named rules in the grammar, whereas
92    /// *anonymous* nodes correspond to string literals in the grammar.
93    #[inline]
94    pub fn is_named(&self) -> bool {
95        unsafe { ts_node_is_named(self.as_raw()) }
96    }
97
98    /// Check if this node is *missing*.
99    ///
100    /// Missing nodes are inserted by the parser in order to recover from
101    /// certain kinds of syntax errors.
102    #[inline]
103    pub fn is_missing(&self) -> bool {
104        unsafe { ts_node_is_missing(self.as_raw()) }
105    }
106
107    /// Get the byte offsets where this node starts.
108    #[inline(always)]
109    pub fn start_byte(&self) -> u32 {
110        // Normally we would implement this method like so:
111        //
112        //     extern "C" {
113        //         /// Get the node's start byte.
114        //         fn ts_node_start_byte(self_: NodeRaw) -> u32;
115        //     }
116        //     unsafe { ts_node_start_byte(self.as_raw()) }
117        //
118        // However this method has a trivial implementation which is unlikely to change (though
119        // there is no guarantee) and this method can be called often, in tight loops, on a hot
120        // code path (for example the highlighter's `next_event_offset` method). So we inline the
121        // implementation directly from `node.c` in the C library to minimize overhead:
122        self.context[0]
123    }
124
125    /// Get the byte offsets where this node end.
126    #[inline]
127    pub fn end_byte(&self) -> u32 {
128        unsafe { ts_node_end_byte(self.as_raw()) }
129    }
130
131    /// Get the byte range of source code that this node represents.
132    #[inline]
133    pub fn byte_range(&self) -> Range<u32> {
134        self.start_byte()..self.end_byte()
135    }
136
137    /// Get the node's child at the given index, where zero represents the first
138    /// child.
139    ///
140    /// This method is fairly fast, but its cost is technically log(i), so if
141    /// you might be iterating over a long list of children, you should use
142    /// [`Node::children`] instead.
143    #[inline]
144    pub fn child(&self, i: u32) -> Option<Node<'tree>> {
145        unsafe { Node::from_raw(ts_node_child(self.as_raw(), i)) }
146    }
147
148    /// Get this node's number of children.
149    #[inline]
150    pub fn child_count(&self) -> u32 {
151        unsafe { ts_node_child_count(self.as_raw()) }
152    }
153
154    /// Get this node's *named* child at the given index.
155    ///
156    /// See also [`Node::is_named`].
157    /// This method is fairly fast, but its cost is technically log(i), so if
158    /// you might be iterating over a long list of children, you should use
159    /// `Node::named_children` instead.
160    #[inline]
161    pub fn named_child(&self, i: u32) -> Option<Node<'tree>> {
162        unsafe { Node::from_raw(ts_node_named_child(self.as_raw(), i)) }
163    }
164
165    /// Get this node's number of *named* children.
166    ///
167    /// See also [`Node::is_named`].
168    #[inline]
169    pub fn named_child_count(&self) -> u32 {
170        unsafe { ts_node_named_child_count(self.as_raw()) }
171    }
172
173    #[inline]
174    unsafe fn map(&self, f: unsafe extern "C" fn(NodeRaw) -> NodeRaw) -> Option<Node<'tree>> {
175        Node::from_raw(f(self.as_raw()))
176    }
177
178    /// Get this node's immediate parent.
179    #[inline]
180    pub fn parent(&self) -> Option<Self> {
181        unsafe { self.map(ts_node_parent) }
182    }
183
184    /// Get this node's next sibling.
185    #[inline]
186    pub fn next_sibling(&self) -> Option<Self> {
187        unsafe { self.map(ts_node_next_sibling) }
188    }
189
190    /// Get this node's previous sibling.
191    #[inline]
192    pub fn prev_sibling(&self) -> Option<Self> {
193        unsafe { self.map(ts_node_prev_sibling) }
194    }
195
196    /// Get this node's next named sibling.
197    #[inline]
198    pub fn next_named_sibling(&self) -> Option<Self> {
199        unsafe { self.map(ts_node_next_named_sibling) }
200    }
201
202    /// Get this node's previous named sibling.
203    #[inline]
204    pub fn prev_named_sibling(&self) -> Option<Self> {
205        unsafe { self.map(ts_node_prev_named_sibling) }
206    }
207
208    /// Get the smallest node within this node that spans the given range.
209    #[inline]
210    pub fn descendant_for_byte_range(&self, start: u32, end: u32) -> Option<Self> {
211        unsafe { Self::from_raw(ts_node_descendant_for_byte_range(self.as_raw(), start, end)) }
212    }
213
214    /// Get the smallest named node within this node that spans the given range.
215    #[inline]
216    pub fn named_descendant_for_byte_range(&self, start: u32, end: u32) -> Option<Self> {
217        unsafe {
218            Self::from_raw(ts_node_named_descendant_for_byte_range(
219                self.as_raw(),
220                start,
221                end,
222            ))
223        }
224    }
225
226    /// Iterate over this node's children.
227    ///
228    /// A [`TreeCursor`] is used to retrieve the children efficiently. Obtain
229    /// a [`TreeCursor`] by calling [`Tree::walk`] or [`Node::walk`]. To avoid
230    /// unnecessary allocations, you should reuse the same cursor for
231    /// subsequent calls to this method.
232    ///
233    /// If you're walking the tree recursively, you may want to use the
234    /// [`TreeCursor`] APIs directly instead.
235    pub fn children(&self) -> impl ExactSizeIterator<Item = Node<'tree>> {
236        let mut cursor = TreeCursor::new(self);
237        cursor.goto_first_child();
238        (0..self.child_count()).map(move |_| {
239            let result = cursor.node();
240            cursor.goto_next_sibling();
241            result
242        })
243    }
244
245    pub fn walk(&self) -> TreeCursor<'tree> {
246        TreeCursor::new(self)
247    }
248}
249
250impl PartialEq for Node<'_> {
251    fn eq(&self, other: &Self) -> bool {
252        self.id == other.id
253    }
254}
255
256impl Eq for Node<'_> {}
257
258unsafe impl Send for Node<'_> {}
259unsafe impl Sync for Node<'_> {}
260
261extern "C" {
262    /// Get the node's type as a null-terminated string.
263    fn ts_node_type(node: NodeRaw) -> *const c_char;
264
265    /// Get the node's type as a numerical id.
266    fn ts_node_symbol(node: NodeRaw) -> u16;
267
268    /// Get the node's language.
269    fn ts_node_language(node: NodeRaw) -> Grammar;
270
271    /// Check if the node is *named*. Named nodes correspond to named rules in
272    /// the grammar, whereas *anonymous* nodes correspond to string literals in
273    /// the grammar
274    fn ts_node_is_named(node: NodeRaw) -> bool;
275
276    /// Check if the node is *missing*. Missing nodes are inserted by the parser
277    /// in order to recover from certain kinds of syntax errors
278    fn ts_node_is_missing(node: NodeRaw) -> bool;
279
280    /// Get the node's immediate parent
281    fn ts_node_parent(node: NodeRaw) -> NodeRaw;
282
283    /// Get the node's child at the given index, where zero represents the first
284    /// child
285    fn ts_node_child(node: NodeRaw, child_index: u32) -> NodeRaw;
286
287    /// Get the node's number of children
288    fn ts_node_child_count(node: NodeRaw) -> u32;
289
290    /// Get the node's *named* child at the given index. See also
291    /// [`ts_node_is_named`]
292    fn ts_node_named_child(node: NodeRaw, child_index: u32) -> NodeRaw;
293
294    /// Get the node's number of *named* children. See also [`ts_node_is_named`]
295    fn ts_node_named_child_count(node: NodeRaw) -> u32;
296
297    /// Get the node's next sibling
298    fn ts_node_next_sibling(node: NodeRaw) -> NodeRaw;
299
300    fn ts_node_prev_sibling(node: NodeRaw) -> NodeRaw;
301
302    /// Get the node's next *named* sibling
303    fn ts_node_next_named_sibling(node: NodeRaw) -> NodeRaw;
304
305    fn ts_node_prev_named_sibling(node: NodeRaw) -> NodeRaw;
306
307    /// Get the smallest node within this node that spans the given range of
308    /// bytes or (row, column) positions
309    fn ts_node_descendant_for_byte_range(node: NodeRaw, start: u32, end: u32) -> NodeRaw;
310
311    /// Get the smallest named node within this node that spans the given range
312    /// of bytes or (row, column) positions
313    fn ts_node_named_descendant_for_byte_range(node: NodeRaw, start: u32, end: u32) -> NodeRaw;
314
315    /// Get the node's end byte.
316    fn ts_node_end_byte(node: NodeRaw) -> u32;
317}