Skip to main content

yak_sitter/
lib.rs

1use std::cmp::Ordering;
2use std::collections::Bound;
3use std::error::Error;
4use std::fmt::{Debug, Display, Formatter};
5use std::hash::{Hash, Hasher};
6use std::iter::{once, FusedIterator, Once};
7use std::ops::{BitAnd, BitOr, BitOrAssign, RangeBounds};
8#[cfg(unix)]
9use std::os::unix::io::AsRawFd;
10#[cfg(windows)]
11use std::os::windows::io::AsRawHandle;
12use std::path::{Path, PathBuf};
13use std::ptr::NonNull;
14use std::str::Utf8Error;
15use streaming_iterator::StreamingIterator;
16use utf8_error_offset_by::Utf8ErrorOffsetBy;
17
18mod utf8_error_offset_by;
19
20/// A tree that represents the syntactic structure of a source code file.
21///
22/// It stores its text and filepath, and uses and is used by other [`yak_sitter`](crate) wrappers.
23#[derive(Clone, Debug)]
24pub struct Tree {
25    tree: tree_sitter::Tree,
26    byte_text: Vec<u8>,
27    path: Option<PathBuf>,
28}
29
30/// A single node on a syntax [`Tree`].
31///
32/// It can access its text and filepath, and uses and is used by other [`yak_sitter`](crate)
33/// wrappers.
34#[derive(Clone, Copy)]
35pub struct Node<'tree> {
36    node: tree_sitter::Node<'tree>,
37    tree: &'tree Tree,
38}
39
40/// Raw pointer equivalent of [`Node`]
41#[derive(Clone, Copy)]
42pub struct NodePtr {
43    node_data: TsNodePtr,
44    tree: NonNull<Tree>,
45}
46
47/// Taken straight from [`tree_sitter::ffi::TSNode`]. This must maintain the same layout
48#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
49#[repr(C)]
50struct TsNodePtr {
51    context: [u32; 4usize],
52    id: *const (),
53    tree: *const (),
54}
55
56/// Wrapper around `usize` (aka node id)
57#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
58#[repr(transparent)]
59pub struct NodeId(usize);
60
61/// A stateful object for walking a syntax tree efficiently.
62///
63/// Unlike tree-sitter's cursor, it go outside of its "local" node, albeit with degraded
64/// performance.
65#[derive(Clone)]
66pub struct TreeCursor<'tree> {
67    cursor: tree_sitter::TreeCursor<'tree>,
68    tree: &'tree Tree,
69    child_depth: usize,
70}
71
72/// Wrapper around [`tree_sitter::QueryCursor`]
73pub struct QueryCursor {
74    query_cursor: tree_sitter::QueryCursor,
75}
76
77/// Wrapper around [`tree_sitter::QueryMatches`].
78///
79/// [`tree_sitter::QueryMatches`] is NOT a real iterator, it's a [`StreamingIterator`] (see
80///     <https://github.com/tree-sitter/tree-sitter/issues/608>). Therefore this doesn't implement
81///     [`Iterator`].
82pub struct QueryMatches<'query, 'tree> {
83    query_matches: tree_sitter::QueryMatches<'query, 'tree, &'tree Tree, &'tree str>,
84    current_match: Option<QueryMatch<'query, 'tree>>,
85    query: &'query Query,
86    tree: &'tree Tree,
87}
88
89/// Wrapper around [`tree_sitter::QueryMatch`]
90pub struct QueryMatch<'query, 'tree> {
91    query_match: *const tree_sitter::QueryMatch<'query, 'tree>,
92    query: &'query Query,
93    tree: &'tree Tree,
94}
95
96/// Wrapper around [`tree_sitter::QueryCaptures`]
97pub struct QueryCaptures<'query, 'tree> {
98    query_captures: tree_sitter::QueryCaptures<'query, 'tree, &'tree Tree, &'tree str>,
99    query: &'query Query,
100    tree: &'tree Tree,
101}
102
103/// Wrapper around [`tree_sitter::QueryCapture`]
104#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
105pub struct QueryCapture<'query, 'tree> {
106    pub node: Node<'tree>,
107    pub index: usize,
108    pub name: &'query str,
109}
110
111/// Variant of [`std::ops::Range`] that can be copied and displays as `:line:column-:line:column`
112#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
113pub struct PointRange {
114    pub start: Point,
115    pub end: Point,
116}
117
118/// Structurally identical to [`tree_sitter::Point`] but displays as `:line:column`
119#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
120pub struct Point {
121    pub row: usize,
122    pub column: usize,
123}
124
125/// Structurally identical to [`tree_sitter::Range`] (byte and point range) but displays as
126/// `:line:column-:line:column`
127#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
128pub struct Range {
129    pub start_byte: usize,
130    pub end_byte: usize,
131    pub start_point: Point,
132    pub end_point: Point,
133}
134
135/// A stateful object that this is used to produce a Tree based on some source code
136#[repr(transparent)]
137pub struct Parser(tree_sitter::Parser);
138
139/// An opaque object that defines how to parse a particular language.
140///
141/// The code for each Language is generated by the Tree-sitter CLI.
142pub type Language = tree_sitter::Language;
143/// Re-exports [`tree_sitter::LanguageRef`]
144pub type LanguageRef<'a> = tree_sitter::LanguageRef<'a>;
145/// An error that occurred when trying to assign an incompatible [`Language`] to a [`Parser`]
146pub type LanguageError = tree_sitter::LanguageError;
147/// A set of patterns that match nodes in a syntax tree
148pub type Query = tree_sitter::Query;
149/// A key-value pair associated with a particular pattern in a [`Query`]
150pub type QueryProperty = tree_sitter::QueryProperty;
151/// An error that occurred in [`Parser::set_included_ranges`]
152pub type IncludedRangesError = tree_sitter::IncludedRangesError;
153/// A summary of a change to a text document
154pub type InputEdit = tree_sitter::InputEdit;
155
156/// Error from parsing a tree
157#[derive(Debug)]
158pub enum TreeParseError {
159    IO(std::io::Error),
160    ParsingFailed,
161    NotUtf8(Utf8Error),
162}
163
164/// Describes the previous traversal action in a pre-order traversal which iterates nodes with
165/// children both up and down, so we can get the next node in the traversal
166#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
167pub enum TraversalState {
168    Start,
169    Down,
170    Right,
171    Up,
172    End,
173}
174
175/// Iterator over a tree in pre-order traversal which iterates nodes with children both up and down
176#[derive(Clone)]
177pub struct PreorderTraversal<'tree> {
178    cursor: TreeCursor<'tree>,
179    last_state: TraversalState,
180}
181
182/// Iterated node in a traversal (includes field name and last state)
183#[derive(Clone, Copy, Debug)]
184pub struct TraversalItem<'tree> {
185    /// The node
186    pub node: Node<'tree>,
187    /// The node's field name
188    pub field_name: Option<&'static str>,
189    /// Last traversal state to reach this node
190    pub last_state: TraversalState,
191}
192
193impl Parser {
194    /// Create a new parser for the given language. See [`tree_sitter::Parser::set_language`]
195    #[inline]
196    pub fn new(language: &Language) -> Result<Self, LanguageError> {
197        let mut parser = tree_sitter::Parser::new();
198        parser.set_language(language)?;
199        Ok(Self(parser))
200    }
201
202    /// Set the language of the parser. See [`tree_sitter::Parser::set_language`]
203    #[inline]
204    pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> {
205        self.0.set_language(language)
206    }
207
208    /// Set the ranges of text the parser should include when parsing. See
209    /// [`tree_sitter::Parser::set_included_ranges`]
210    #[inline]
211    pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> {
212        let ranges = ranges
213            .iter()
214            .copied()
215            .map(tree_sitter::Range::from)
216            .collect::<Vec<_>>();
217        self.0.set_included_ranges(&ranges)
218    }
219
220    /// Parse a file. See [`tree_sitter::Parser::parse`].
221    ///
222    /// Additionally, file must be valid utf-8 or this will return `Err`. The file's path is used
223    /// for stable node comparison between trees.
224    #[inline]
225    pub fn parse_file(
226        &mut self,
227        path: &Path,
228        old_tree: Option<&Tree>,
229    ) -> Result<Tree, TreeParseError> {
230        let byte_text = std::fs::read(path)?;
231        self.parse_bytes(byte_text, Some(path), old_tree)
232    }
233
234    /// Parse a string. See [`tree_sitter::Parser::parse`].
235    ///
236    /// The path is stored as metadata that can be accessed from nodes. If you don't need this, pass
237    /// `None`.
238    #[inline]
239    pub fn parse_string(
240        &mut self,
241        text: String,
242        path: Option<&Path>,
243        old_tree: Option<&Tree>,
244    ) -> Result<Tree, TreeParseError> {
245        self.parse_bytes(text.into_bytes(), path, old_tree)
246    }
247
248    /// Parse a byte string. See [`tree_sitter::Parser::parse`].
249    ///
250    /// Note that the wrappers expect and assume UTF-8, so this will fail if the text is not valid
251    /// UTF-8.
252    ///
253    /// The path is stored as metadata that can be accessed from nodes. If you don't need this, pass
254    /// `None`.
255    #[inline]
256    pub fn parse_bytes(
257        &mut self,
258        byte_text: Vec<u8>,
259        path: Option<&Path>,
260        old_tree: Option<&Tree>,
261    ) -> Result<Tree, TreeParseError> {
262        let tree = self
263            .0
264            .parse(&byte_text, old_tree.map(|t| &t.tree))
265            .ok_or(TreeParseError::ParsingFailed)?;
266        Ok(Tree::new(tree, byte_text, path.map(|p| p.to_path_buf()))?)
267    }
268}
269
270impl Tree {
271    /// Wrap the tree and its associated text.
272    ///
273    /// Note that the wrappers expect and assume UTF-8, so this returns `Err` if the text is not
274    /// valid UTF-8.
275    #[inline]
276    fn new(
277        tree: tree_sitter::Tree,
278        byte_text: Vec<u8>,
279        path: Option<PathBuf>,
280    ) -> Result<Self, Utf8Error> {
281        Self::validate_utf8(&tree, &byte_text)?;
282        Ok(Self {
283            tree,
284            byte_text,
285            path,
286        })
287    }
288
289    fn validate_utf8(tree: &tree_sitter::Tree, byte_text: &[u8]) -> Result<(), Utf8Error> {
290        let _ = std::str::from_utf8(byte_text)?;
291        let mut cursor = tree.walk();
292        let mut went_up = false;
293        while (!went_up && cursor.goto_first_child()) || cursor.goto_next_sibling() || {
294            went_up = true;
295            cursor.goto_parent()
296        } {
297            let node = cursor.node();
298            let range = node.byte_range();
299            let _ = std::str::from_utf8(&byte_text[range])
300                .map_err(|e| e.offset_by(node.start_byte()))?;
301        }
302        Ok(())
303    }
304
305    /// Get the underlying text. This includes text which isn't in the [`Self::included_ranges`]
306    #[inline]
307    pub fn text(&self) -> &str {
308        // SAFETY: we ran validate_utf8 before constructing so the text is valid UTF-8
309        unsafe { std::str::from_utf8_unchecked(&self.byte_text) }
310    }
311
312    /// Get the path the tree is associated with, if any.
313    ///
314    /// The path may be virtual, it's used for stable node comparison between trees.
315    #[inline]
316    pub fn path(&self) -> Option<&Path> {
317        self.path.as_deref()
318    }
319
320    /// Get the root node.
321    #[inline]
322    pub fn root_node(&self) -> Node<'_> {
323        // SAFETY: The node is from this tree
324        unsafe { Node::new(self.tree.root_node(), self) }
325    }
326
327    /// Create a cursor starting at the root node
328    #[inline]
329    pub fn walk(&self) -> TreeCursor<'_> {
330        TreeCursor::new(self.tree.walk(), self, true)
331    }
332
333    /// Get the included ranges used to parse the tree
334    #[inline]
335    pub fn included_ranges(&self) -> Vec<Range> {
336        self.tree
337            .included_ranges()
338            .into_iter()
339            .map(Range::from)
340            .collect()
341    }
342
343    /// Get the changed ranges. See [`tree_sitter::Tree::changed_ranges`]
344    #[inline]
345    pub fn changed_ranges(&self, other: &Tree) -> impl ExactSizeIterator<Item = Range> {
346        self.tree.changed_ranges(&other.tree).map(Range::from)
347    }
348
349    /// Get the language used to parse the tree.
350    #[inline]
351    pub fn language(&self) -> LanguageRef<'_> {
352        self.tree.language()
353    }
354
355    //noinspection RsIncorrectFunctionArgumentCount - IntelliJ inspection bug.
356    /// Print a dot graph of the tree to the given file. See [`tree_sitter::Tree::print_dot_graph`]
357    #[inline]
358    pub fn print_dot_graph(
359        &self,
360        #[cfg(unix)] file: &impl AsRawFd,
361        #[cfg(windows)] file: &impl AsRawHandle,
362    ) {
363        self.tree.print_dot_graph(file)
364    }
365
366    /// Edit the tree. See [`tree_sitter::Tree::edit`]
367    #[inline]
368    pub fn edit(&mut self, edit: &InputEdit) {
369        self.tree.edit(edit)
370    }
371}
372
373impl<'tree> tree_sitter::TextProvider<&'tree str> for &'tree Tree {
374    type I = Once<&'tree str>;
375
376    #[inline]
377    fn text(&mut self, node: tree_sitter::Node<'_>) -> Self::I {
378        // SAFETY: we ran validate_utf8 before constructing so every node's text is valid UTF-8
379        once(unsafe { std::str::from_utf8_unchecked(&self.byte_text[node.byte_range()]) })
380    }
381}
382
383impl<'tree> Node<'tree> {
384    /// Wrap a [`tree_sitter::Node`]. Requires its associated [`Tree`] for convenience methods.
385    ///
386    /// # Safety
387    /// The node must be from the given tree.
388    #[inline]
389    pub unsafe fn new(node: tree_sitter::Node<'tree>, tree: &'tree Tree) -> Self {
390        Self { node, tree }
391    }
392
393    /// Gets the node id, which is represented by its address.
394    ///
395    /// Nodes from separate trees are guaranteed to have different ids iff both trees are alive, but
396    /// a node which is no longer alive may have the same id as a different node which is. The
397    /// tree-sitter docs specify that a if a tree is created from an older tree, nodes may be reused
398    /// and from the old tree and these will have the same id.
399    ///
400    /// See [`tree_sitter::Node::id`].
401    #[inline]
402    pub fn id(&self) -> NodeId {
403        NodeId::of_ts(self.node)
404    }
405
406    /// Get the node's kind. See [`tree_sitter::Node::kind`]
407    #[inline]
408    pub fn kind(&self) -> &'static str {
409        self.node.kind()
410    }
411
412    /// Check if the node is named. See [`tree_sitter::Node::is_named`]
413    #[inline]
414    pub fn is_named(&self) -> bool {
415        self.node.is_named()
416    }
417
418    /// Check if the node is missing. See [`tree_sitter::Node::is_missing`]
419    #[inline]
420    pub fn is_missing(&self) -> bool {
421        self.node.is_missing()
422    }
423
424    /// Check if the node is extra. See [`tree_sitter::Node::is_extra`]
425    #[inline]
426    pub fn is_extra(&self) -> bool {
427        self.node.is_extra()
428    }
429
430    /// Check if the node is an error. See [`tree_sitter::Node::is_error`]
431    #[inline]
432    pub fn is_error(&self) -> bool {
433        self.node.is_error()
434    }
435
436    /// Check if the node has an error. See [`tree_sitter::Node::has_error`]
437    #[inline]
438    pub fn has_error(&self) -> bool {
439        self.node.has_error()
440    }
441
442    /// Check if the node has changes. See [`tree_sitter::Node::has_changes`]
443    #[inline]
444    pub fn has_changes(&self) -> bool {
445        self.node.has_changes()
446    }
447
448    /// Edit the node. See [`tree_sitter::Node::edit`]
449    #[inline]
450    pub fn edit(&mut self, edit: &InputEdit) {
451        self.node.edit(edit)
452    }
453
454    /// Get the byte offsets where this node starts
455    #[inline]
456    pub fn start_byte(&self) -> usize {
457        self.node.start_byte()
458    }
459
460    /// Get the byte offsets where this node ends
461    #[inline]
462    pub fn end_byte(&self) -> usize {
463        self.node.end_byte()
464    }
465
466    /// Get the row and column where this node starts
467    #[inline]
468    pub fn start_position(&self) -> Point {
469        Point::from(self.node.start_position())
470    }
471
472    /// Get the row and column where this node ends
473    #[inline]
474    pub fn end_position(&self) -> Point {
475        Point::from(self.node.end_position())
476    }
477
478    /// Get the byte range where this node is located
479    #[inline]
480    pub fn byte_range(&self) -> std::ops::Range<usize> {
481        self.node.byte_range()
482    }
483
484    /// Get the row and column range where this node is located
485    #[inline]
486    pub fn position_range(&self) -> PointRange {
487        PointRange {
488            start: self.start_position(),
489            end: self.end_position(),
490        }
491    }
492
493    /// Get the byte range and row and column range where this node is located
494    #[inline]
495    pub fn range(&self) -> Range {
496        Range::from(self.node.range())
497    }
498
499    /// Get the node's text as a byte string.
500    ///
501    /// **Warning:** the return value is unspecified if the tree is edited.
502    #[inline]
503    fn byte_text(&self) -> &'tree [u8] {
504        &self.tree.byte_text[self.byte_range()]
505    }
506
507    /// Get the node's text.
508    ///
509    /// **Warning:** the return value is unspecified if the tree is edited.
510    #[inline]
511    pub fn text(&self) -> &'tree str {
512        // SAFETY: we ran validate_utf8 before constructing so every node's text is valid UTF-8
513        unsafe { std::str::from_utf8_unchecked(self.byte_text()) }
514    }
515
516    /// Path of the node's tree.
517    ///
518    /// This is the virtual path set on the tree's creation, used primarily for consistent ordering.
519    #[inline]
520    pub fn path(&self) -> Option<&'tree Path> {
521        self.tree.path()
522    }
523
524    /// Get the node's named and unnamed children. See [`tree_sitter::Node::children`]
525    #[inline]
526    pub fn all_children<'a>(
527        &self,
528        cursor: &'a mut TreeCursor<'tree>,
529    ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'a {
530        let tree = self.tree;
531        // SAFETY: Same tree
532        self.node
533            .children(&mut cursor.cursor)
534            .map(move |node| unsafe { Node::new(node, tree) })
535    }
536
537    /// Get the node's named children. See [`tree_sitter::Node::named_children`]
538    #[inline]
539    pub fn named_children<'a>(
540        &self,
541        cursor: &'a mut TreeCursor<'tree>,
542    ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'a {
543        let tree = self.tree;
544        // SAFETY: Same tree
545        self.node
546            .named_children(&mut cursor.cursor)
547            .map(move |node| unsafe { Node::new(node, tree) })
548    }
549
550    /// Get the number of (named and unnamed) children
551    #[inline]
552    pub fn child_count(&self) -> usize {
553        self.node.child_count()
554    }
555
556    /// Get the number of named children
557    #[inline]
558    pub fn named_child_count(&self) -> usize {
559        self.node.named_child_count()
560    }
561
562    /// Get the node's immediate parent
563    #[inline]
564    pub fn parent(&self) -> Option<Node<'tree>> {
565        // SAFETY: Same tree
566        self.node
567            .parent()
568            .map(|node| unsafe { Node::new(node, self.tree) })
569    }
570
571    /// Get the node's immediate next (named or unnamed) sibling
572    #[inline]
573    pub fn next_sibling(&self) -> Option<Node<'tree>> {
574        // SAFETY: Same tree
575        self.node
576            .next_sibling()
577            .map(|node| unsafe { Node::new(node, self.tree) })
578    }
579
580    /// Get the node's immediate next named sibling
581    #[inline]
582    pub fn next_named_sibling(&self) -> Option<Node<'tree>> {
583        // SAFETY: Same tree
584        self.node
585            .next_named_sibling()
586            .map(|node| unsafe { Node::new(node, self.tree) })
587    }
588
589    /// Get the node's immediate previous (named or unnamed) sibling
590    #[inline]
591    pub fn prev_sibling(&self) -> Option<Node<'tree>> {
592        // SAFETY: Same tree
593        self.node
594            .prev_sibling()
595            .map(|node| unsafe { Node::new(node, self.tree) })
596    }
597
598    /// Get the node's immediate previous named sibling
599    #[inline]
600    pub fn prev_named_sibling(&self) -> Option<Node<'tree>> {
601        // SAFETY: Same tree
602        self.node
603            .prev_named_sibling()
604            .map(|node| unsafe { Node::new(node, self.tree) })
605    }
606
607    /// Get the node's (named or unnamed) child at the given index. See [`tree_sitter::Node::child`]
608    #[inline]
609    pub fn child(&self, i: usize) -> Option<Node<'tree>> {
610        // SAFETY: Same tree
611        self.node
612            .child(u32::try_from(i).ok()?)
613            .map(|node| unsafe { Node::new(node, self.tree) })
614    }
615
616    /// Get the node's named child at the given index. See [`tree_sitter::Node::named_child`]
617    #[inline]
618    pub fn named_child(&self, i: usize) -> Option<Node<'tree>> {
619        // SAFETY: Same tree
620        self.node
621            .named_child(i.try_into().ok()?)
622            .map(|node| unsafe { Node::new(node, self.tree) })
623    }
624
625    /// Get the node's last (named or unnamed) child
626    #[inline]
627    pub fn last_child(&self) -> Option<Node<'tree>> {
628        // .child is already bounds-checked so we use wrapping_sub for iff the count is 0
629        self.child(self.child_count().wrapping_sub(1))
630    }
631
632    /// Get the node's last named child
633    #[inline]
634    pub fn last_named_child(&self) -> Option<Node<'tree>> {
635        // .named_child is already bounds-checked so we use wrapping_sub for iff the count is 0
636        self.named_child(self.named_child_count().wrapping_sub(1))
637    }
638
639    /// Get the node's first child of the given kind, named or unnamed.
640    ///
641    /// The cursor is used to iterate the node's immediate children in order to find said child.
642    #[inline]
643    pub fn child_of_kind(&self, kind: &str, cursor: &mut TreeCursor<'tree>) -> Option<Node<'tree>> {
644        // SAFETY: Same tree
645        self.node
646            .named_children(&mut cursor.cursor)
647            .find(|node| node.kind() == kind)
648            .map(|node| unsafe { Node::new(node, self.tree) })
649    }
650
651    /// Get the node's children of the given kind, named or unnamed.
652    ///
653    /// The cursor is used to iterate the node's immediate children in order to find said child.
654    #[inline]
655    pub fn children_of_kind<'a>(
656        &self,
657        kind: &'a str,
658        cursor: &'a mut TreeCursor<'tree>,
659    ) -> impl Iterator<Item = Node<'tree>> + 'a {
660        // SAFETY: Same tree
661        self.node
662            .named_children(&mut cursor.cursor)
663            .filter(move |node| node.kind() == kind)
664            .map(|node| unsafe { Node::new(node, self.tree) })
665    }
666
667    /// Get the first child with the given field name
668    #[inline]
669    pub fn child_by_field_name(&self, field_name: &str) -> Option<Node<'tree>> {
670        // SAFETY: Same tree
671        self.node
672            .child_by_field_name(field_name)
673            .map(|node| unsafe { Node::new(node, self.tree) })
674    }
675
676    /// Get the node's children with the given field name
677    #[inline]
678    pub fn children_by_field_name<'a>(
679        &self,
680        field_name: &str,
681        c: &'a mut TreeCursor<'tree>,
682    ) -> impl Iterator<Item = Node<'tree>> + 'a {
683        // SAFETY: Same tree
684        self.node
685            .children_by_field_name(field_name, &mut c.cursor)
686            .map(|node| unsafe { Node::new(node, self.tree) })
687    }
688
689    /// Get the field name of the child at the given index
690    #[inline]
691    pub fn field_name_for_child(&self, i: usize) -> Option<&'static str> {
692        self.node.field_name_for_child(i as u32)
693    }
694
695    /// Get the field name of the named child at the given index
696    #[inline]
697    pub fn field_name_for_named_child(&self, i: usize) -> Option<&'static str> {
698        self.node.field_name_for_named_child(i as u32)
699    }
700
701    /// Get the node's field name.
702    ///
703    /// This is done by looking at the parent's children and finding the one that matches this node,
704    /// then returning its field name, hence the need for a cursor.
705    pub fn field_name(&self, cursor: &mut TreeCursor<'tree>) -> Option<&'static str> {
706        self.parent().and_then(|parent| {
707            let i = parent
708                .all_children(cursor)
709                .position(|x| x == *self)
710                .expect("node not one of its parent's children");
711            parent.field_name_for_child(i)
712        })
713    }
714
715    /// Get a [`TreeCursor`] that points to this node.
716    ///
717    /// Unlike tree-sitter's cursors, this one can also reach its siblings and parents, albeit with
718    /// degraded performance.
719    #[inline]
720    pub fn walk(&self) -> TreeCursor<'tree> {
721        TreeCursor::new(self.node.walk(), self.tree, false)
722    }
723
724    /// Print the node as an s-expression
725    #[inline]
726    pub fn to_sexp(&self) -> String {
727        self.node.to_sexp()
728    }
729
730    /// Get a raw pointer to this node (remove the `'tree` lifetime)
731    #[inline]
732    pub fn to_ptr(&self) -> NodePtr {
733        NodePtr {
734            node_data: TsNodePtr::from(self.node),
735            tree: NonNull::from(self.tree),
736        }
737    }
738}
739
740impl<'tree> PartialEq for Node<'tree> {
741    #[inline]
742    fn eq(&self, other: &Node<'tree>) -> bool {
743        self.id() == other.id()
744    }
745}
746
747impl<'tree> Eq for Node<'tree> {}
748
749impl<'tree> PartialOrd for Node<'tree> {
750    /// If not equal, compares based on source position, then filepath, then address.
751    #[inline]
752    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
753        Some(self.cmp(other))
754    }
755}
756
757impl<'tree> Ord for Node<'tree> {
758    /// If not equal, compares based on source position, then filepath, then address.
759    fn cmp(&self, other: &Self) -> Ordering {
760        if self.id() == other.id() {
761            Ordering::Equal
762        } else if std::ptr::eq(self.tree as *const _, other.tree as *const _) {
763            self.start_byte()
764                .cmp(&other.start_byte())
765                .then(self.end_byte().cmp(&other.end_byte()))
766        } else {
767            self.path()
768                .cmp(&other.path())
769                .then(self.id().0.cmp(&other.id().0))
770        }
771    }
772}
773
774impl<'tree> Hash for Node<'tree> {
775    #[inline]
776    fn hash<H: Hasher>(&self, state: &mut H) {
777        self.id().hash(state)
778    }
779}
780
781impl NodePtr {
782    /// Converts this node pointer back into a "node", i.e., node reference.
783    ///
784    /// # Safety
785    /// You must ensure that the tree the node came from is alive.
786    #[inline]
787    pub unsafe fn to_node<'a>(self) -> Node<'a> {
788        Node {
789            node: self.node_data.to_node(),
790            tree: self.tree.as_ref(),
791        }
792    }
793}
794
795impl PartialEq for NodePtr {
796    #[inline]
797    fn eq(&self, other: &NodePtr) -> bool {
798        self.node_data == other.node_data
799    }
800}
801
802impl Eq for NodePtr {}
803
804impl Hash for NodePtr {
805    #[inline]
806    fn hash<H: Hasher>(&self, state: &mut H) {
807        self.node_data.hash(state)
808    }
809}
810
811impl TsNodePtr {
812    /// Converts this tree-sitter node pointer back into a tree-sitter "node", i.e., node reference.
813    ///
814    /// # Safety
815    /// You must ensure that the tree the node came from is alive
816    #[inline]
817    pub unsafe fn to_node<'tree>(self) -> tree_sitter::Node<'tree> {
818        // SAFETY: tree_sitter::Node is POD (no Drop, Copy),
819        // and sizes are compile_time checked to be the same
820        std::mem::transmute(self)
821    }
822}
823
824impl<'tree> From<tree_sitter::Node<'tree>> for TsNodePtr {
825    #[inline]
826    fn from(node: tree_sitter::Node) -> Self {
827        // SAFETY: We are storing this as opaquely, tree_sitter::Node is POD (no Drop, Copy),
828        // and sizes are compile_time checked to be the same
829        unsafe { std::mem::transmute::<tree_sitter::Node<'_>, TsNodePtr>(node) }
830    }
831}
832
833impl<'tree> TreeCursor<'tree> {
834    /// Wrap a [`tree-sitter::TreeCursor`].
835    ///
836    /// You must also provide the tree and whether the cursor is at the root node, which are used to
837    /// access parent and siblings on cursors that are not rooted.
838    #[inline]
839    fn new(cursor: tree_sitter::TreeCursor<'tree>, tree: &'tree Tree, is_rooted: bool) -> Self {
840        Self {
841            cursor,
842            tree,
843            child_depth: match is_rooted {
844                false => 0,
845                true => 1,
846            },
847        }
848    }
849
850    /// Gets the cursor's current node
851    #[inline]
852    pub fn node(&self) -> Node<'tree> {
853        // SAFETY: Same tree
854        unsafe { Node::new(self.cursor.node(), self.tree) }
855    }
856
857    /// Gets the field name of the cursor's current node
858    pub fn field_name(&mut self) -> Option<&'static str> {
859        self.cursor.field_name().or_else(|| {
860            if self.child_depth > 0 {
861                None
862            } else {
863                match self.node().parent() {
864                    None => None,
865                    Some(parent) => {
866                        let original_node = self.node();
867                        self.reset(parent);
868                        self.goto_first_child();
869                        while self.node() != original_node {
870                            self.goto_next_sibling();
871                        }
872                        self.cursor.field_name()
873                    }
874                }
875            }
876        })
877    }
878
879    /// Re-initialize the cursor to point to the given node
880    #[inline]
881    pub fn reset(&mut self, node: Node<'tree>) {
882        if self.cursor.node() != node.node {
883            self.cursor.reset(node.node);
884            self.child_depth = if node.tree.root_node() == node { 1 } else { 0 };
885        }
886    }
887
888    /// Move the cursor to the first child of the current node and return `true`, or return `false`
889    /// if the current node has no children
890    #[inline]
891    pub fn goto_first_child(&mut self) -> bool {
892        if self.cursor.goto_first_child() {
893            self.child_depth += 1;
894            true
895        } else {
896            false
897        }
898    }
899
900    /// Move the cursor to the first child of the current node that extends beyond the given byte
901    /// offset, and return its index.
902    ///
903    /// Returns `None` if the current node has no children past that offset.
904    #[inline]
905    pub fn goto_first_child_for_byte(&mut self, index: usize) -> Option<usize> {
906        self.cursor.goto_first_child_for_byte(index).map(|index| {
907            self.child_depth += 1;
908            index
909        })
910    }
911
912    /// Move the cursor to the first child of the current node that extends beyond the given row
913    /// and column, and return its index.
914    ///
915    /// Returns `None` if the current node has no children past that row and column.
916    #[inline]
917    pub fn goto_first_child_for_point(&mut self, point: Point) -> Option<usize> {
918        self.cursor
919            .goto_first_child_for_point(point.into())
920            .map(|index| {
921                self.child_depth += 1;
922                index
923            })
924    }
925
926    /// Move the cursor to the next sibling of the current node and return `true`, or return `false`
927    /// if the current node has no next sibling.
928    ///
929    /// Unlike [`tree_sitter::TreeCursor.goto_next_sibling`], this will try (isn't guaranteed to
930    /// return `false`) if the cursor is rooted (e.g. reset) to its current node.
931    pub fn goto_next_sibling(&mut self) -> bool {
932        self.cursor.goto_next_sibling()
933            || if self.child_depth > 0 {
934                false
935            } else {
936                match self.node().parent() {
937                    None => false,
938                    Some(parent) => {
939                        let original_node = self.node();
940                        self.reset(parent);
941                        self.goto_first_child();
942                        while self.node() != original_node {
943                            self.goto_next_sibling();
944                        }
945                        self.goto_next_sibling()
946                    }
947                }
948            }
949    }
950
951    /// Move the cursor to the parent of the current node and return `true`, or return `false`
952    /// if the current node is a tree root.
953    ///
954    /// Unlike [`tree_sitter::TreeCursor.goto_parent`], this will try (isn't guaranteed to return
955    /// `false`) if the cursor is rooted (e.g. reset) to its current node.
956    pub fn goto_parent(&mut self) -> bool {
957        if self.cursor.goto_parent() {
958            debug_assert!(self.child_depth != 0);
959            self.child_depth -= 1;
960            true
961        } else {
962            if self.child_depth > 0 {
963                false
964            } else {
965                match self.node().parent() {
966                    None => false,
967                    Some(parent) => {
968                        self.reset(parent);
969                        true
970                    }
971                }
972            }
973        }
974    }
975
976    /// Move the cursor to the next node in pre-order traversal order, where nodes with children are
977    /// traversed on both the up and down.
978    ///
979    /// This uses `last_state` to determine where to go next (i.e. up or right/down on a node with
980    /// children), and returns the next state which you would pass to the next `goto_preorder` call
981    /// and so on.
982    pub fn goto_preorder(&mut self, last_state: TraversalState) -> TraversalState {
983        if !last_state.is_up() && self.goto_first_child() {
984            TraversalState::Down
985        } else if self.goto_next_sibling() {
986            TraversalState::Right
987        } else if self.goto_parent() {
988            TraversalState::Up
989        } else {
990            TraversalState::End
991        }
992    }
993}
994
995impl QueryCursor {
996    /// Creates a new cursor. See [`tree_sitter::QueryCursor::new`]
997    #[inline]
998    pub fn new() -> Self {
999        Self {
1000            query_cursor: tree_sitter::QueryCursor::new(),
1001        }
1002    }
1003
1004    /// Iterate over all matches in the order they were found. See
1005    /// [`tree_sitter::QueryCursor::matches`]
1006    #[inline]
1007    pub fn matches<'query, 'cursor: 'query, 'tree>(
1008        &'cursor mut self,
1009        query: &'query Query,
1010        node: Node<'tree>,
1011    ) -> QueryMatches<'query, 'tree> {
1012        QueryMatches {
1013            query_matches: self.query_cursor.matches(&query, node.node, node.tree),
1014            current_match: None,
1015            tree: node.tree,
1016            query,
1017        }
1018    }
1019
1020    /// Iterate over all captures in the order they appear. See
1021    /// [`tree_sitter::QueryCursor::captures`]
1022    #[inline]
1023    pub fn captures<'query, 'cursor: 'query, 'tree>(
1024        &'cursor mut self,
1025        query: &'query Query,
1026        node: Node<'tree>,
1027    ) -> QueryCaptures<'query, 'tree> {
1028        QueryCaptures {
1029            query_captures: self.query_cursor.captures(query, node.node, node.tree),
1030            tree: node.tree,
1031            query,
1032        }
1033    }
1034
1035    /// Set the maximum number of in-progress matches for this cursor
1036    #[inline]
1037    pub fn set_match_limit(&mut self, limit: u16) {
1038        self.query_cursor.set_match_limit(limit as u32);
1039    }
1040
1041    /// Get the maximum number of in-progress matches for this cursor
1042    #[inline]
1043    pub fn match_limit(&self) -> u16 {
1044        self.query_cursor.match_limit() as u16
1045    }
1046
1047    /// Check if, on its last execution, this cursor exceeded its maximum number of in-progress
1048    /// matches
1049    #[inline]
1050    pub fn did_exceed_match_limit(&self) -> bool {
1051        self.query_cursor.did_exceed_match_limit()
1052    }
1053
1054    /// Set the range in which to search for matches, in terms of byte offsets.
1055    ///
1056    /// Like [`tree_sitter::QueryCursor::set_byte_range`], returns `self` for convenience (builder
1057    /// pattern).
1058    #[inline]
1059    pub fn set_byte_range(&mut self, range: std::ops::Range<usize>) -> &mut Self {
1060        self.query_cursor.set_byte_range(range);
1061        self
1062    }
1063
1064    /// Set the range in which to search for matches, in terms of rows and columns.
1065    ///
1066    /// Like [`tree_sitter::QueryCursor::set_point_range`], returns `self` for convenience (builder
1067    /// pattern).
1068    #[inline]
1069    pub fn set_point_range(&mut self, range: PointRange) -> &mut Self {
1070        self.query_cursor.set_point_range(range.to_ts_point_range());
1071        self
1072    }
1073}
1074
1075impl<'query, 'tree> QueryMatches<'query, 'tree> {
1076    /// Get the query that the matches are from
1077    #[inline]
1078    pub fn query(&self) -> &'query Query {
1079        self.query
1080    }
1081
1082    /// Get the tree that the matches are from
1083    #[inline]
1084    pub fn tree(&self) -> &'tree Tree {
1085        self.tree
1086    }
1087
1088    /// Limit captures to a byte range
1089    #[inline]
1090    pub fn set_byte_range(&mut self, range: std::ops::Range<usize>) {
1091        self.query_matches.set_byte_range(range);
1092    }
1093
1094    /// Limit captures to a point range
1095    #[inline]
1096    pub fn set_point_range(&mut self, range: PointRange) {
1097        self.query_matches
1098            .set_point_range(range.to_ts_point_range());
1099    }
1100
1101    /// Get the underlying [`tree_sitter::QueryMatches`]
1102    #[inline]
1103    pub fn as_inner(&self) -> &tree_sitter::QueryMatches<'query, 'tree, &'tree Tree, &'tree str> {
1104        &self.query_matches
1105    }
1106
1107    /// Get the underlying [`tree_sitter::QueryMatches`] (mutable)
1108    #[inline]
1109    pub fn as_inner_mut(
1110        &mut self,
1111    ) -> &mut tree_sitter::QueryMatches<'query, 'tree, &'tree Tree, &'tree str> {
1112        &mut self.query_matches
1113    }
1114
1115    /// Destruct into the underlying [`tree_sitter::QueryMatches`], as well as the query and tree
1116    #[inline]
1117    pub fn into_inner(
1118        self,
1119    ) -> (
1120        tree_sitter::QueryMatches<'query, 'tree, &'tree Tree, &'tree str>,
1121        &'query Query,
1122        &'tree Tree,
1123    ) {
1124        (self.query_matches, self.query, self.tree)
1125    }
1126}
1127
1128impl<'query, 'tree: 'query> StreamingIterator for QueryMatches<'query, 'tree> {
1129    type Item = QueryMatch<'query, 'tree>;
1130
1131    #[inline]
1132    fn advance(&mut self) {
1133        self.query_matches.advance();
1134        self.current_match = self.query_matches.get().map(|query_match| QueryMatch {
1135            query_match: query_match as *const _,
1136            query: self.query,
1137            tree: self.tree,
1138        });
1139    }
1140
1141    #[inline]
1142    fn get(&self) -> Option<&Self::Item> {
1143        self.current_match.as_ref()
1144    }
1145
1146    fn size_hint(&self) -> (usize, Option<usize>) {
1147        self.query_matches.size_hint()
1148    }
1149}
1150
1151impl<'query, 'tree> QueryCaptures<'query, 'tree> {
1152    /// Get the query that the captures are from
1153    #[inline]
1154    pub fn query(&self) -> &'query Query {
1155        self.query
1156    }
1157
1158    /// Get the tree that the captures are from
1159    #[inline]
1160    pub fn tree(&self) -> &'tree Tree {
1161        self.tree
1162    }
1163
1164    /// Limit captures to a byte range
1165    #[inline]
1166    pub fn set_byte_range(&mut self, range: std::ops::Range<usize>) {
1167        self.query_captures.set_byte_range(range);
1168    }
1169
1170    /// Limit captures to a point range
1171    #[inline]
1172    pub fn set_point_range(&mut self, range: PointRange) {
1173        self.query_captures
1174            .set_point_range(range.to_ts_point_range());
1175    }
1176
1177    /// Get the underlying [`tree_sitter::QueryCaptures`]
1178    #[inline]
1179    pub fn as_inner(&self) -> &tree_sitter::QueryCaptures<'query, 'tree, &'tree Tree, &'tree str> {
1180        &self.query_captures
1181    }
1182
1183    /// Get the underlying [`tree_sitter::QueryCaptures`] (mutable)
1184    #[inline]
1185    pub fn as_inner_mut(
1186        &mut self,
1187    ) -> &mut tree_sitter::QueryCaptures<'query, 'tree, &'tree Tree, &'tree str> {
1188        &mut self.query_captures
1189    }
1190
1191    /// Destruct into the underlying [`tree_sitter::QueryCaptures`], as well as query and tree
1192    #[inline]
1193    pub fn into_inner(
1194        self,
1195    ) -> (
1196        tree_sitter::QueryCaptures<'query, 'tree, &'tree Tree, &'tree str>,
1197        &'query Query,
1198        &'tree Tree,
1199    ) {
1200        (self.query_captures, self.query, self.tree)
1201    }
1202}
1203
1204impl<'query, 'tree: 'query> Iterator for QueryCaptures<'query, 'tree> {
1205    type Item = QueryCapture<'query, 'tree>;
1206
1207    #[inline]
1208    fn next(&mut self) -> Option<Self::Item> {
1209        self.query_captures.next().map(|(query_match, index)| {
1210            QueryCapture::new(query_match.captures[*index], self.query, self.tree)
1211        })
1212    }
1213}
1214
1215impl<'query, 'tree> QueryMatch<'query, 'tree> {
1216    /// Wrap a tree-sitter query match.
1217    ///
1218    /// # Safety
1219    /// The query match must be from the given tree and query. Additionally, *`query_match`'s
1220    /// lifetime must be longer than the "lifetime" where any methods may be called on this
1221    /// structure, despite not being captured in the signature* (the structure can outlive
1222    /// `query_match` because it stores a raw pointer, but most of its methods dereference, so when
1223    /// `query_match` is no longer live they cause UB).
1224    #[inline]
1225    pub unsafe fn new(
1226        query_match: &tree_sitter::QueryMatch<'query, 'tree>,
1227        query: &'query Query,
1228        tree: &'tree Tree,
1229    ) -> Self {
1230        Self {
1231            query_match: query_match as *const _,
1232            query,
1233            tree,
1234        }
1235    }
1236
1237    /// Get the query that the match is from
1238    #[inline]
1239    pub fn query(&self) -> &'query Query {
1240        self.query
1241    }
1242
1243    /// Get the tree that the match is from
1244    #[inline]
1245    pub fn tree(&self) -> &'tree Tree {
1246        self.tree
1247    }
1248
1249    /// Iterate all captures in the order they appear.
1250    #[inline]
1251    pub fn iter_captures(&self) -> impl Iterator<Item = QueryCapture<'query, 'tree>> {
1252        self.as_inner()
1253            .captures
1254            .iter()
1255            .map(|&query_capture| QueryCapture::new(query_capture, self.query, self.tree))
1256    }
1257
1258    /// Get the capture at the given index (order it appears).
1259    #[inline]
1260    pub fn capture(&self, index: usize) -> Option<QueryCapture<'query, 'tree>> {
1261        self.as_inner()
1262            .captures
1263            .get(index)
1264            .map(|&query_capture| QueryCapture::new(query_capture, self.query, self.tree))
1265    }
1266
1267    /// Get the first occurrence of the capture with the given name.
1268    #[inline]
1269    pub fn capture_named(&self, name: &str) -> Option<QueryCapture<'query, 'tree>> {
1270        self.iter_captures().find(|capture| capture.name == name)
1271    }
1272
1273    /// Get every occurrence of the captures with the given name.
1274    #[inline]
1275    pub fn captures_named<'a>(
1276        &'a self,
1277        name: &'a str,
1278    ) -> impl Iterator<Item = QueryCapture<'query, 'tree>> + 'a {
1279        self.iter_captures()
1280            .filter(move |capture| capture.name == name)
1281    }
1282
1283    /// Get the number of captures in this match.
1284    #[inline]
1285    pub fn capture_count(&self) -> usize {
1286        self.as_inner().captures.len()
1287    }
1288
1289    /// Get the pattern index of this match.
1290    #[inline]
1291    pub fn pattern_index(&self) -> usize {
1292        self.as_inner().pattern_index
1293    }
1294
1295    /// Get the id of this match  (honestly I don't know what this does because it's not documented)
1296    #[inline]
1297    pub fn id(&self) -> u32 {
1298        self.as_inner().id()
1299    }
1300
1301    /// Remove the match (honestly I don't know what this does because it's not documented)
1302    #[inline]
1303    pub fn remove(&self) {
1304        self.as_inner().remove()
1305    }
1306
1307    /// Get the nodes that were captures by the capture at the given index.
1308    #[inline]
1309    pub fn nodes_for_capture_index(
1310        &self,
1311        capture_index: u32,
1312    ) -> impl Iterator<Item = Node<'tree>> + '_ {
1313        // SAFETY: Same tree
1314        self.as_inner()
1315            .nodes_for_capture_index(capture_index)
1316            .map(move |node| unsafe { Node::new(node, self.tree) })
1317    }
1318
1319    /// Get the underlying [`tree_sitter::QueryMatch`]
1320    #[inline]
1321    pub fn as_inner(&self) -> &tree_sitter::QueryMatch<'query, 'tree> {
1322        // SAFETY: The `unsafe` constructor requires that the pointer is live.
1323        unsafe { &*self.query_match }
1324    }
1325
1326    /// Destruct into the underlying [`tree_sitter::QueryMatch`] raw pointer, as well as the query and
1327    /// tree
1328    #[inline]
1329    pub fn into_inner(
1330        self,
1331    ) -> (
1332        *const tree_sitter::QueryMatch<'query, 'tree>,
1333        &'query Query,
1334        &'tree Tree,
1335    ) {
1336        (self.query_match, self.query, self.tree)
1337    }
1338}
1339
1340impl<'query, 'tree> QueryCapture<'query, 'tree> {
1341    /// Wrap a [`tree_sitter::QueryCapture`]. This also needs the tree and query for helper methods
1342    #[inline]
1343    fn new(
1344        query_capture: tree_sitter::QueryCapture<'tree>,
1345        query: &'query Query,
1346        tree: &'tree Tree,
1347    ) -> Self {
1348        // SAFETY: fn is internal so the provided tree is always the same as the node's tree
1349        unsafe {
1350            Self {
1351                node: Node::new(query_capture.node, tree),
1352                index: query_capture.index as usize,
1353                name: &query.capture_names()[query_capture.index as usize],
1354            }
1355        }
1356    }
1357}
1358
1359impl From<tree_sitter::Point> for Point {
1360    #[inline]
1361    fn from(value: tree_sitter::Point) -> Self {
1362        Self {
1363            row: value.row,
1364            column: value.column,
1365        }
1366    }
1367}
1368
1369impl From<Point> for tree_sitter::Point {
1370    #[inline]
1371    fn from(value: Point) -> Self {
1372        Self {
1373            row: value.row,
1374            column: value.column,
1375        }
1376    }
1377}
1378
1379impl Display for Point {
1380    #[inline]
1381    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1382        write!(f, "{}:{}", self.row + 1, self.column + 1)
1383    }
1384}
1385
1386impl PointRange {
1387    /// Convert this into an [`std::ops::Range`]
1388    #[inline]
1389    pub fn to_ops_range(self) -> std::ops::Range<Point> {
1390        self.start..self.end
1391    }
1392
1393    /// Convert this into an [`std::ops::Range`] of [`tree_sitter::Point`]s
1394    #[inline]
1395    pub fn to_ts_point_range(self) -> std::ops::Range<tree_sitter::Point> {
1396        self.start.into()..self.end.into()
1397    }
1398}
1399
1400impl From<std::ops::Range<Point>> for PointRange {
1401    #[inline]
1402    fn from(value: std::ops::Range<Point>) -> Self {
1403        Self {
1404            start: value.start,
1405            end: value.end,
1406        }
1407    }
1408}
1409
1410impl RangeBounds<Point> for PointRange {
1411    fn start_bound(&self) -> Bound<&Point> {
1412        Bound::Excluded(&self.start)
1413    }
1414
1415    fn end_bound(&self) -> Bound<&Point> {
1416        Bound::Excluded(&self.end)
1417    }
1418}
1419
1420impl Display for PointRange {
1421    #[inline]
1422    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1423        if self.start == self.end {
1424            write!(f, "{}", self.start)
1425        } else if self.start.row == self.end.row {
1426            write!(f, "{}-{}", self.start, self.end.column + 1)
1427        } else {
1428            write!(f, "{}-{}", self.start, self.end)
1429        }
1430    }
1431}
1432
1433impl From<tree_sitter::Range> for Range {
1434    #[inline]
1435    fn from(value: tree_sitter::Range) -> Self {
1436        Self {
1437            start_byte: value.start_byte,
1438            end_byte: value.end_byte,
1439            start_point: Point::from(value.start_point),
1440            end_point: Point::from(value.end_point),
1441        }
1442    }
1443}
1444
1445impl From<Range> for tree_sitter::Range {
1446    #[inline]
1447    fn from(value: Range) -> Self {
1448        Self {
1449            start_byte: value.start_byte,
1450            end_byte: value.end_byte,
1451            start_point: value.start_point.into(),
1452            end_point: value.end_point.into(),
1453        }
1454    }
1455}
1456
1457impl From<Range> for PointRange {
1458    #[inline]
1459    fn from(value: Range) -> Self {
1460        Self {
1461            start: value.start_point,
1462            end: value.end_point,
1463        }
1464    }
1465}
1466
1467impl BitOr for Range {
1468    type Output = Range;
1469
1470    /// Smallest range which contains both ranges
1471    #[inline]
1472    fn bitor(self, rhs: Self) -> Self::Output {
1473        Range {
1474            start_byte: self.start_byte.min(rhs.start_byte),
1475            end_byte: self.end_byte.max(rhs.end_byte),
1476            start_point: self.start_point.min(rhs.start_point),
1477            end_point: self.end_point.max(rhs.end_point),
1478        }
1479    }
1480}
1481
1482impl BitOrAssign for Range {
1483    /// Smallest range which contains both ranges
1484    #[inline]
1485    fn bitor_assign(&mut self, rhs: Self) {
1486        *self = *self | rhs;
1487    }
1488}
1489
1490impl BitAnd for Range {
1491    type Output = Option<Range>;
1492
1493    /// Largest range which both ranges contain if not disjoint, or `None` if they are
1494    #[inline]
1495    fn bitand(self, rhs: Self) -> Self::Output {
1496        let start_byte = self.start_byte.max(rhs.start_byte);
1497        let end_byte = self.end_byte.min(rhs.end_byte);
1498        let start_point = self.start_point.max(rhs.start_point);
1499        let end_point = self.end_point.min(rhs.end_point);
1500
1501        if start_byte <= end_byte && start_point <= end_point {
1502            Some(Range {
1503                start_byte,
1504                end_byte,
1505                start_point,
1506                end_point,
1507            })
1508        } else {
1509            None
1510        }
1511    }
1512}
1513
1514impl Display for Range {
1515    #[inline]
1516    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1517        write!(f, "{}", PointRange::from(*self))
1518    }
1519}
1520
1521impl NodeId {
1522    /// "Magic" node id for an invalid node
1523    pub const INVALID: Self = Self(usize::MAX);
1524
1525    /// Get the id of the given [`tree_sitter::Node`]. See [`tree_sitter::Node::id`]
1526    #[inline]
1527    fn of_ts(node: tree_sitter::Node<'_>) -> Self {
1528        NodeId(node.id())
1529    }
1530}
1531
1532impl From<u64> for NodeId {
1533    #[inline]
1534    fn from(value: u64) -> Self {
1535        NodeId(value as usize)
1536    }
1537}
1538
1539impl Into<u64> for NodeId {
1540    #[inline]
1541    fn into(self) -> u64 {
1542        self.0 as u64
1543    }
1544}
1545
1546impl Display for NodeId {
1547    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1548        write!(f, "#{}", self.0)
1549    }
1550}
1551
1552impl Clone for TreeParseError {
1553    #[inline]
1554    fn clone(&self) -> Self {
1555        match self {
1556            TreeParseError::IO(e) => TreeParseError::IO(std::io::Error::from(e.kind())),
1557            TreeParseError::ParsingFailed => TreeParseError::ParsingFailed,
1558            TreeParseError::NotUtf8(e) => TreeParseError::NotUtf8(*e),
1559        }
1560    }
1561}
1562
1563impl From<std::io::Error> for TreeParseError {
1564    fn from(e: std::io::Error) -> Self {
1565        TreeParseError::IO(e)
1566    }
1567}
1568
1569impl From<Utf8Error> for TreeParseError {
1570    fn from(e: Utf8Error) -> Self {
1571        TreeParseError::NotUtf8(e)
1572    }
1573}
1574
1575impl Display for TreeParseError {
1576    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1577        match self {
1578            TreeParseError::IO(e) => write!(f, "IO error: {}", e),
1579            TreeParseError::ParsingFailed => write!(f, "Parsing failed"),
1580            TreeParseError::NotUtf8(e) => write!(f, "Not UTF-8: {}", e),
1581        }
1582    }
1583}
1584
1585impl Error for TreeParseError {
1586    fn source(&self) -> Option<&(dyn Error + 'static)> {
1587        match self {
1588            TreeParseError::IO(e) => Some(e),
1589            TreeParseError::ParsingFailed => None,
1590            TreeParseError::NotUtf8(e) => Some(e),
1591        }
1592    }
1593}
1594
1595impl TraversalState {
1596    /// Is this the up state?
1597    #[inline]
1598    pub fn is_up(&self) -> bool {
1599        match self {
1600            TraversalState::Up => true,
1601            _ => false,
1602        }
1603    }
1604
1605    /// Is this the final state (done traversing?)
1606    #[inline]
1607    pub fn is_end(&self) -> bool {
1608        match self {
1609            TraversalState::End => true,
1610            _ => false,
1611        }
1612    }
1613}
1614
1615impl<'tree> PreorderTraversal<'tree> {
1616    /// Create a new preorder traversal which will use the given tree-cursor
1617    #[inline]
1618    pub fn with_cursor(cursor: TreeCursor<'tree>) -> Self {
1619        Self {
1620            cursor,
1621            last_state: TraversalState::Start,
1622        }
1623    }
1624
1625    /// Create a new preorder traversal which will traverse the given tree
1626    #[inline]
1627    pub fn of_tree(tree: &'tree Tree) -> Self {
1628        Self::with_cursor(tree.walk())
1629    }
1630
1631    /// Create a new preorder traversal which will traverse the given node
1632    #[inline]
1633    pub fn of_node(node: Node<'tree>) -> Self {
1634        Self::with_cursor(node.walk())
1635    }
1636
1637    /// Get the current item without advancing the traversal
1638    #[inline]
1639    pub fn peek(&mut self) -> TraversalItem<'tree> {
1640        TraversalItem {
1641            node: self.cursor.node(),
1642            field_name: self.cursor.field_name(),
1643            last_state: self.last_state,
1644        }
1645    }
1646
1647    /// Advance the traversal to the next item and return `true`, or return `false` if it's done
1648    #[inline]
1649    pub fn goto_next(&mut self) -> bool {
1650        if self.last_state.is_end() {
1651            false
1652        } else {
1653            self.last_state = self.cursor.goto_preorder(self.last_state);
1654            true
1655        }
1656    }
1657}
1658
1659impl<'tree> Iterator for PreorderTraversal<'tree> {
1660    type Item = TraversalItem<'tree>;
1661
1662    #[inline]
1663    fn next(&mut self) -> Option<TraversalItem<'tree>> {
1664        if self.last_state.is_end() {
1665            return None;
1666        }
1667        let item = self.peek();
1668        self.last_state = self.cursor.goto_preorder(self.last_state);
1669        Some(item)
1670    }
1671}
1672
1673impl<'tree> FusedIterator for PreorderTraversal<'tree> {}
1674
1675// region special "boilerplate" impls
1676impl<'tree> Debug for Node<'tree> {
1677    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1678        write!(f, "{:?}", self.node)
1679    }
1680}
1681
1682impl Debug for NodePtr {
1683    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1684        write!(f, "{:?}", self.node_data)
1685    }
1686}
1687
1688impl<'query, 'tree> Debug for QueryMatch<'query, 'tree> {
1689    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1690        write!(f, "{:?}", self.query_match)
1691    }
1692}
1693// endregion
1694
1695impl<'tree> PartialEq for TraversalItem<'tree> {
1696    fn eq(&self, other: &Self) -> bool {
1697        if self.node == other.node {
1698            debug_assert_eq!(
1699                self.field_name, other.field_name,
1700                "field_name must be the same if node is the same"
1701            );
1702        }
1703        self.node == other.node && self.last_state == other.last_state
1704    }
1705}
1706
1707impl<'tree> Eq for TraversalItem<'tree> {}
1708// endregion