Skip to main content

tree_sitter/
lib.rs

1#![cfg_attr(not(any(test, doctest)), doc = include_str!("./README.md"))]
2#![cfg_attr(not(feature = "std"), no_std)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5pub mod ffi;
6mod util;
7
8#[cfg(any(
9    not(feature = "std"),
10    all(target_arch = "wasm32", target_os = "unknown")
11))]
12extern crate alloc;
13#[cfg(not(feature = "std"))]
14use alloc::{boxed::Box, format, string::String, string::ToString, vec::Vec};
15use core::{
16    ffi::{CStr, c_char, c_void},
17    fmt::{self, Write},
18    hash, iter,
19    marker::PhantomData,
20    mem::MaybeUninit,
21    num::NonZeroU16,
22    ops::{self, ControlFlow, Deref},
23    ptr::{self, NonNull},
24    slice, str,
25};
26#[cfg(feature = "std")]
27use std::error;
28#[cfg(all(unix, feature = "std"))]
29use std::os::fd::AsRawFd;
30#[cfg(all(windows, feature = "std"))]
31use std::os::windows::io::AsRawHandle;
32
33pub use streaming_iterator::{StreamingIterator, StreamingIteratorMut};
34use tree_sitter_language::LanguageFn;
35
36#[cfg(feature = "wasm")]
37mod wasm_language;
38#[cfg(feature = "wasm")]
39#[cfg_attr(docsrs, doc(cfg(feature = "wasm")))]
40pub use wasm_language::*;
41
42#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
43mod wasm_allocator;
44
45/// The only ABI version that the current version of the library supports.
46///
47/// The CLI of this fork assigns it to each generated language. Its upper 16
48/// bits (`0x5742`, "WB") tag the fork and its lower 16 bits count the fork's
49/// ABI revisions, so that it never equals an ABI version of upstream
50/// Tree-sitter: the library rejects languages generated by upstream's CLI, and
51/// upstream's library rejects languages generated by this fork's CLI.
52#[doc(alias = "TREE_SITTER_LANGUAGE_VERSION")]
53pub const LANGUAGE_VERSION: usize = ffi::TREE_SITTER_LANGUAGE_VERSION as usize;
54
55/// The earliest ABI version that is supported by the current version of the
56/// library, which is [`LANGUAGE_VERSION`].
57#[doc(alias = "TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION")]
58pub const MIN_COMPATIBLE_LANGUAGE_VERSION: usize =
59    ffi::TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION as usize;
60
61pub const PARSER_HEADER: &str = include_str!("../src/parser.h");
62
63/// An opaque object that defines how to parse a particular language. The code
64/// for each `Language` is generated by the Tree-sitter CLI.
65#[doc(alias = "TSLanguage")]
66#[derive(Debug, PartialEq, Eq, Hash)]
67#[repr(transparent)]
68pub struct Language(*const ffi::TSLanguage);
69
70pub struct LanguageRef<'a>(*const ffi::TSLanguage, PhantomData<&'a ()>);
71
72/// The metadata associated with a language.
73///
74/// Currently, this metadata can be used to check the [Semantic Version](https://semver.org/)
75/// of the language. This version information should be used to signal if a given parser might
76/// be incompatible with existing queries when upgrading between major versions, or minor versions
77/// if it's in zerover.
78#[doc(alias = "TSLanguageMetadata")]
79pub struct LanguageMetadata {
80    pub major_version: u8,
81    pub minor_version: u8,
82    pub patch_version: u8,
83}
84
85impl From<ffi::TSLanguageMetadata> for LanguageMetadata {
86    fn from(val: ffi::TSLanguageMetadata) -> Self {
87        Self {
88            major_version: val.major_version,
89            minor_version: val.minor_version,
90            patch_version: val.patch_version,
91        }
92    }
93}
94
95/// A tree that represents the syntactic structure of a source code file.
96#[doc(alias = "TSTree")]
97pub struct Tree(NonNull<ffi::TSTree>);
98
99/// A position in a multi-line text document, in terms of rows and columns.
100///
101/// Rows and columns are zero-based.
102#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
103pub struct Point {
104    pub row: usize,
105    pub column: usize,
106}
107
108/// A range of positions in a multi-line text document, both in terms of bytes
109/// and of rows and columns.
110#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
111pub struct Range {
112    pub start_byte: usize,
113    pub end_byte: usize,
114    pub start_point: Point,
115    pub end_point: Point,
116}
117
118/// A summary of a change to a text document.
119#[derive(Clone, Copy, Debug, PartialEq, Eq)]
120pub struct InputEdit {
121    pub start_byte: usize,
122    pub old_end_byte: usize,
123    pub new_end_byte: usize,
124    pub start_position: Point,
125    pub old_end_position: Point,
126    pub new_end_position: Point,
127}
128
129impl InputEdit {
130    /// Edit a point to keep it in-sync with source code that has been edited.
131    ///
132    /// This function updates a single point's byte offset and row/column position
133    /// based on this edit operation. This is useful for editing points without
134    /// requiring a tree or node instance.
135    #[doc(alias = "ts_point_edit")]
136    pub fn edit_point(&self, point: &mut Point, byte: &mut usize) {
137        let edit = self.into();
138        let mut ts_point = (*point).into();
139        let mut ts_byte = *byte as u32;
140
141        unsafe {
142            ffi::ts_point_edit(
143                core::ptr::addr_of_mut!(ts_point),
144                core::ptr::addr_of_mut!(ts_byte),
145                &raw const edit,
146            );
147        }
148
149        *point = ts_point.into();
150        *byte = ts_byte as usize;
151    }
152
153    /// Edit a range to keep it in-sync with source code that has been edited.
154    ///
155    /// This function updates a range's start and end positions based on this edit
156    /// operation. This is useful for editing ranges without requiring a tree
157    /// or node instance.
158    #[doc(alias = "ts_range_edit")]
159    pub fn edit_range(&self, range: &mut Range) {
160        let edit = self.into();
161        let mut ts_range = (*range).into();
162
163        unsafe {
164            ffi::ts_range_edit(core::ptr::addr_of_mut!(ts_range), &raw const edit);
165        }
166
167        *range = ts_range.into();
168    }
169}
170
171/// A single node within a syntax [`Tree`].
172#[doc(alias = "TSNode")]
173#[derive(Clone, Copy)]
174#[repr(transparent)]
175pub struct Node<'tree>(ffi::TSNode, PhantomData<&'tree ()>);
176
177/// A stateful object that this is used to produce a [`Tree`] based on some
178/// source code.
179#[doc(alias = "TSParser")]
180pub struct Parser(NonNull<ffi::TSParser>);
181
182/// A stateful object that is used to look up symbols valid in a specific parse
183/// state
184#[doc(alias = "TSLookaheadIterator")]
185pub struct LookaheadIterator(NonNull<ffi::TSLookaheadIterator>);
186struct LookaheadNamesIterator<'a>(&'a mut LookaheadIterator);
187
188/// A stateful object that is passed into a [`ParseProgressCallback`]
189/// to pass in the current state of the parser.
190pub struct ParseState(NonNull<ffi::TSParseState>);
191
192impl ParseState {
193    #[must_use]
194    pub const fn current_byte_offset(&self) -> usize {
195        unsafe { self.0.as_ref() }.current_byte_offset as usize
196    }
197
198    #[must_use]
199    pub const fn has_error(&self) -> bool {
200        unsafe { self.0.as_ref() }.has_error
201    }
202}
203
204/// A stateful object that is passed into a [`QueryProgressCallback`]
205/// to pass in the current state of the query execution.
206pub struct QueryCursorState(NonNull<ffi::TSQueryCursorState>);
207
208impl QueryCursorState {
209    #[must_use]
210    pub const fn current_byte_offset(&self) -> usize {
211        unsafe { self.0.as_ref() }.current_byte_offset as usize
212    }
213}
214
215#[derive(Default)]
216pub struct ParseOptions<'a> {
217    pub progress_callback: Option<ParseProgressCallback<'a>>,
218}
219
220impl<'a> ParseOptions<'a> {
221    #[must_use]
222    pub fn new() -> Self {
223        Self::default()
224    }
225
226    #[must_use]
227    pub fn progress_callback<F: FnMut(&ParseState) -> ControlFlow<()>>(
228        mut self,
229        callback: &'a mut F,
230    ) -> Self {
231        self.progress_callback = Some(callback);
232        self
233    }
234
235    /// Create a new `ParseOptions` with a shorter lifetime, borrowing from this one.
236    ///
237    /// This is useful when you need to reuse parse options multiple times, e.g., calling
238    /// [`Parser::parse_with_options`] multiple times with the same options.
239    #[must_use]
240    pub fn reborrow(&mut self) -> ParseOptions {
241        ParseOptions {
242            progress_callback: match &mut self.progress_callback {
243                Some(cb) => Some(*cb),
244                None => None,
245            },
246        }
247    }
248}
249
250#[derive(Default)]
251pub struct QueryCursorOptions<'a> {
252    pub progress_callback: Option<QueryProgressCallback<'a>>,
253}
254
255impl<'a> QueryCursorOptions<'a> {
256    #[must_use]
257    pub fn new() -> Self {
258        Self::default()
259    }
260
261    #[must_use]
262    pub fn progress_callback<F: FnMut(&QueryCursorState) -> ControlFlow<()>>(
263        mut self,
264        callback: &'a mut F,
265    ) -> Self {
266        self.progress_callback = Some(callback);
267        self
268    }
269
270    /// Create a new `QueryCursorOptions` with a shorter lifetime, borrowing from this one.
271    ///
272    /// This is useful when you need to reuse query cursor options multiple times, e.g., calling
273    /// [`QueryCursor::matches`] multiple times with the same options.
274    #[must_use]
275    pub fn reborrow(&mut self) -> QueryCursorOptions {
276        QueryCursorOptions {
277            progress_callback: match &mut self.progress_callback {
278                Some(cb) => Some(*cb),
279                None => None,
280            },
281        }
282    }
283}
284
285struct QueryCursorOptionsDrop<'options>(
286    *mut ffi::TSQueryCursorOptions,
287    PhantomData<QueryProgressCallback<'options>>,
288);
289
290impl Drop for QueryCursorOptionsDrop<'_> {
291    fn drop(&mut self) {
292        unsafe {
293            if !(*self.0).payload.is_null() {
294                drop(Box::from_raw(
295                    (*self.0).payload.cast::<QueryProgressCallback>(),
296                ));
297            }
298            drop(Box::from_raw(self.0));
299        }
300    }
301}
302
303/// A type of log message.
304#[derive(Debug, PartialEq, Eq)]
305pub enum LogType {
306    Parse,
307    Lex,
308}
309
310type FieldId = NonZeroU16;
311
312/// A callback that receives log messages during parsing.
313type Logger = Box<dyn FnMut(LogType, &str) + Send + 'static>;
314
315/// A callback that receives log messages during parsing, with relaxed constraints.
316type UnsafeLogger<'a> = Box<dyn FnMut(LogType, &str) + Send + 'a>;
317
318/// A callback that receives the parse state during parsing.
319type ParseProgressCallback<'a> = &'a mut dyn FnMut(&ParseState) -> ControlFlow<()>;
320
321/// A callback that receives the query state during query execution.
322type QueryProgressCallback<'a> = &'a mut dyn FnMut(&QueryCursorState) -> ControlFlow<()>;
323
324pub trait Decode {
325    /// A callback that decodes the next code point from the input slice. It should return the code
326    /// point, and how many bytes were decoded.
327    fn decode(bytes: &[u8]) -> (i32, u32);
328}
329
330/// A stateful object for walking a syntax [`Tree`] efficiently.
331#[doc(alias = "TSTreeCursor")]
332pub struct TreeCursor<'tree>(ffi::TSTreeCursor, PhantomData<&'tree ()>);
333
334/// A set of patterns that match nodes in a syntax tree.
335#[doc(alias = "TSQuery")]
336#[derive(Debug)]
337#[expect(
338    clippy::type_complexity,
339    reason = "complex nested types are inherent to the query data model"
340)]
341pub struct Query {
342    ptr: NonNull<ffi::TSQuery>,
343    capture_names: Box<[&'static str]>,
344    capture_quantifiers: Box<[Box<[CaptureQuantifier]>]>,
345    text_predicates: Box<[Box<[TextPredicateCapture]>]>,
346    property_settings: Box<[Box<[QueryProperty]>]>,
347    property_predicates: Box<[Box<[(QueryProperty, bool)]>]>,
348    general_predicates: Box<[Box<[QueryPredicate]>]>,
349}
350
351/// A quantifier for captures
352#[derive(Debug, PartialEq, Eq, Clone, Copy)]
353pub enum CaptureQuantifier {
354    Zero,
355    ZeroOrOne,
356    ZeroOrMore,
357    One,
358    OneOrMore,
359}
360
361impl From<ffi::TSQuantifier> for CaptureQuantifier {
362    fn from(value: ffi::TSQuantifier) -> Self {
363        match value {
364            ffi::TSQuantifierZero => Self::Zero,
365            ffi::TSQuantifierZeroOrOne => Self::ZeroOrOne,
366            ffi::TSQuantifierZeroOrMore => Self::ZeroOrMore,
367            ffi::TSQuantifierOne => Self::One,
368            ffi::TSQuantifierOneOrMore => Self::OneOrMore,
369            _ => unreachable!(),
370        }
371    }
372}
373
374/// A stateful object for executing a [`Query`] on a syntax [`Tree`].
375#[doc(alias = "TSQueryCursor")]
376pub struct QueryCursor {
377    ptr: NonNull<ffi::TSQueryCursor>,
378}
379
380/// A key-value pair associated with a particular pattern in a [`Query`].
381#[derive(Debug, PartialEq, Eq)]
382pub struct QueryProperty {
383    pub key: Box<str>,
384    pub value: Option<Box<str>>,
385    pub capture_id: Option<usize>,
386}
387
388#[derive(Debug, PartialEq, Eq)]
389pub enum QueryPredicateArg {
390    Capture(u32),
391    String(Box<str>),
392}
393
394/// A key-value pair associated with a particular pattern in a [`Query`].
395#[derive(Debug, PartialEq, Eq)]
396pub struct QueryPredicate {
397    pub operator: Box<str>,
398    pub args: Box<[QueryPredicateArg]>,
399}
400
401/// A match of a [`Query`] to a particular set of [`Node`]s.
402pub struct QueryMatch<'cursor, 'tree> {
403    pub pattern_index: usize,
404    captures: &'cursor [QueryCapture<'tree>],
405    id: u32,
406    cursor: *mut ffi::TSQueryCursor,
407}
408
409/// A sequence of [`QueryMatch`]es associated with a given [`QueryCursor`].
410pub struct QueryMatches<'query, 'tree, 'options, T: TextProvider<I>, I: AsRef<[u8]>> {
411    ptr: *mut ffi::TSQueryCursor,
412    query: &'query Query,
413    text_provider: T,
414    buffer1: Vec<u8>,
415    buffer2: Vec<u8>,
416    current_match: Option<QueryMatch<'query, 'tree>>,
417    _options: Option<QueryCursorOptionsDrop<'options>>,
418    _phantom: PhantomData<(&'tree (), I)>,
419}
420
421/// A sequence of [`QueryCapture`]s associated with a given [`QueryCursor`].
422///
423/// During iteration, each element contains a [`QueryMatch`] and index. The index can
424/// be used to access the new capture inside of the [`QueryMatch::captures`]'s [`captures`].
425pub struct QueryCaptures<'query, 'tree, 'options, T: TextProvider<I>, I: AsRef<[u8]>> {
426    ptr: *mut ffi::TSQueryCursor,
427    query: &'query Query,
428    text_provider: T,
429    buffer1: Vec<u8>,
430    buffer2: Vec<u8>,
431    current_match: Option<(QueryMatch<'query, 'tree>, usize)>,
432    _options: Option<QueryCursorOptionsDrop<'options>>,
433    _phantom: PhantomData<(&'tree (), I)>,
434}
435
436pub trait TextProvider<I>
437where
438    I: AsRef<[u8]>,
439{
440    type I: Iterator<Item = I>;
441    fn text(&mut self, node: Node) -> Self::I;
442}
443
444/// A particular [`Node`] that has been captured with a particular name within a
445/// [`Query`].
446#[derive(Clone, Copy, Debug)]
447#[repr(C)]
448pub struct QueryCapture<'tree> {
449    pub node: Node<'tree>,
450    pub index: u32,
451}
452
453/// An error that occurred when trying to assign a [`Language`] to a [`Parser`].
454/// If the `wasm` feature is enabled, this can also indicate a failure to load
455/// the Wasm store.
456#[derive(Debug, PartialEq, Eq)]
457pub enum LanguageError {
458    Version(usize),
459    NotParseable,
460    #[cfg(feature = "wasm")]
461    Wasm,
462}
463
464/// An error that occurred in [`Parser::set_included_ranges`].
465#[derive(Debug, PartialEq, Eq)]
466pub struct IncludedRangesError(pub usize);
467
468/// An error that occurred when trying to create a [`Query`].
469#[derive(Debug, PartialEq, Eq)]
470pub struct QueryError {
471    pub row: usize,
472    pub column: usize,
473    pub offset: usize,
474    pub message: String,
475    pub kind: QueryErrorKind,
476}
477
478#[derive(Debug, PartialEq, Eq)]
479pub enum QueryErrorKind {
480    Syntax,
481    NodeType,
482    Field,
483    Capture,
484    Predicate,
485    Structure,
486    Language,
487}
488
489#[derive(Debug)]
490/// The first item is the capture index
491/// The next is capture specific, depending on what item is expected
492/// The first bool is if the capture is positive
493/// The last item is a bool signifying whether or not it's meant to match
494/// any or all captures
495enum TextPredicateCapture {
496    EqString(u32, Box<str>, bool, bool),
497    EqCapture(u32, u32, bool, bool),
498    MatchString(u32, regex::bytes::Regex, bool, bool),
499    AnyString(u32, Box<[Box<str>]>, bool),
500}
501
502// TODO: Remove this struct at some point. If `core::str::lossy::Utf8Lossy`
503// is ever stabilized.
504pub struct LossyUtf8<'a> {
505    bytes: &'a [u8],
506    in_replacement: bool,
507}
508
509impl Language {
510    #[must_use]
511    pub fn new(builder: LanguageFn) -> Self {
512        Self(unsafe { builder.into_raw()().cast() })
513    }
514
515    /// Check whether this language can be assigned to a parser.
516    ///
517    /// When Tree-sitter is compiled to WebAssembly, languages obtained from a
518    /// syntax tree can be used for parsing only within the same WebAssembly
519    /// instance that created the tree. In other instances, such languages can
520    /// still be used to inspect syntax trees.
521    #[doc(alias = "ts_language_is_parseable")]
522    #[must_use]
523    pub fn is_parseable(&self) -> bool {
524        unsafe { ffi::ts_language_is_parseable(self.0) }
525    }
526
527    /// Get the name of this language. This returns `None` for a language with
528    /// another ABI version.
529    #[doc(alias = "ts_language_name")]
530    #[must_use]
531    pub fn name(&self) -> Option<&str> {
532        let ptr = unsafe { ffi::ts_language_name(self.0) };
533        (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
534    }
535
536    /// Get the ABI version number of this [`Language`].
537    ///
538    /// The library loads only languages whose number is [`LANGUAGE_VERSION`],
539    /// which the CLI of this fork assigns. Any other number comes from a parser
540    /// that another CLI generated.
541    #[doc(alias = "ts_language_abi_version")]
542    #[must_use]
543    pub fn abi_version(&self) -> usize {
544        unsafe { ffi::ts_language_abi_version(self.0) as usize }
545    }
546
547    /// Get the metadata for this language. This information is generated by the
548    /// CLI, and relies on the language author providing the correct metadata in
549    /// the language's `tree-sitter.json` file. This returns `None` for a
550    /// language with another ABI version.
551    ///
552    /// See also [`LanguageMetadata`].
553    #[doc(alias = "ts_language_metadata")]
554    #[must_use]
555    pub fn metadata(&self) -> Option<LanguageMetadata> {
556        unsafe {
557            let ptr = ffi::ts_language_metadata(self.0);
558            (!ptr.is_null()).then(|| (*ptr).into())
559        }
560    }
561
562    /// Get the number of distinct node types in this language.
563    #[doc(alias = "ts_language_symbol_count")]
564    #[must_use]
565    pub fn node_kind_count(&self) -> usize {
566        unsafe { ffi::ts_language_symbol_count(self.0) as usize }
567    }
568
569    /// Get the number of valid states in this language.
570    #[doc(alias = "ts_language_state_count")]
571    #[must_use]
572    pub fn parse_state_count(&self) -> usize {
573        unsafe { ffi::ts_language_state_count(self.0) as usize }
574    }
575
576    /// Get a list of all supertype symbols for the language. The list is empty
577    /// for a language with another ABI version.
578    #[doc(alias = "ts_language_supertypes")]
579    #[must_use]
580    pub fn supertypes(&self) -> &[u16] {
581        let mut length = 0u32;
582        unsafe {
583            let ptr = ffi::ts_language_supertypes(self.0, core::ptr::addr_of_mut!(length));
584            if length == 0 {
585                &[]
586            } else {
587                slice::from_raw_parts(ptr.cast_mut(), length as usize)
588            }
589        }
590    }
591
592    /// Get a list of all subtype symbols for a given supertype symbol. The list
593    /// is empty for a language with another ABI version.
594    #[doc(alias = "ts_language_supertype_map")]
595    #[must_use]
596    pub fn subtypes_for_supertype(&self, supertype: u16) -> &[u16] {
597        unsafe {
598            let mut length = 0u32;
599            let ptr = ffi::ts_language_subtypes(self.0, supertype, core::ptr::addr_of_mut!(length));
600            if length == 0 {
601                &[]
602            } else {
603                slice::from_raw_parts(ptr.cast_mut(), length as usize)
604            }
605        }
606    }
607
608    /// Get the name of the node kind for the given numerical id.
609    #[doc(alias = "ts_language_symbol_name")]
610    #[must_use]
611    pub fn node_kind_for_id(&self, id: u16) -> Option<&str> {
612        let ptr = unsafe { ffi::ts_language_symbol_name(self.0, id) };
613        (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
614    }
615
616    /// Get the numeric id for the given node kind.
617    #[doc(alias = "ts_language_symbol_for_name")]
618    #[must_use]
619    pub fn id_for_node_kind(&self, kind: &str, named: bool) -> u16 {
620        unsafe {
621            ffi::ts_language_symbol_for_name(
622                self.0,
623                kind.as_bytes().as_ptr().cast::<c_char>(),
624                kind.len() as u32,
625                named,
626            )
627        }
628    }
629
630    /// Check whether `id` can be used to index this language's symbol tables.
631    ///
632    /// `ts_symbol_metadata` holds one entry per grammar symbol plus one per alias,
633    /// so [`Self::node_kind_count`] is an exact bound. `ERROR` and `_ERROR` sit
634    /// at the top of the `u16` range and are handled by the C library before any
635    /// table lookup.
636    fn node_kind_id_is_valid(&self, id: u16) -> bool {
637        (id as usize) < self.node_kind_count() || id >= u16::MAX - 1
638    }
639
640    /// Check if the node type for the given numerical id is named (as opposed
641    /// to an anonymous node type).
642    #[must_use]
643    pub fn node_kind_is_named(&self, id: u16) -> bool {
644        self.node_kind_id_is_valid(id)
645            && unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeRegular }
646    }
647
648    /// Check if the node type for the given numerical id is visible (as opposed
649    /// to a hidden node type).
650    #[must_use]
651    pub fn node_kind_is_visible(&self, id: u16) -> bool {
652        self.node_kind_id_is_valid(id)
653            && unsafe { ffi::ts_language_symbol_type(self.0, id) <= ffi::TSSymbolTypeAnonymous }
654    }
655
656    /// Check if the node type for the given numerical id is a supertype.
657    #[must_use]
658    pub fn node_kind_is_supertype(&self, id: u16) -> bool {
659        self.node_kind_id_is_valid(id)
660            && unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeSupertype }
661    }
662
663    /// Get the number of distinct field names in this language.
664    #[doc(alias = "ts_language_field_count")]
665    #[must_use]
666    pub fn field_count(&self) -> usize {
667        unsafe { ffi::ts_language_field_count(self.0) as usize }
668    }
669
670    /// Get the field name for the given numerical id.
671    #[doc(alias = "ts_language_field_name_for_id")]
672    #[must_use]
673    pub fn field_name_for_id(&self, field_id: u16) -> Option<&str> {
674        let ptr = unsafe { ffi::ts_language_field_name_for_id(self.0, field_id) };
675        (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
676    }
677
678    /// Get the numerical id for the given field name.
679    #[doc(alias = "ts_language_field_id_for_name")]
680    #[must_use]
681    pub fn field_id_for_name(&self, field_name: impl AsRef<[u8]>) -> Option<FieldId> {
682        let field_name = field_name.as_ref();
683        let id = unsafe {
684            ffi::ts_language_field_id_for_name(
685                self.0,
686                field_name.as_ptr().cast::<c_char>(),
687                field_name.len() as u32,
688            )
689        };
690        FieldId::new(id)
691    }
692
693    /// Get the next parse state. Combine this with
694    /// [`lookahead_iterator`](Language::lookahead_iterator) to
695    /// generate completion suggestions or valid symbols in error nodes.
696    ///
697    /// Example:
698    /// ```ignore
699    /// let state = language.next_state(node.parse_state(), node.grammar_id());
700    /// ```
701    #[doc(alias = "ts_language_next_state")]
702    #[must_use]
703    pub fn next_state(&self, state: u16, id: u16) -> u16 {
704        unsafe { ffi::ts_language_next_state(self.0, state, id) }
705    }
706
707    /// Create a new lookahead iterator for this language and parse state.
708    ///
709    /// This returns `None` if state is invalid for this language.
710    ///
711    /// Iterating [`LookaheadIterator`] will yield valid symbols in the given
712    /// parse state. A newly created iterator is not positioned on a symbol, so
713    /// [`LookaheadIterator::current_symbol`] returns `None` until the first
714    /// [`Iterator::next`] call.
715    ///
716    /// The iterator retains the language, so the language may be dropped while
717    /// the iterator is still in use.
718    ///
719    /// Lookahead iterators can be useful to generate suggestions and improve
720    /// syntax error diagnostics. To get symbols valid in an `ERROR` node, use the
721    /// lookahead iterator on its first leaf node state. For a missing node, use
722    /// the node's [`parse_state`](Node::parse_state). Keep in mind that lookahead
723    /// symbols are valid in that parse state, but are not necessarily valid
724    /// continuations in the context of the actual following token or guaranteed
725    /// to be considered during error recovery.
726    #[doc(alias = "ts_lookahead_iterator_new")]
727    #[must_use]
728    pub fn lookahead_iterator(&self, state: u16) -> Option<LookaheadIterator> {
729        let ptr = unsafe { ffi::ts_lookahead_iterator_new(self.0, state) };
730        (!ptr.is_null()).then(|| unsafe { LookaheadIterator::from_raw(ptr) })
731    }
732}
733
734impl From<LanguageFn> for Language {
735    fn from(value: LanguageFn) -> Self {
736        Self::new(value)
737    }
738}
739
740impl Clone for Language {
741    fn clone(&self) -> Self {
742        unsafe { Self(ffi::ts_language_copy(self.0)) }
743    }
744}
745
746impl Drop for Language {
747    fn drop(&mut self) {
748        unsafe { ffi::ts_language_delete(self.0) }
749    }
750}
751
752impl Deref for LanguageRef<'_> {
753    type Target = Language;
754
755    fn deref(&self) -> &Self::Target {
756        unsafe { &*(core::ptr::addr_of!(self.0).cast::<Language>()) }
757    }
758}
759
760impl Default for Parser {
761    fn default() -> Self {
762        Self::new()
763    }
764}
765
766impl Parser {
767    /// Create a new parser.
768    #[doc(alias = "ts_parser_new")]
769    #[must_use]
770    pub fn new() -> Self {
771        unsafe {
772            let parser = ffi::ts_parser_new();
773            Self(NonNull::new_unchecked(parser))
774        }
775    }
776
777    /// Set the language that the parser should use for parsing.
778    ///
779    /// Returns a Result indicating whether or not the language was successfully
780    /// assigned. Assignment fails if the language cannot be used for parsing,
781    /// or if it was generated with an incompatible version of the Tree-sitter
782    /// CLI. Check this using [`Language::is_parseable`] and
783    /// [`Language::abi_version`].
784    #[doc(alias = "ts_parser_set_language")]
785    pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> {
786        let version = language.abi_version();
787        if version == LANGUAGE_VERSION {
788            if !language.is_parseable() {
789                return Err(LanguageError::NotParseable);
790            }
791            #[cfg_attr(
792                not(feature = "wasm"),
793                expect(unused_variables, reason = "only used when wasm feature is enabled")
794            )]
795            let success = unsafe { ffi::ts_parser_set_language(self.0.as_ptr(), language.0) };
796            #[cfg(feature = "wasm")]
797            if !success {
798                return Err(LanguageError::Wasm);
799            }
800            Ok(())
801        } else {
802            Err(LanguageError::Version(version))
803        }
804    }
805
806    /// Get the parser's current language.
807    #[doc(alias = "ts_parser_language")]
808    #[must_use]
809    pub fn language(&self) -> Option<LanguageRef<'_>> {
810        let ptr = unsafe { ffi::ts_parser_language(self.0.as_ptr()) };
811        (!ptr.is_null()).then_some(LanguageRef(ptr, PhantomData))
812    }
813
814    /// Get the parser's current logger.
815    #[doc(alias = "ts_parser_logger")]
816    #[must_use]
817    pub fn logger(&self) -> Option<&Logger> {
818        let logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
819        unsafe { logger.payload.cast::<Logger>().as_ref() }
820    }
821
822    /// Set the logging callback that the parser should use during parsing.
823    ///
824    /// To log through a callback that borrows non-`'static` data, see
825    /// [`set_logger_unchecked`](Parser::set_logger_unchecked).
826    #[doc(alias = "ts_parser_set_logger")]
827    pub fn set_logger(&mut self, logger: Option<Logger>) {
828        // SAFETY: `Logger` is `Send + 'static`
829        unsafe { self.set_logger_unchecked(logger) };
830    }
831
832    /// Set the logging callback, allowing the callback to borrow non-`'static`
833    /// data. See [`set_logger`](Parser::set_logger).
834    ///
835    /// # Safety
836    ///
837    /// Any data borrowed by `logger` must remain valid until the logger is
838    /// removed. Equivalently, the parser must not be used to parse once the
839    /// borrowed data has gone out of scope.
840    pub unsafe fn set_logger_unchecked(&mut self, logger: Option<UnsafeLogger<'_>>) {
841        let prev_logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
842        if !prev_logger.payload.is_null() {
843            drop(unsafe { Box::from_raw(prev_logger.payload.cast::<Logger>()) });
844        }
845
846        let c_logger = if let Some(logger) = logger {
847            let container = Box::new(logger);
848
849            unsafe extern "C" fn log(
850                payload: *mut c_void,
851                c_log_type: ffi::TSLogType,
852                c_message: *const c_char,
853            ) {
854                unsafe {
855                    let callback = payload.cast::<Logger>().as_mut().unwrap();
856                    if let Ok(message) = CStr::from_ptr(c_message).to_str() {
857                        let log_type = if c_log_type == ffi::TSLogTypeParse {
858                            LogType::Parse
859                        } else {
860                            LogType::Lex
861                        };
862                        callback(log_type, message);
863                    }
864                }
865            }
866
867            let raw_container = Box::into_raw(container);
868
869            ffi::TSLogger {
870                payload: raw_container.cast::<c_void>(),
871                log: Some(log),
872            }
873        } else {
874            ffi::TSLogger {
875                payload: ptr::null_mut(),
876                log: None,
877            }
878        };
879
880        unsafe { ffi::ts_parser_set_logger(self.0.as_ptr(), c_logger) };
881    }
882
883    /// Set the destination to which the parser should write debugging graphs
884    /// during parsing. The graphs are formatted in the DOT language. You may
885    /// want to pipe these graphs directly to a `dot(1)` process in order to
886    /// generate SVG output.
887    #[doc(alias = "ts_parser_print_dot_graphs")]
888    #[cfg(not(target_os = "wasi"))]
889    #[cfg(feature = "std")]
890    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
891    pub fn print_dot_graphs(
892        &mut self,
893        #[cfg(unix)] file: &impl AsRawFd,
894        #[cfg(windows)] file: &impl AsRawHandle,
895    ) {
896        #[cfg(unix)]
897        {
898            let fd = file.as_raw_fd();
899            unsafe {
900                ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(fd));
901            }
902        }
903
904        #[cfg(windows)]
905        {
906            let handle = file.as_raw_handle();
907            unsafe {
908                ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(handle));
909            }
910        }
911    }
912
913    /// Stop the parser from printing debugging graphs while parsing.
914    #[doc(alias = "ts_parser_print_dot_graphs")]
915    #[cfg(not(target_os = "wasi"))]
916    #[cfg(feature = "std")]
917    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
918    pub fn stop_printing_dot_graphs(&mut self) {
919        unsafe { ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), -1) }
920    }
921
922    /// Parse a slice of UTF8 text.
923    ///
924    /// # Arguments:
925    /// * `text` The UTF8-encoded text to parse.
926    /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the
927    ///   document has changed since `old_tree` was created, then you must edit `old_tree` to match
928    ///   the new text using [`Tree::edit`].
929    ///
930    /// Returns a [`Tree`] if parsing succeeded, or `None` if:
931    ///  * The parser has not yet had a language assigned with [`Parser::set_language`]
932    #[doc(alias = "ts_parser_parse")]
933    pub fn parse(&mut self, text: impl AsRef<[u8]>, old_tree: Option<&Tree>) -> Option<Tree> {
934        let bytes = text.as_ref();
935        let len = bytes.len();
936        self.parse_with_options(
937            &mut |i, _| {
938                if i < len {
939                    &bytes[i..]
940                } else {
941                    Default::default()
942                }
943            },
944            old_tree,
945            None,
946        )
947    }
948
949    /// Parse text provided in chunks by a callback.
950    ///
951    /// # Arguments:
952    /// * `callback` A function that takes a byte offset and position and returns a slice of
953    ///   UTF8-encoded text starting at that byte offset and position. The slices can be of any
954    ///   length. If the given position is at the end of the text, the callback should return an
955    ///   empty slice.
956    /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the
957    ///   document has changed since `old_tree` was created, then you must edit `old_tree` to match
958    ///   the new text using [`Tree::edit`].
959    /// * `options` Options for parsing the text. This can be used to set a progress callback.
960    pub fn parse_with_options<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
961        &mut self,
962        callback: &mut F,
963        old_tree: Option<&Tree>,
964        options: Option<ParseOptions>,
965    ) -> Option<Tree> {
966        type Payload<'a, F, T> = (&'a mut F, Option<T>);
967
968        // This C function is passed to Tree-sitter as the progress callback.
969        unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
970            unsafe {
971                let callback = (*state)
972                    .payload
973                    .cast::<ParseProgressCallback>()
974                    .as_mut()
975                    .unwrap();
976                match callback(&ParseState::from_raw(state)) {
977                    ControlFlow::Continue(()) => false,
978                    ControlFlow::Break(()) => true,
979                }
980            }
981        }
982
983        // This C function is passed to Tree-sitter as the input callback.
984        unsafe extern "C" fn read<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
985            payload: *mut c_void,
986            byte_offset: u32,
987            position: ffi::TSPoint,
988            bytes_read: *mut u32,
989        ) -> *const c_char {
990            unsafe {
991                let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
992                *text = Some(callback(byte_offset as usize, position.into()));
993                let slice = text.as_ref().unwrap().as_ref();
994                *bytes_read = slice.len() as u32;
995                slice.as_ptr().cast::<c_char>()
996            }
997        }
998
999        let empty_options = ffi::TSParseOptions {
1000            payload: ptr::null_mut(),
1001            progress_callback: None,
1002        };
1003
1004        let mut callback_ptr;
1005        let parse_options = if let Some(options) = options {
1006            if let Some(cb) = options.progress_callback {
1007                callback_ptr = cb;
1008                ffi::TSParseOptions {
1009                    payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1010                    progress_callback: Some(progress),
1011                }
1012            } else {
1013                empty_options
1014            }
1015        } else {
1016            empty_options
1017        };
1018
1019        // A pointer to this payload is passed on every call to the `read` C function.
1020        // The payload contains two things:
1021        // 1. A reference to the rust `callback`.
1022        // 2. The text that was returned from the previous call to `callback`. This allows the
1023        //    callback to return owned values like vectors.
1024        let mut payload: Payload<F, T> = (callback, None);
1025
1026        let c_input = ffi::TSInput {
1027            payload: ptr::addr_of_mut!(payload).cast::<c_void>(),
1028            read: Some(read::<T, F>),
1029            encoding: ffi::TSInputEncodingUTF8,
1030            decode: None,
1031        };
1032
1033        let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1034        unsafe {
1035            let c_new_tree = ffi::ts_parser_parse_with_options(
1036                self.0.as_ptr(),
1037                c_old_tree,
1038                c_input,
1039                parse_options,
1040            );
1041
1042            NonNull::new(c_new_tree).map(Tree)
1043        }
1044    }
1045
1046    /// Parse a slice of UTF16 little-endian text.
1047    ///
1048    /// # Arguments:
1049    /// * `text` The UTF16-encoded text to parse.
1050    /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the
1051    ///   document has changed since `old_tree` was created, then you must edit `old_tree` to match
1052    ///   the new text using [`Tree::edit`].
1053    pub fn parse_utf16_le(
1054        &mut self,
1055        input: impl AsRef<[u16]>,
1056        old_tree: Option<&Tree>,
1057    ) -> Option<Tree> {
1058        let code_points = input.as_ref();
1059        let len = code_points.len();
1060        self.parse_utf16_le_with_options(
1061            &mut |i, _| {
1062                if i < len {
1063                    &code_points[i..]
1064                } else {
1065                    Default::default()
1066                }
1067            },
1068            old_tree,
1069            None,
1070        )
1071    }
1072
1073    /// Parse UTF16 little-endian text provided in chunks by a callback.
1074    ///
1075    /// # Arguments:
1076    /// * `callback` A function that takes a code point offset and position and returns a slice of
1077    ///   UTF16-encoded text starting at that byte offset and position. The slices can be of any
1078    ///   length. If the given position is at the end of the text, the callback should return an
1079    ///   empty slice.
1080    /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the
1081    ///   document has changed since `old_tree` was created, then you must edit `old_tree` to match
1082    ///   the new text using [`Tree::edit`].
1083    /// * `options` Options for parsing the text. This can be used to set a progress callback.
1084    pub fn parse_utf16_le_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1085        &mut self,
1086        callback: &mut F,
1087        old_tree: Option<&Tree>,
1088        options: Option<ParseOptions>,
1089    ) -> Option<Tree> {
1090        type Payload<'a, F, T> = (&'a mut F, Option<T>);
1091
1092        unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
1093            unsafe {
1094                let callback = (*state)
1095                    .payload
1096                    .cast::<ParseProgressCallback>()
1097                    .as_mut()
1098                    .unwrap();
1099                match callback(&ParseState::from_raw(state)) {
1100                    ControlFlow::Continue(()) => false,
1101                    ControlFlow::Break(()) => true,
1102                }
1103            }
1104        }
1105
1106        // This C function is passed to Tree-sitter as the input callback.
1107        unsafe extern "C" fn read<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1108            payload: *mut c_void,
1109            byte_offset: u32,
1110            position: ffi::TSPoint,
1111            bytes_read: *mut u32,
1112        ) -> *const c_char {
1113            unsafe {
1114                let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
1115                *text = Some(callback(
1116                    (byte_offset / 2) as usize,
1117                    Point {
1118                        row: position.row as usize,
1119                        column: position.column as usize / 2,
1120                    },
1121                ));
1122                let slice = text.as_ref().unwrap().as_ref();
1123                *bytes_read = slice.len() as u32 * 2;
1124                slice.as_ptr().cast::<c_char>()
1125            }
1126        }
1127
1128        let empty_options = ffi::TSParseOptions {
1129            payload: ptr::null_mut(),
1130            progress_callback: None,
1131        };
1132
1133        let mut callback_ptr;
1134        let parse_options = if let Some(options) = options {
1135            if let Some(cb) = options.progress_callback {
1136                callback_ptr = cb;
1137                ffi::TSParseOptions {
1138                    payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1139                    progress_callback: Some(progress),
1140                }
1141            } else {
1142                empty_options
1143            }
1144        } else {
1145            empty_options
1146        };
1147
1148        // A pointer to this payload is passed on every call to the `read` C function.
1149        // The payload contains two things:
1150        // 1. A reference to the rust `callback`.
1151        // 2. The text that was returned from the previous call to `callback`. This allows the
1152        //    callback to return owned values like vectors.
1153        let mut payload: Payload<F, T> = (callback, None);
1154
1155        let c_input = ffi::TSInput {
1156            payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1157            read: Some(read::<T, F>),
1158            encoding: ffi::TSInputEncodingUTF16LE,
1159            decode: None,
1160        };
1161
1162        let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1163        unsafe {
1164            let c_new_tree = ffi::ts_parser_parse_with_options(
1165                self.0.as_ptr(),
1166                c_old_tree,
1167                c_input,
1168                parse_options,
1169            );
1170
1171            NonNull::new(c_new_tree).map(Tree)
1172        }
1173    }
1174
1175    /// Parse a slice of UTF16 big-endian text.
1176    ///
1177    /// # Arguments:
1178    /// * `text` The UTF16-encoded text to parse.
1179    /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the
1180    ///   document has changed since `old_tree` was created, then you must edit `old_tree` to match
1181    ///   the new text using [`Tree::edit`].
1182    pub fn parse_utf16_be(
1183        &mut self,
1184        input: impl AsRef<[u16]>,
1185        old_tree: Option<&Tree>,
1186    ) -> Option<Tree> {
1187        let code_points = input.as_ref();
1188        let len = code_points.len();
1189        self.parse_utf16_be_with_options(
1190            &mut |i, _| if i < len { &code_points[i..] } else { &[] },
1191            old_tree,
1192            None,
1193        )
1194    }
1195
1196    /// Parse UTF16 big-endian text provided in chunks by a callback.
1197    ///
1198    /// # Arguments:
1199    /// * `callback` A function that takes a code point offset and position and returns a slice of
1200    ///   UTF16-encoded text starting at that byte offset and position. The slices can be of any
1201    ///   length. If the given position is at the end of the text, the callback should return an
1202    ///   empty slice.
1203    /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the
1204    ///   document has changed since `old_tree` was created, then you must edit `old_tree` to match
1205    ///   the new text using [`Tree::edit`].
1206    /// * `options` Options for parsing the text. This can be used to set a progress callback.
1207    pub fn parse_utf16_be_with_options<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1208        &mut self,
1209        callback: &mut F,
1210        old_tree: Option<&Tree>,
1211        options: Option<ParseOptions>,
1212    ) -> Option<Tree> {
1213        type Payload<'a, F, T> = (&'a mut F, Option<T>);
1214
1215        // This C function is passed to Tree-sitter as the progress callback.
1216        unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
1217            unsafe {
1218                let callback = (*state)
1219                    .payload
1220                    .cast::<ParseProgressCallback>()
1221                    .as_mut()
1222                    .unwrap();
1223                match callback(&ParseState::from_raw(state)) {
1224                    ControlFlow::Continue(()) => false,
1225                    ControlFlow::Break(()) => true,
1226                }
1227            }
1228        }
1229
1230        // This C function is passed to Tree-sitter as the input callback.
1231        unsafe extern "C" fn read<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
1232            payload: *mut c_void,
1233            byte_offset: u32,
1234            position: ffi::TSPoint,
1235            bytes_read: *mut u32,
1236        ) -> *const c_char {
1237            unsafe {
1238                let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
1239                *text = Some(callback(
1240                    (byte_offset / 2) as usize,
1241                    Point {
1242                        row: position.row as usize,
1243                        column: position.column as usize / 2,
1244                    },
1245                ));
1246                let slice = text.as_ref().unwrap().as_ref();
1247                *bytes_read = slice.len() as u32 * 2;
1248                slice.as_ptr().cast::<c_char>()
1249            }
1250        }
1251
1252        let empty_options = ffi::TSParseOptions {
1253            payload: ptr::null_mut(),
1254            progress_callback: None,
1255        };
1256
1257        let mut callback_ptr;
1258        let parse_options = if let Some(options) = options {
1259            if let Some(cb) = options.progress_callback {
1260                callback_ptr = cb;
1261                ffi::TSParseOptions {
1262                    payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1263                    progress_callback: Some(progress),
1264                }
1265            } else {
1266                empty_options
1267            }
1268        } else {
1269            empty_options
1270        };
1271
1272        // A pointer to this payload is passed on every call to the `read` C function.
1273        // The payload contains two things:
1274        // 1. A reference to the rust `callback`.
1275        // 2. The text that was returned from the previous call to `callback`. This allows the
1276        //    callback to return owned values like vectors.
1277        let mut payload: Payload<F, T> = (callback, None);
1278
1279        let c_input = ffi::TSInput {
1280            payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1281            read: Some(read::<T, F>),
1282            encoding: ffi::TSInputEncodingUTF16BE,
1283            decode: None,
1284        };
1285
1286        let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1287        unsafe {
1288            let c_new_tree = ffi::ts_parser_parse_with_options(
1289                self.0.as_ptr(),
1290                c_old_tree,
1291                c_input,
1292                parse_options,
1293            );
1294
1295            NonNull::new(c_new_tree).map(Tree)
1296        }
1297    }
1298
1299    /// Parse text provided in chunks by a callback using a custom encoding.
1300    /// This is useful for parsing text in encodings that are not UTF-8 or UTF-16.
1301    ///
1302    /// # Arguments:
1303    /// * `callback` A function that takes a byte offset and position and returns a slice of text
1304    ///   starting at that byte offset and position. The slices can be of any length. If the given
1305    ///   position is at the end of the text, the callback should return an empty slice.
1306    /// * `old_tree` A previous syntax tree parsed from the same document. If the text of the
1307    ///   document has changed since `old_tree` was created, then you must edit `old_tree` to match
1308    ///   the new text using [`Tree::edit`].
1309    /// * `options` Options for parsing the text. This can be used to set a progress callback.
1310    ///
1311    /// Additionally, you must set the generic parameter [`D`] to a type that implements the
1312    /// [`Decode`] trait. This trait has a single method, [`decode`](Decode::decode), which takes a
1313    /// slice of bytes and returns a tuple of the code point and the number of bytes consumed.
1314    /// The `decode` method should return `-1` for the code point if decoding fails.
1315    pub fn parse_custom_encoding<D: Decode, T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
1316        &mut self,
1317        callback: &mut F,
1318        old_tree: Option<&Tree>,
1319        options: Option<ParseOptions>,
1320    ) -> Option<Tree> {
1321        type Payload<'a, F, T> = (&'a mut F, Option<T>);
1322
1323        unsafe extern "C" fn progress(state: *mut ffi::TSParseState) -> bool {
1324            unsafe {
1325                let callback = (*state)
1326                    .payload
1327                    .cast::<ParseProgressCallback>()
1328                    .as_mut()
1329                    .unwrap();
1330                match callback(&ParseState::from_raw(state)) {
1331                    ControlFlow::Continue(()) => false,
1332                    ControlFlow::Break(()) => true,
1333                }
1334            }
1335        }
1336
1337        // At compile time, create a C-compatible callback that calls the custom `decode` method.
1338        unsafe extern "C" fn decode_fn<D: Decode>(
1339            data: *const u8,
1340            len: u32,
1341            code_point: *mut i32,
1342        ) -> u32 {
1343            unsafe {
1344                let (c, len) = D::decode(core::slice::from_raw_parts(data, len as usize));
1345                if let Some(code_point) = code_point.as_mut() {
1346                    *code_point = c;
1347                }
1348                len
1349            }
1350        }
1351
1352        // This C function is passed to Tree-sitter as the input callback.
1353        unsafe extern "C" fn read<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
1354            payload: *mut c_void,
1355            byte_offset: u32,
1356            position: ffi::TSPoint,
1357            bytes_read: *mut u32,
1358        ) -> *const c_char {
1359            unsafe {
1360                let (callback, text) = payload.cast::<Payload<F, T>>().as_mut().unwrap();
1361                *text = Some(callback(byte_offset as usize, position.into()));
1362                let slice = text.as_ref().unwrap().as_ref();
1363                *bytes_read = slice.len() as u32;
1364                slice.as_ptr().cast::<c_char>()
1365            }
1366        }
1367
1368        let empty_options = ffi::TSParseOptions {
1369            payload: ptr::null_mut(),
1370            progress_callback: None,
1371        };
1372
1373        let mut callback_ptr;
1374        let parse_options = if let Some(options) = options {
1375            if let Some(cb) = options.progress_callback {
1376                callback_ptr = cb;
1377                ffi::TSParseOptions {
1378                    payload: core::ptr::addr_of_mut!(callback_ptr).cast::<c_void>(),
1379                    progress_callback: Some(progress),
1380                }
1381            } else {
1382                empty_options
1383            }
1384        } else {
1385            empty_options
1386        };
1387
1388        // A pointer to this payload is passed on every call to the `read` C function.
1389        // The payload contains two things:
1390        // 1. A reference to the rust `callback`.
1391        // 2. The text that was returned from the previous call to `callback`. This allows the
1392        //    callback to return owned values like vectors.
1393        let mut payload: Payload<F, T> = (callback, None);
1394
1395        let c_input = ffi::TSInput {
1396            payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
1397            read: Some(read::<T, F>),
1398            encoding: ffi::TSInputEncodingCustom,
1399            // Use this custom decode callback
1400            decode: Some(decode_fn::<D>),
1401        };
1402
1403        let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
1404        unsafe {
1405            let c_new_tree = ffi::ts_parser_parse_with_options(
1406                self.0.as_ptr(),
1407                c_old_tree,
1408                c_input,
1409                parse_options,
1410            );
1411
1412            NonNull::new(c_new_tree).map(Tree)
1413        }
1414    }
1415
1416    /// Instruct the parser to start the next parse from the beginning.
1417    ///
1418    /// If the parser previously failed because of a callback, then by default,
1419    /// it will resume where it left off on the next call to [`parse`](Parser::parse)
1420    /// or other parsing functions. If you don't want to resume, and instead intend to use
1421    /// this parser to parse some other document, you must call `reset` first.
1422    #[doc(alias = "ts_parser_reset")]
1423    pub fn reset(&mut self) {
1424        unsafe { ffi::ts_parser_reset(self.0.as_ptr()) }
1425    }
1426
1427    /// Set the ranges of text that the parser should include when parsing.
1428    ///
1429    /// By default, the parser will always include entire documents. This
1430    /// function allows you to parse only a *portion* of a document but
1431    /// still return a syntax tree whose ranges match up with the document
1432    /// as a whole. You can also pass multiple disjoint ranges.
1433    ///
1434    /// If `ranges` is empty, then the entire document will be parsed.
1435    /// Otherwise, the given ranges must be ordered from earliest to latest
1436    /// in the document, and they must not overlap. That is, the following
1437    /// must hold for all `i` < `length - 1`:
1438    /// ```text
1439    ///     ranges[i].end_byte <= ranges[i + 1].start_byte
1440    /// ```
1441    /// If this requirement is not satisfied, method will return
1442    /// [`IncludedRangesError`] error with an offset in the passed ranges
1443    /// slice pointing to a first incorrect range.
1444    #[doc(alias = "ts_parser_set_included_ranges")]
1445    pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> {
1446        let ts_ranges = ranges.iter().copied().map(Into::into).collect::<Vec<_>>();
1447        let result = unsafe {
1448            ffi::ts_parser_set_included_ranges(
1449                self.0.as_ptr(),
1450                ts_ranges.as_ptr(),
1451                ts_ranges.len() as u32,
1452            )
1453        };
1454
1455        if result {
1456            Ok(())
1457        } else {
1458            let mut prev_end_byte = 0;
1459            for (i, range) in ranges.iter().enumerate() {
1460                if range.start_byte < prev_end_byte || range.end_byte < range.start_byte {
1461                    return Err(IncludedRangesError(i));
1462                }
1463                prev_end_byte = range.end_byte;
1464            }
1465            Err(IncludedRangesError(0))
1466        }
1467    }
1468
1469    /// Get the ranges of text that the parser will include when parsing.
1470    #[doc(alias = "ts_parser_included_ranges")]
1471    #[must_use]
1472    pub fn included_ranges(&self) -> Vec<Range> {
1473        let mut count = 0u32;
1474        unsafe {
1475            let ptr =
1476                ffi::ts_parser_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
1477            let ranges = slice::from_raw_parts(ptr, count as usize);
1478            ranges.iter().copied().map(Into::into).collect()
1479        }
1480    }
1481}
1482
1483impl Drop for Parser {
1484    fn drop(&mut self) {
1485        #[cfg(feature = "std")]
1486        #[cfg(not(target_os = "wasi"))]
1487        {
1488            self.stop_printing_dot_graphs();
1489        }
1490        self.set_logger(None);
1491        unsafe { ffi::ts_parser_delete(self.0.as_ptr()) }
1492    }
1493}
1494
1495#[cfg(windows)]
1496unsafe extern "C" {
1497    fn _open_osfhandle(osfhandle: isize, flags: core::ffi::c_int) -> core::ffi::c_int;
1498}
1499
1500impl Tree {
1501    /// Get the root node of the syntax tree.
1502    #[doc(alias = "ts_tree_root_node")]
1503    #[must_use]
1504    pub fn root_node(&self) -> Node {
1505        Node::new(unsafe { ffi::ts_tree_root_node(self.0.as_ptr()) }).unwrap()
1506    }
1507
1508    /// Get the root node of the syntax tree, but with its position shifted
1509    /// forward by the given offset.
1510    #[doc(alias = "ts_tree_root_node_with_offset")]
1511    #[must_use]
1512    pub fn root_node_with_offset(&self, offset_bytes: usize, offset_extent: Point) -> Node {
1513        Node::new(unsafe {
1514            ffi::ts_tree_root_node_with_offset(
1515                self.0.as_ptr(),
1516                offset_bytes as u32,
1517                offset_extent.into(),
1518            )
1519        })
1520        .unwrap()
1521    }
1522
1523    /// Get the language that was used to parse the syntax tree.
1524    ///
1525    /// When Tree-sitter is compiled to WebAssembly, this returns the original
1526    /// language if the tree is being accessed from the same WebAssembly
1527    /// instance that created it. Otherwise, this returns a copy of the language
1528    /// that can be used to inspect the tree but cannot be assigned to a parser.
1529    #[doc(alias = "ts_tree_language")]
1530    #[must_use]
1531    pub fn language(&self) -> LanguageRef {
1532        LanguageRef(
1533            unsafe { ffi::ts_tree_language(self.0.as_ptr()) },
1534            PhantomData,
1535        )
1536    }
1537
1538    /// Edit the syntax tree to keep it in sync with source code that has been
1539    /// edited.
1540    ///
1541    /// You must describe the edit both in terms of byte offsets and in terms of
1542    /// row/column coordinates.
1543    #[doc(alias = "ts_tree_edit")]
1544    pub fn edit(&mut self, edit: &InputEdit) {
1545        let edit = edit.into();
1546        unsafe { ffi::ts_tree_edit(self.0.as_ptr(), &raw const edit) };
1547    }
1548
1549    /// Create a new [`TreeCursor`] starting from the root of the tree.
1550    #[must_use]
1551    pub fn walk(&self) -> TreeCursor {
1552        self.root_node().walk()
1553    }
1554
1555    /// Compare this old edited syntax tree to a new syntax tree representing
1556    /// the same document, returning a sequence of ranges whose syntactic
1557    /// structure has changed.
1558    ///
1559    /// For this to work correctly, this syntax tree must have been edited such
1560    /// that its ranges match up to the new tree. Generally, you'll want to
1561    /// call this method right after calling one of the [`Parser::parse`]
1562    /// functions. Call it on the old tree that was passed to parse, and
1563    /// pass the new tree that was returned from `parse`.
1564    #[doc(alias = "ts_tree_get_changed_ranges")]
1565    pub fn changed_ranges(&self, other: &Self) -> impl ExactSizeIterator<Item = Range> {
1566        let mut count = 0u32;
1567        unsafe {
1568            let ptr = ffi::ts_tree_get_changed_ranges(
1569                self.0.as_ptr(),
1570                other.0.as_ptr(),
1571                core::ptr::addr_of_mut!(count),
1572            );
1573            util::CBufferIter::new(ptr, count as usize).map(Into::into)
1574        }
1575    }
1576
1577    /// Get the included ranges that were used to parse the syntax tree.
1578    #[doc(alias = "ts_tree_included_ranges")]
1579    #[must_use]
1580    pub fn included_ranges(&self) -> Vec<Range> {
1581        let mut count = 0u32;
1582        unsafe {
1583            let ptr = ffi::ts_tree_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
1584            let ranges = slice::from_raw_parts(ptr, count as usize);
1585            let result = ranges.iter().copied().map(Into::into).collect();
1586            ts_free(ptr.cast::<c_void>());
1587            result
1588        }
1589    }
1590
1591    /// Print a graph of the tree to the given file descriptor.
1592    /// The graph is formatted in the DOT language. You may want to pipe this
1593    /// graph directly to a `dot(1)` process in order to generate SVG
1594    /// output.
1595    #[doc(alias = "ts_tree_print_dot_graph")]
1596    #[cfg(not(target_os = "wasi"))]
1597    #[cfg(feature = "std")]
1598    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1599    pub fn print_dot_graph(
1600        &self,
1601        #[cfg(unix)] file: &impl AsRawFd,
1602        #[cfg(windows)] file: &impl AsRawHandle,
1603    ) {
1604        #[cfg(unix)]
1605        {
1606            let fd = file.as_raw_fd();
1607            unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1608        }
1609
1610        #[cfg(windows)]
1611        {
1612            let handle = file.as_raw_handle();
1613            let fd = unsafe { _open_osfhandle(handle as isize, 0) };
1614            unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
1615        }
1616    }
1617}
1618
1619impl fmt::Debug for Tree {
1620    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1621        write!(f, "{{Tree {:?}}}", self.root_node())
1622    }
1623}
1624
1625impl Drop for Tree {
1626    fn drop(&mut self) {
1627        unsafe { ffi::ts_tree_delete(self.0.as_ptr()) }
1628    }
1629}
1630
1631impl Clone for Tree {
1632    fn clone(&self) -> Self {
1633        unsafe { Self(NonNull::new_unchecked(ffi::ts_tree_copy(self.0.as_ptr()))) }
1634    }
1635}
1636
1637impl<'tree> Node<'tree> {
1638    fn new(node: ffi::TSNode) -> Option<Self> {
1639        (!node.id.is_null()).then_some(Node(node, PhantomData))
1640    }
1641
1642    /// Get a numeric id for this node that is unique.
1643    ///
1644    /// Within a given syntax tree, no two nodes have the same id. However:
1645    ///
1646    /// - If a new tree is created based on an older tree, and a node from the old tree is reused in
1647    ///   the process, then that node will have the same id in both trees.
1648    ///
1649    /// - A node not marked as having changes does not guarantee it was reused.
1650    ///
1651    /// - If a node is marked as having changed in the old tree, it will not be reused.
1652    #[must_use]
1653    pub fn id(&self) -> usize {
1654        self.0.id as usize
1655    }
1656
1657    /// Get this node's type as a numerical id.
1658    #[doc(alias = "ts_node_symbol")]
1659    #[must_use]
1660    pub fn kind_id(&self) -> u16 {
1661        unsafe { ffi::ts_node_symbol(self.0) }
1662    }
1663
1664    /// Get the node's type as a numerical id as it appears in the grammar
1665    /// ignoring aliases.
1666    #[doc(alias = "ts_node_grammar_symbol")]
1667    #[must_use]
1668    pub fn grammar_id(&self) -> u16 {
1669        unsafe { ffi::ts_node_grammar_symbol(self.0) }
1670    }
1671
1672    /// Get this node's type as a string.
1673    #[doc(alias = "ts_node_type")]
1674    #[must_use]
1675    pub fn kind(&self) -> &'tree str {
1676        let ptr = unsafe { ffi::ts_node_type(self.0) };
1677        assert!(!ptr.is_null());
1678        unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()
1679    }
1680
1681    /// Get this node's symbol name as it appears in the grammar ignoring
1682    /// aliases as a string.
1683    #[doc(alias = "ts_node_grammar_type")]
1684    #[must_use]
1685    pub fn grammar_name(&self) -> &'tree str {
1686        let ptr = unsafe { ffi::ts_node_grammar_type(self.0) };
1687        assert!(!ptr.is_null());
1688        unsafe { CStr::from_ptr(ptr) }.to_str().unwrap()
1689    }
1690
1691    /// Get the [`Language`] that was used to parse this node's syntax tree.
1692    ///
1693    /// When Tree-sitter is compiled to WebAssembly, this returns the original
1694    /// language if the node is being accessed from the same WebAssembly
1695    /// instance that created its tree. Otherwise, this returns a copy of the
1696    /// language that can be used to inspect the tree but cannot be assigned to
1697    /// a parser.
1698    #[doc(alias = "ts_node_language")]
1699    #[must_use]
1700    pub fn language(&self) -> LanguageRef<'tree> {
1701        LanguageRef(unsafe { ffi::ts_node_language(self.0) }, PhantomData)
1702    }
1703
1704    /// Check if this node is *named*.
1705    ///
1706    /// Named nodes correspond to named rules in the grammar, whereas
1707    /// *anonymous* nodes correspond to string literals in the grammar.
1708    #[doc(alias = "ts_node_is_named")]
1709    #[must_use]
1710    pub fn is_named(&self) -> bool {
1711        unsafe { ffi::ts_node_is_named(self.0) }
1712    }
1713
1714    /// Check if this node is *extra*.
1715    ///
1716    /// Extra nodes represent things like comments, which are not required by the
1717    /// grammar, but can appear anywhere.
1718    #[doc(alias = "ts_node_is_extra")]
1719    #[must_use]
1720    pub fn is_extra(&self) -> bool {
1721        unsafe { ffi::ts_node_is_extra(self.0) }
1722    }
1723
1724    /// Check if this node has been edited.
1725    #[doc(alias = "ts_node_has_changes")]
1726    #[must_use]
1727    pub fn has_changes(&self) -> bool {
1728        unsafe { ffi::ts_node_has_changes(self.0) }
1729    }
1730
1731    /// Check if this node represents a syntax error or contains any syntax
1732    /// errors anywhere within it.
1733    #[doc(alias = "ts_node_has_error")]
1734    #[must_use]
1735    pub fn has_error(&self) -> bool {
1736        unsafe { ffi::ts_node_has_error(self.0) }
1737    }
1738
1739    /// Check if this node represents a syntax error.
1740    ///
1741    /// Syntax errors represent parts of the code that could not be incorporated
1742    /// into a valid syntax tree.
1743    #[doc(alias = "ts_node_is_error")]
1744    #[must_use]
1745    pub fn is_error(&self) -> bool {
1746        unsafe { ffi::ts_node_is_error(self.0) }
1747    }
1748
1749    /// Get the parse state immediately before this node.
1750    ///
1751    /// For a missing node, this is the state from the recovery path that was
1752    /// selected by the parser. It can be used with
1753    /// [`Language::lookahead_iterator`] to inspect the symbols that are valid in
1754    /// that state. This does not necessarily include every symbol that could be
1755    /// recovered by inserting a missing node, because the recovery process can
1756    /// consider multiple stack versions.
1757    #[doc(alias = "ts_node_parse_state")]
1758    #[must_use]
1759    pub fn parse_state(&self) -> u16 {
1760        unsafe { ffi::ts_node_parse_state(self.0) }
1761    }
1762
1763    /// Get the parse state after this node.
1764    #[doc(alias = "ts_node_next_parse_state")]
1765    #[must_use]
1766    pub fn next_parse_state(&self) -> u16 {
1767        unsafe { ffi::ts_node_next_parse_state(self.0) }
1768    }
1769
1770    /// Check if this node is *missing*.
1771    ///
1772    /// Missing nodes are inserted by the parser in order to recover from
1773    /// certain kinds of syntax errors.
1774    #[doc(alias = "ts_node_is_missing")]
1775    #[must_use]
1776    pub fn is_missing(&self) -> bool {
1777        unsafe { ffi::ts_node_is_missing(self.0) }
1778    }
1779
1780    /// Get the byte offset where this node starts.
1781    #[doc(alias = "ts_node_start_byte")]
1782    #[must_use]
1783    pub fn start_byte(&self) -> usize {
1784        unsafe { ffi::ts_node_start_byte(self.0) as usize }
1785    }
1786
1787    /// Get the byte offset where this node ends.
1788    #[doc(alias = "ts_node_end_byte")]
1789    #[must_use]
1790    pub fn end_byte(&self) -> usize {
1791        unsafe { ffi::ts_node_end_byte(self.0) as usize }
1792    }
1793
1794    /// Get the byte range of source code that this node represents.
1795    #[must_use]
1796    pub fn byte_range(&self) -> core::ops::Range<usize> {
1797        self.start_byte()..self.end_byte()
1798    }
1799
1800    /// Get the range of source code that this node represents, both in terms of
1801    /// raw bytes and of row/column coordinates.
1802    #[must_use]
1803    pub fn range(&self) -> Range {
1804        Range {
1805            start_byte: self.start_byte(),
1806            end_byte: self.end_byte(),
1807            start_point: self.start_position(),
1808            end_point: self.end_position(),
1809        }
1810    }
1811
1812    /// Get this node's start position in terms of rows and columns.
1813    #[doc(alias = "ts_node_start_point")]
1814    #[must_use]
1815    pub fn start_position(&self) -> Point {
1816        let result = unsafe { ffi::ts_node_start_point(self.0) };
1817        result.into()
1818    }
1819
1820    /// Get this node's end position in terms of rows and columns.
1821    #[doc(alias = "ts_node_end_point")]
1822    #[must_use]
1823    pub fn end_position(&self) -> Point {
1824        let result = unsafe { ffi::ts_node_end_point(self.0) };
1825        result.into()
1826    }
1827
1828    /// Get the node's child at the given index, where zero represents the first
1829    /// child.
1830    ///
1831    /// This method is fairly fast, but its cost is technically log(i), so if
1832    /// you might be iterating over a long list of children, you should use
1833    /// [`Node::children`] instead.
1834    #[doc(alias = "ts_node_child")]
1835    #[must_use]
1836    pub fn child(&self, i: u32) -> Option<Self> {
1837        Self::new(unsafe { ffi::ts_node_child(self.0, i) })
1838    }
1839
1840    /// Get this node's number of children.
1841    #[doc(alias = "ts_node_child_count")]
1842    #[must_use]
1843    pub fn child_count(&self) -> u32 {
1844        unsafe { ffi::ts_node_child_count(self.0) }
1845    }
1846
1847    /// Get this node's *named* child at the given index.
1848    ///
1849    /// See also [`Node::is_named`].
1850    /// This method is fairly fast, but its cost is technically log(i), so if
1851    /// you might be iterating over a long list of children, you should use
1852    /// [`Node::named_children`] instead.
1853    #[doc(alias = "ts_node_named_child")]
1854    #[must_use]
1855    pub fn named_child(&self, i: u32) -> Option<Self> {
1856        Self::new(unsafe { ffi::ts_node_named_child(self.0, i) })
1857    }
1858
1859    /// Get this node's number of *named* children.
1860    ///
1861    /// See also [`Node::is_named`].
1862    #[doc(alias = "ts_node_named_child_count")]
1863    #[must_use]
1864    pub fn named_child_count(&self) -> usize {
1865        unsafe { ffi::ts_node_named_child_count(self.0) as usize }
1866    }
1867
1868    /// Get the first child with the given field name.
1869    ///
1870    /// If multiple children may have the same field name, access them using
1871    /// [`children_by_field_name`](Node::children_by_field_name)
1872    #[doc(alias = "ts_node_child_by_field_name")]
1873    #[must_use]
1874    pub fn child_by_field_name(&self, field_name: impl AsRef<[u8]>) -> Option<Self> {
1875        let field_name = field_name.as_ref();
1876        Self::new(unsafe {
1877            ffi::ts_node_child_by_field_name(
1878                self.0,
1879                field_name.as_ptr().cast::<c_char>(),
1880                field_name.len() as u32,
1881            )
1882        })
1883    }
1884
1885    /// Get this node's child with the given numerical field id.
1886    ///
1887    /// See also [`child_by_field_name`](Node::child_by_field_name). You can
1888    /// convert a field name to an id using [`Language::field_id_for_name`].
1889    #[doc(alias = "ts_node_child_by_field_id")]
1890    #[must_use]
1891    pub fn child_by_field_id(&self, field_id: u16) -> Option<Self> {
1892        Self::new(unsafe { ffi::ts_node_child_by_field_id(self.0, field_id) })
1893    }
1894
1895    /// Get the field name of this node's child at the given index.
1896    #[doc(alias = "ts_node_field_name_for_child")]
1897    #[must_use]
1898    pub fn field_name_for_child(&self, child_index: u32) -> Option<&'tree str> {
1899        unsafe {
1900            let ptr = ffi::ts_node_field_name_for_child(self.0, child_index);
1901            (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1902        }
1903    }
1904
1905    /// Get the field name of this node's named child at the given index.
1906    #[must_use]
1907    pub fn field_name_for_named_child(&self, named_child_index: u32) -> Option<&'tree str> {
1908        unsafe {
1909            let ptr = ffi::ts_node_field_name_for_named_child(self.0, named_child_index);
1910            (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1911        }
1912    }
1913
1914    /// Iterate over this node's children.
1915    ///
1916    /// A [`TreeCursor`] is used to retrieve the children efficiently. Obtain
1917    /// a [`TreeCursor`] by calling [`Tree::walk`] or [`Node::walk`]. To avoid
1918    /// unnecessary allocations, you should reuse the same cursor for
1919    /// subsequent calls to this method.
1920    ///
1921    /// If you're walking the tree recursively, you may want to use the
1922    /// [`TreeCursor`] APIs directly instead.
1923    pub fn children<'cursor>(
1924        &self,
1925        cursor: &'cursor mut TreeCursor<'tree>,
1926    ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1927        cursor.reset(*self);
1928        cursor.goto_first_child();
1929        (0..self.child_count()).map(move |_| {
1930            let result = cursor.node();
1931            cursor.goto_next_sibling();
1932            result
1933        })
1934    }
1935
1936    /// Iterate over this node's named children.
1937    ///
1938    /// See also [`Node::children`].
1939    pub fn named_children<'cursor>(
1940        &self,
1941        cursor: &'cursor mut TreeCursor<'tree>,
1942    ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1943        cursor.reset(*self);
1944        cursor.goto_first_child();
1945        (0..self.named_child_count()).map(move |_| {
1946            while !cursor.node().is_named() {
1947                if !cursor.goto_next_sibling() {
1948                    break;
1949                }
1950            }
1951            let result = cursor.node();
1952            cursor.goto_next_sibling();
1953            result
1954        })
1955    }
1956
1957    /// Iterate over this node's children with a given field name.
1958    ///
1959    /// See also [`Node::children`].
1960    pub fn children_by_field_name<'cursor>(
1961        &self,
1962        field_name: &str,
1963        cursor: &'cursor mut TreeCursor<'tree>,
1964    ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1965        let field_id = self.language().field_id_for_name(field_name);
1966        let mut done = field_id.is_none();
1967        if !done {
1968            cursor.reset(*self);
1969            cursor.goto_first_child();
1970        }
1971        iter::from_fn(move || {
1972            if !done {
1973                while cursor.field_id() != field_id {
1974                    if !cursor.goto_next_sibling() {
1975                        return None;
1976                    }
1977                }
1978                let result = cursor.node();
1979                if !cursor.goto_next_sibling() {
1980                    done = true;
1981                }
1982                return Some(result);
1983            }
1984            None
1985        })
1986    }
1987
1988    /// Iterate over this node's children with a given field id.
1989    ///
1990    /// See also [`Node::children_by_field_name`].
1991    pub fn children_by_field_id<'cursor>(
1992        &self,
1993        field_id: FieldId,
1994        cursor: &'cursor mut TreeCursor<'tree>,
1995    ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1996        cursor.reset(*self);
1997        cursor.goto_first_child();
1998        let mut done = false;
1999        iter::from_fn(move || {
2000            if !done {
2001                while cursor.field_id() != Some(field_id) {
2002                    if !cursor.goto_next_sibling() {
2003                        return None;
2004                    }
2005                }
2006                let result = cursor.node();
2007                if !cursor.goto_next_sibling() {
2008                    done = true;
2009                }
2010                return Some(result);
2011            }
2012            None
2013        })
2014    }
2015
2016    /// Get this node's immediate parent.
2017    /// Prefer [`child_with_descendant`](Node::child_with_descendant)
2018    /// for iterating over this node's ancestors.
2019    #[doc(alias = "ts_node_parent")]
2020    #[must_use]
2021    pub fn parent(&self) -> Option<Self> {
2022        Self::new(unsafe { ffi::ts_node_parent(self.0) })
2023    }
2024
2025    /// Get the node that contains `descendant`.
2026    ///
2027    /// Note that this can return `descendant` itself.
2028    #[doc(alias = "ts_node_child_with_descendant")]
2029    #[must_use]
2030    pub fn child_with_descendant(&self, descendant: Self) -> Option<Self> {
2031        Self::new(unsafe { ffi::ts_node_child_with_descendant(self.0, descendant.0) })
2032    }
2033
2034    /// Get this node's next sibling.
2035    #[doc(alias = "ts_node_next_sibling")]
2036    #[must_use]
2037    pub fn next_sibling(&self) -> Option<Self> {
2038        Self::new(unsafe { ffi::ts_node_next_sibling(self.0) })
2039    }
2040
2041    /// Get this node's previous sibling.
2042    #[doc(alias = "ts_node_prev_sibling")]
2043    #[must_use]
2044    pub fn prev_sibling(&self) -> Option<Self> {
2045        Self::new(unsafe { ffi::ts_node_prev_sibling(self.0) })
2046    }
2047
2048    /// Get this node's next named sibling.
2049    #[doc(alias = "ts_node_next_named_sibling")]
2050    #[must_use]
2051    pub fn next_named_sibling(&self) -> Option<Self> {
2052        Self::new(unsafe { ffi::ts_node_next_named_sibling(self.0) })
2053    }
2054
2055    /// Get this node's previous named sibling.
2056    #[doc(alias = "ts_node_prev_named_sibling")]
2057    #[must_use]
2058    pub fn prev_named_sibling(&self) -> Option<Self> {
2059        Self::new(unsafe { ffi::ts_node_prev_named_sibling(self.0) })
2060    }
2061
2062    /// Get this node's first child that contains or starts after the given byte offset.
2063    #[doc(alias = "ts_node_first_child_for_byte")]
2064    #[must_use]
2065    pub fn first_child_for_byte(&self, byte: usize) -> Option<Self> {
2066        Self::new(unsafe { ffi::ts_node_first_child_for_byte(self.0, byte as u32) })
2067    }
2068
2069    /// Get this node's first named child that contains or starts after the given byte offset.
2070    #[doc(alias = "ts_node_first_named_child_for_point")]
2071    #[must_use]
2072    pub fn first_named_child_for_byte(&self, byte: usize) -> Option<Self> {
2073        Self::new(unsafe { ffi::ts_node_first_named_child_for_byte(self.0, byte as u32) })
2074    }
2075
2076    /// Get the node's number of descendants, including one for the node itself.
2077    #[doc(alias = "ts_node_descendant_count")]
2078    #[must_use]
2079    pub fn descendant_count(&self) -> usize {
2080        unsafe { ffi::ts_node_descendant_count(self.0) as usize }
2081    }
2082
2083    /// Get the smallest node within this node that spans the given byte range.
2084    #[doc(alias = "ts_node_descendant_for_byte_range")]
2085    #[must_use]
2086    pub fn descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
2087        Self::new(unsafe {
2088            ffi::ts_node_descendant_for_byte_range(self.0, start as u32, end as u32)
2089        })
2090    }
2091
2092    /// Get the smallest named node within this node that spans the given byte range.
2093    #[doc(alias = "ts_node_named_descendant_for_byte_range")]
2094    #[must_use]
2095    pub fn named_descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
2096        Self::new(unsafe {
2097            ffi::ts_node_named_descendant_for_byte_range(self.0, start as u32, end as u32)
2098        })
2099    }
2100
2101    /// Get the smallest node within this node that spans the given point range.
2102    #[doc(alias = "ts_node_descendant_for_point_range")]
2103    #[must_use]
2104    pub fn descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
2105        Self::new(unsafe {
2106            ffi::ts_node_descendant_for_point_range(self.0, start.into(), end.into())
2107        })
2108    }
2109
2110    /// Get the smallest named node within this node that spans the given point range.
2111    #[doc(alias = "ts_node_named_descendant_for_point_range")]
2112    #[must_use]
2113    pub fn named_descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
2114        Self::new(unsafe {
2115            ffi::ts_node_named_descendant_for_point_range(self.0, start.into(), end.into())
2116        })
2117    }
2118
2119    /// Get an S-expression representing the node.
2120    #[doc(alias = "ts_node_string")]
2121    #[must_use]
2122    pub fn to_sexp(&self) -> String {
2123        let c_string = unsafe { ffi::ts_node_string(self.0) };
2124        let result = unsafe { CStr::from_ptr(c_string) }
2125            .to_str()
2126            .unwrap()
2127            .to_string();
2128        unsafe { ts_free(c_string.cast::<c_void>()) };
2129        result
2130    }
2131
2132    pub fn utf8_text<'a>(&self, source: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
2133        str::from_utf8(&source[self.start_byte()..self.end_byte()])
2134    }
2135
2136    #[must_use]
2137    pub fn utf16_text<'a>(&self, source: &'a [u16]) -> &'a [u16] {
2138        &source[self.start_byte() / 2..self.end_byte() / 2]
2139    }
2140
2141    /// Create a new [`TreeCursor`] starting from this node.
2142    ///
2143    /// Note that the given node is considered the root of the cursor,
2144    /// and the cursor cannot walk outside this node.
2145    #[doc(alias = "ts_tree_cursor_new")]
2146    #[must_use]
2147    pub fn walk(&self) -> TreeCursor<'tree> {
2148        TreeCursor(unsafe { ffi::ts_tree_cursor_new(self.0) }, PhantomData)
2149    }
2150
2151    /// Edit this node to keep it in-sync with source code that has been edited.
2152    ///
2153    /// This function is only rarely needed. When you edit a syntax tree with
2154    /// the [`Tree::edit`] method, all of the nodes that you retrieve from
2155    /// the tree afterward will already reflect the edit. You only need to
2156    /// use [`Node::edit`] when you have a specific [`Node`] instance that
2157    /// you want to keep and continue to use after an edit.
2158    #[doc(alias = "ts_node_edit")]
2159    pub fn edit(&mut self, edit: &InputEdit) {
2160        let edit = edit.into();
2161        unsafe { ffi::ts_node_edit(core::ptr::addr_of_mut!(self.0), &raw const edit) }
2162    }
2163}
2164
2165impl PartialEq for Node<'_> {
2166    fn eq(&self, other: &Self) -> bool {
2167        core::ptr::eq(self.0.id, other.0.id)
2168    }
2169}
2170
2171impl Eq for Node<'_> {}
2172
2173impl hash::Hash for Node<'_> {
2174    fn hash<H: hash::Hasher>(&self, state: &mut H) {
2175        self.0.id.hash(state);
2176        self.0.context[0].hash(state);
2177        self.0.context[1].hash(state);
2178        self.0.context[2].hash(state);
2179        self.0.context[3].hash(state);
2180    }
2181}
2182
2183impl fmt::Debug for Node<'_> {
2184    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2185        write!(
2186            f,
2187            "{{Node {} {} - {}}}",
2188            self.kind(),
2189            self.start_position(),
2190            self.end_position()
2191        )
2192    }
2193}
2194
2195impl fmt::Display for Node<'_> {
2196    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2197        if !f.alternate() {
2198            return f.write_str(&self.to_sexp());
2199        }
2200        let c_string = unsafe { ts_node_string_pretty(self.0, f.width().unwrap_or(0)) };
2201        let result = unsafe { CStr::from_ptr(c_string) }
2202            .to_str()
2203            .unwrap()
2204            .to_string();
2205        unsafe { ts_free(c_string.cast::<c_void>()) };
2206        f.write_str(&result)
2207    }
2208}
2209
2210impl<'tree> TreeCursor<'tree> {
2211    /// Get the tree cursor's current [`Node`].
2212    #[doc(alias = "ts_tree_cursor_current_node")]
2213    #[must_use]
2214    pub fn node(&self) -> Node<'tree> {
2215        Node(
2216            unsafe { ffi::ts_tree_cursor_current_node(&raw const self.0) },
2217            PhantomData,
2218        )
2219    }
2220
2221    /// Get the numerical field id of this tree cursor's current node.
2222    ///
2223    /// See also [`field_name`](TreeCursor::field_name).
2224    #[doc(alias = "ts_tree_cursor_current_field_id")]
2225    #[must_use]
2226    pub fn field_id(&self) -> Option<FieldId> {
2227        let id = unsafe { ffi::ts_tree_cursor_current_field_id(&raw const self.0) };
2228        FieldId::new(id)
2229    }
2230
2231    /// Get the field name of this tree cursor's current node.
2232    #[doc(alias = "ts_tree_cursor_current_field_name")]
2233    #[must_use]
2234    pub fn field_name(&self) -> Option<&'tree str> {
2235        unsafe {
2236            let ptr = ffi::ts_tree_cursor_current_field_name(&raw const self.0);
2237            (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
2238        }
2239    }
2240
2241    /// Get the depth of the cursor's current node relative to the original
2242    /// node that the cursor was constructed with.
2243    #[doc(alias = "ts_tree_cursor_current_depth")]
2244    #[must_use]
2245    pub fn depth(&self) -> u32 {
2246        unsafe { ffi::ts_tree_cursor_current_depth(&raw const self.0) }
2247    }
2248
2249    /// Get the index of the cursor's current node out of all of the
2250    /// descendants of the original node that the cursor was constructed with
2251    #[doc(alias = "ts_tree_cursor_current_descendant_index")]
2252    #[must_use]
2253    pub fn descendant_index(&self) -> usize {
2254        unsafe { ffi::ts_tree_cursor_current_descendant_index(&raw const self.0) as usize }
2255    }
2256
2257    /// Move this cursor to the first child of its current node.
2258    ///
2259    /// This returns `true` if the cursor successfully moved, and returns
2260    /// `false` if there were no children.
2261    #[doc(alias = "ts_tree_cursor_goto_first_child")]
2262    pub fn goto_first_child(&mut self) -> bool {
2263        unsafe { ffi::ts_tree_cursor_goto_first_child(&raw mut self.0) }
2264    }
2265
2266    /// Move this cursor to the last child of its current node.
2267    ///
2268    /// This returns `true` if the cursor successfully moved, and returns
2269    /// `false` if there were no children.
2270    ///
2271    /// Note that this function may be slower than
2272    /// [`goto_first_child`](TreeCursor::goto_first_child) because it needs to
2273    /// iterate through all the children to compute the child's position.
2274    #[doc(alias = "ts_tree_cursor_goto_last_child")]
2275    pub fn goto_last_child(&mut self) -> bool {
2276        unsafe { ffi::ts_tree_cursor_goto_last_child(&raw mut self.0) }
2277    }
2278
2279    /// Move this cursor to the parent of its current node.
2280    ///
2281    /// This returns `true` if the cursor successfully moved, and returns
2282    /// `false` if there was no parent node (the cursor was already on the
2283    /// root node).
2284    ///
2285    /// Note that the node the cursor was constructed with is considered the root
2286    /// of the cursor, and the cursor cannot walk outside this node.
2287    #[doc(alias = "ts_tree_cursor_goto_parent")]
2288    pub fn goto_parent(&mut self) -> bool {
2289        unsafe { ffi::ts_tree_cursor_goto_parent(&raw mut self.0) }
2290    }
2291
2292    /// Move this cursor to the next sibling of its current node.
2293    ///
2294    /// This returns `true` if the cursor successfully moved, and returns
2295    /// `false` if there was no next sibling node.
2296    ///
2297    /// Note that the node the cursor was constructed with is considered the root
2298    /// of the cursor, and the cursor cannot walk outside this node.
2299    #[doc(alias = "ts_tree_cursor_goto_next_sibling")]
2300    pub fn goto_next_sibling(&mut self) -> bool {
2301        unsafe { ffi::ts_tree_cursor_goto_next_sibling(&raw mut self.0) }
2302    }
2303
2304    /// Move the cursor to the node that is the nth descendant of
2305    /// the original node that the cursor was constructed with, where
2306    /// zero represents the original node itself.
2307    #[doc(alias = "ts_tree_cursor_goto_descendant")]
2308    pub fn goto_descendant(&mut self, descendant_index: usize) {
2309        unsafe { ffi::ts_tree_cursor_goto_descendant(&raw mut self.0, descendant_index as u32) }
2310    }
2311
2312    /// Move this cursor to the previous sibling of its current node.
2313    ///
2314    /// This returns `true` if the cursor successfully moved, and returns
2315    /// `false` if there was no previous sibling node.
2316    ///
2317    /// Note, that this function may be slower than
2318    /// [`goto_next_sibling`](TreeCursor::goto_next_sibling) due to how node
2319    /// positions are stored. In the worst case, this will need to iterate
2320    /// through all the children up to the previous sibling node to recalculate
2321    /// its position. Also note that the node the cursor was constructed with is
2322    /// considered the root of the cursor, and the cursor cannot walk outside this node.
2323    #[doc(alias = "ts_tree_cursor_goto_previous_sibling")]
2324    pub fn goto_previous_sibling(&mut self) -> bool {
2325        unsafe { ffi::ts_tree_cursor_goto_previous_sibling(&raw mut self.0) }
2326    }
2327
2328    /// Move this cursor to the first child of its current node that contains or
2329    /// starts after the given byte offset.
2330    ///
2331    /// This returns the index of the child node if one was found, and returns
2332    /// `None` if no such child was found.
2333    #[doc(alias = "ts_tree_cursor_goto_first_child_for_byte")]
2334    pub fn goto_first_child_for_byte(&mut self, index: usize) -> Option<usize> {
2335        let result =
2336            unsafe { ffi::ts_tree_cursor_goto_first_child_for_byte(&raw mut self.0, index as u32) };
2337        result.try_into().ok()
2338    }
2339
2340    /// Move this cursor to the first child of its current node that contains or
2341    /// starts after the given byte offset.
2342    ///
2343    /// This returns the index of the child node if one was found, and returns
2344    /// `None` if no such child was found.
2345    #[doc(alias = "ts_tree_cursor_goto_first_child_for_point")]
2346    pub fn goto_first_child_for_point(&mut self, point: Point) -> Option<usize> {
2347        let result = unsafe {
2348            ffi::ts_tree_cursor_goto_first_child_for_point(&raw mut self.0, point.into())
2349        };
2350        result.try_into().ok()
2351    }
2352
2353    /// Re-initialize this tree cursor to start at the original node that the
2354    /// cursor was constructed with.
2355    #[doc(alias = "ts_tree_cursor_reset")]
2356    pub fn reset(&mut self, node: Node<'tree>) {
2357        unsafe { ffi::ts_tree_cursor_reset(&raw mut self.0, node.0) };
2358    }
2359
2360    /// Re-initialize a tree cursor to the same position as another cursor.
2361    ///
2362    /// Unlike [`reset`](TreeCursor::reset), this will not lose parent
2363    /// information and allows reusing already created cursors.
2364    #[doc(alias = "ts_tree_cursor_reset_to")]
2365    pub fn reset_to(&mut self, cursor: &Self) {
2366        unsafe { ffi::ts_tree_cursor_reset_to(&raw mut self.0, &raw const cursor.0) };
2367    }
2368}
2369
2370impl Clone for TreeCursor<'_> {
2371    fn clone(&self) -> Self {
2372        TreeCursor(
2373            unsafe { ffi::ts_tree_cursor_copy(&raw const self.0) },
2374            PhantomData,
2375        )
2376    }
2377}
2378
2379impl Drop for TreeCursor<'_> {
2380    fn drop(&mut self) {
2381        unsafe { ffi::ts_tree_cursor_delete(&raw mut self.0) }
2382    }
2383}
2384
2385impl LookaheadIterator {
2386    /// Get the current language of the lookahead iterator.
2387    #[doc(alias = "ts_lookahead_iterator_language")]
2388    #[must_use]
2389    pub fn language(&self) -> LanguageRef<'_> {
2390        LanguageRef(
2391            unsafe { ffi::ts_lookahead_iterator_language(self.0.as_ptr()) },
2392            PhantomData,
2393        )
2394    }
2395
2396    /// Get the current symbol of the lookahead iterator.
2397    ///
2398    /// Returns `None` if the iterator is not positioned on a symbol:
2399    ///
2400    /// - Before the first [`Iterator::next`] call
2401    /// - After the iterator is exhausted
2402    /// - After a [`Self::reset`] or [`Self::reset_state`] call
2403    #[doc(alias = "ts_lookahead_iterator_current_symbol")]
2404    #[must_use]
2405    pub fn current_symbol(&self) -> Option<u16> {
2406        // C signals "not positioned" through a null symbol name.
2407        let name = unsafe { ffi::ts_lookahead_iterator_current_symbol_name(self.0.as_ptr()) };
2408        (!name.is_null())
2409            .then(|| unsafe { ffi::ts_lookahead_iterator_current_symbol(self.0.as_ptr()) })
2410    }
2411
2412    /// Get the current symbol name of the lookahead iterator.
2413    ///
2414    /// Returns `None` if the iterator is not positioned on a symbol.
2415    #[doc(alias = "ts_lookahead_iterator_current_symbol_name")]
2416    #[must_use]
2417    pub fn current_symbol_name(&self) -> Option<&str> {
2418        unsafe {
2419            let name = ffi::ts_lookahead_iterator_current_symbol_name(self.0.as_ptr());
2420            if name.is_null() {
2421                None
2422            } else {
2423                Some(CStr::from_ptr(name).to_str().unwrap())
2424            }
2425        }
2426    }
2427
2428    /// Reset the lookahead iterator.
2429    ///
2430    /// This returns `true` if the language was set successfully and `false`
2431    /// otherwise.
2432    #[doc(alias = "ts_lookahead_iterator_reset")]
2433    pub fn reset(&mut self, language: &Language, state: u16) -> bool {
2434        unsafe { ffi::ts_lookahead_iterator_reset(self.0.as_ptr(), language.0, state) }
2435    }
2436
2437    /// Reset the lookahead iterator to another state.
2438    ///
2439    /// This returns `true` if the iterator was reset to the given state and
2440    /// `false` otherwise.
2441    #[doc(alias = "ts_lookahead_iterator_reset_state")]
2442    pub fn reset_state(&mut self, state: u16) -> bool {
2443        unsafe { ffi::ts_lookahead_iterator_reset_state(self.0.as_ptr(), state) }
2444    }
2445
2446    /// Iterate symbol names.
2447    pub fn iter_names(&mut self) -> impl iter::FusedIterator<Item = &str> + '_ {
2448        LookaheadNamesIterator(self)
2449    }
2450}
2451
2452impl<'a> Iterator for LookaheadNamesIterator<'a> {
2453    type Item = &'a str;
2454
2455    #[doc(alias = "ts_lookahead_iterator_next")]
2456    fn next(&mut self) -> Option<Self::Item> {
2457        let ptr = self.0.0.as_ptr();
2458        // SAFETY: The borrow keeps the iterator (and the language refcount it holds)
2459        // alive for `'a`. The name is non-null because the iterator is positioned
2460        // whenever `next` returns `true`.
2461        unsafe {
2462            ffi::ts_lookahead_iterator_next(ptr).then(|| {
2463                let name = ffi::ts_lookahead_iterator_current_symbol_name(ptr);
2464                debug_assert!(!name.is_null());
2465                CStr::from_ptr(name).to_str().unwrap()
2466            })
2467        }
2468    }
2469}
2470
2471impl iter::FusedIterator for LookaheadNamesIterator<'_> {}
2472
2473impl Iterator for LookaheadIterator {
2474    type Item = u16;
2475
2476    #[doc(alias = "ts_lookahead_iterator_next")]
2477    fn next(&mut self) -> Option<Self::Item> {
2478        unsafe { ffi::ts_lookahead_iterator_next(self.0.as_ptr()) }
2479            .then(|| unsafe { ffi::ts_lookahead_iterator_current_symbol(self.0.as_ptr()) })
2480    }
2481}
2482
2483impl iter::FusedIterator for LookaheadIterator {}
2484
2485impl Drop for LookaheadIterator {
2486    #[doc(alias = "ts_lookahead_iterator_delete")]
2487    fn drop(&mut self) {
2488        unsafe { ffi::ts_lookahead_iterator_delete(self.0.as_ptr()) }
2489    }
2490}
2491
2492impl Query {
2493    /// Create a new query from a string containing one or more S-expression
2494    /// patterns.
2495    ///
2496    /// The query is associated with a particular language, and can only be run
2497    /// on syntax nodes parsed with that language. References to Queries can be
2498    /// shared between multiple threads.
2499    ///
2500    /// Patterns are limited to 100 levels of nesting, including groups, alternations,
2501    /// and field constraints. Exceeding this limit returns [`QueryErrorKind::Structure`].
2502    pub fn new(language: &Language, source: &str) -> Result<Self, QueryError> {
2503        let ptr = Self::new_raw(language, source)?;
2504        unsafe { Self::from_raw_parts(ptr, source) }
2505    }
2506
2507    /// Constructs a raw [`TSQuery`](ffi::TSQuery) pointer without performing extra checks specific to the rust
2508    /// bindings, such as predicate validation. A [`Query`] object can be constructed from the
2509    /// returned pointer using [`from_raw_parts`](Query::from_raw_parts). The caller is
2510    /// responsible for ensuring that the returned pointer is eventually freed by calling
2511    /// [`ts_query_delete`](ffi::ts_query_delete).
2512    pub fn new_raw(language: &Language, source: &str) -> Result<*mut ffi::TSQuery, QueryError> {
2513        let mut error_offset = 0u32;
2514        let mut error_type: ffi::TSQueryError = 0;
2515        let bytes = source.as_bytes();
2516
2517        // Compile the query.
2518        let ptr = unsafe {
2519            ffi::ts_query_new(
2520                language.0,
2521                bytes.as_ptr().cast::<c_char>(),
2522                bytes.len() as u32,
2523                core::ptr::addr_of_mut!(error_offset),
2524                core::ptr::addr_of_mut!(error_type),
2525            )
2526        };
2527
2528        if !ptr.is_null() {
2529            return Ok(ptr);
2530        }
2531
2532        // On failure, build an error based on the error code and offset.
2533        if error_type == ffi::TSQueryErrorLanguage {
2534            return Err(QueryError {
2535                row: 0,
2536                column: 0,
2537                offset: 0,
2538                message: LanguageError::Version(language.abi_version()).to_string(),
2539                kind: QueryErrorKind::Language,
2540            });
2541        }
2542
2543        let offset = error_offset as usize;
2544        let mut line_start = 0;
2545        let mut row = 0;
2546        let mut line_containing_error = None;
2547        for line in source.lines() {
2548            let line_end = line_start + line.len() + 1;
2549            if line_end > offset {
2550                line_containing_error = Some(line);
2551                break;
2552            }
2553            line_start = line_end;
2554            row += 1;
2555        }
2556        let column = offset - line_start;
2557
2558        let (message, kind) = match error_type {
2559            // Error types that report names
2560            ffi::TSQueryErrorNodeType | ffi::TSQueryErrorField | ffi::TSQueryErrorCapture => {
2561                let suffix = source.split_at(offset).1;
2562                let in_quotes = offset > 0 && source.as_bytes()[offset - 1] == b'"';
2563                let mut backslashes = 0;
2564                let end_offset = suffix
2565                    .find(|c| {
2566                        if in_quotes {
2567                            if c == '"' && backslashes % 2 == 0 {
2568                                true
2569                            } else if c == '\\' {
2570                                backslashes += 1;
2571                                false
2572                            } else {
2573                                backslashes = 0;
2574                                false
2575                            }
2576                        } else {
2577                            !char::is_alphanumeric(c) && c != '_' && c != '-'
2578                        }
2579                    })
2580                    .unwrap_or(suffix.len());
2581                (
2582                    format!("\"{}\"", suffix.split_at(end_offset).0),
2583                    match error_type {
2584                        ffi::TSQueryErrorNodeType => QueryErrorKind::NodeType,
2585                        ffi::TSQueryErrorField => QueryErrorKind::Field,
2586                        ffi::TSQueryErrorCapture => QueryErrorKind::Capture,
2587                        _ => unreachable!(),
2588                    },
2589                )
2590            }
2591
2592            // Error types that report positions
2593            _ => (
2594                line_containing_error.map_or_else(
2595                    || "Unexpected EOF".to_string(),
2596                    |line| line.to_string() + "\n" + &" ".repeat(offset - line_start) + "^",
2597                ),
2598                match error_type {
2599                    ffi::TSQueryErrorStructure => QueryErrorKind::Structure,
2600                    _ => QueryErrorKind::Syntax,
2601                },
2602            ),
2603        };
2604
2605        Err(QueryError {
2606            row,
2607            column,
2608            offset,
2609            message,
2610            kind,
2611        })
2612    }
2613
2614    #[doc(hidden)]
2615    unsafe fn from_raw_parts(ptr: *mut ffi::TSQuery, source: &str) -> Result<Self, QueryError> {
2616        let ptr = {
2617            struct TSQueryDrop(*mut ffi::TSQuery);
2618            impl Drop for TSQueryDrop {
2619                fn drop(&mut self) {
2620                    unsafe { ffi::ts_query_delete(self.0) }
2621                }
2622            }
2623            TSQueryDrop(ptr)
2624        };
2625
2626        let string_count = unsafe { ffi::ts_query_string_count(ptr.0) };
2627        let capture_count = unsafe { ffi::ts_query_capture_count(ptr.0) };
2628        let pattern_count = unsafe { ffi::ts_query_pattern_count(ptr.0) as usize };
2629
2630        let mut capture_names = Vec::with_capacity(capture_count as usize);
2631        let mut capture_quantifiers_vec = Vec::with_capacity(pattern_count);
2632        let mut text_predicates_vec = Vec::with_capacity(pattern_count);
2633        let mut property_predicates_vec = Vec::with_capacity(pattern_count);
2634        let mut property_settings_vec = Vec::with_capacity(pattern_count);
2635        let mut general_predicates_vec = Vec::with_capacity(pattern_count);
2636
2637        // Build a vector of strings to store the capture names.
2638        for i in 0..capture_count {
2639            unsafe {
2640                let mut length = 0u32;
2641                let name =
2642                    ffi::ts_query_capture_name_for_id(ptr.0, i, core::ptr::addr_of_mut!(length))
2643                        .cast::<u8>();
2644                let name = slice::from_raw_parts(name, length as usize);
2645                let name = str::from_utf8_unchecked(name);
2646                capture_names.push(name);
2647            }
2648        }
2649
2650        // Build a vector to store capture quantifiers.
2651        for i in 0..pattern_count {
2652            let mut capture_quantifiers = Vec::with_capacity(capture_count as usize);
2653            for j in 0..capture_count {
2654                unsafe {
2655                    let quantifier = ffi::ts_query_capture_quantifier_for_id(ptr.0, i as u32, j);
2656                    capture_quantifiers.push(quantifier.into());
2657                }
2658            }
2659            capture_quantifiers_vec.push(capture_quantifiers.into());
2660        }
2661
2662        // Build a vector of strings to represent literal values used in predicates.
2663        let string_values = (0..string_count)
2664            .map(|i| unsafe {
2665                let mut length = 0u32;
2666                let value =
2667                    ffi::ts_query_string_value_for_id(ptr.0, i, core::ptr::addr_of_mut!(length))
2668                        .cast::<u8>();
2669                let value = slice::from_raw_parts(value, length as usize);
2670                str::from_utf8_unchecked(value)
2671            })
2672            .collect::<Vec<_>>();
2673
2674        // Build a vector of predicates for each pattern.
2675        for i in 0..pattern_count {
2676            let predicate_steps = unsafe {
2677                let mut length = 0u32;
2678                let raw_predicates = ffi::ts_query_predicates_for_pattern(
2679                    ptr.0,
2680                    i as u32,
2681                    core::ptr::addr_of_mut!(length),
2682                );
2683                if length > 0 {
2684                    slice::from_raw_parts(raw_predicates, length as usize)
2685                } else {
2686                    Default::default()
2687                }
2688            };
2689
2690            let byte_offset = unsafe { ffi::ts_query_start_byte_for_pattern(ptr.0, i as u32) };
2691            let row = source
2692                .char_indices()
2693                .take_while(|(i, _)| *i < byte_offset as usize)
2694                .filter(|(_, c)| *c == '\n')
2695                .count();
2696
2697            use ffi::TSQueryPredicateStepType as T;
2698            const TYPE_DONE: T = ffi::TSQueryPredicateStepTypeDone;
2699            const TYPE_CAPTURE: T = ffi::TSQueryPredicateStepTypeCapture;
2700            const TYPE_STRING: T = ffi::TSQueryPredicateStepTypeString;
2701
2702            let mut text_predicates = Vec::new();
2703            let mut property_predicates = Vec::new();
2704            let mut property_settings = Vec::new();
2705            let mut general_predicates = Vec::new();
2706            for p in predicate_steps.split(|s| s.type_ == TYPE_DONE) {
2707                if p.is_empty() {
2708                    continue;
2709                }
2710
2711                if p[0].type_ != TYPE_STRING {
2712                    return Err(predicate_error(
2713                        row,
2714                        format!(
2715                            "Expected predicate to start with a function name. Got @{}.",
2716                            capture_names[p[0].value_id as usize],
2717                        ),
2718                    ));
2719                }
2720
2721                // Build a predicate for each of the known predicate function names.
2722                let operator_name = string_values[p[0].value_id as usize];
2723                match operator_name {
2724                    "eq?" | "not-eq?" | "any-eq?" | "any-not-eq?" => {
2725                        if p.len() != 3 {
2726                            return Err(predicate_error(
2727                                row,
2728                                format!(
2729                                    "Wrong number of arguments to #eq? predicate. Expected 2, got {}.",
2730                                    p.len() - 1
2731                                ),
2732                            ));
2733                        }
2734                        if p[1].type_ != TYPE_CAPTURE {
2735                            return Err(predicate_error(
2736                                row,
2737                                format!(
2738                                    "First argument to #eq? predicate must be a capture name. Got literal \"{}\".",
2739                                    string_values[p[1].value_id as usize],
2740                                ),
2741                            ));
2742                        }
2743
2744                        let is_positive = operator_name == "eq?" || operator_name == "any-eq?";
2745                        let match_all = match operator_name {
2746                            "eq?" | "not-eq?" => true,
2747                            "any-eq?" | "any-not-eq?" => false,
2748                            _ => unreachable!(),
2749                        };
2750                        text_predicates.push(if p[2].type_ == TYPE_CAPTURE {
2751                            TextPredicateCapture::EqCapture(
2752                                p[1].value_id,
2753                                p[2].value_id,
2754                                is_positive,
2755                                match_all,
2756                            )
2757                        } else {
2758                            TextPredicateCapture::EqString(
2759                                p[1].value_id,
2760                                string_values[p[2].value_id as usize].to_string().into(),
2761                                is_positive,
2762                                match_all,
2763                            )
2764                        });
2765                    }
2766
2767                    "match?" | "not-match?" | "any-match?" | "any-not-match?" => {
2768                        if p.len() != 3 {
2769                            return Err(predicate_error(
2770                                row,
2771                                format!(
2772                                    "Wrong number of arguments to #match? predicate. Expected 2, got {}.",
2773                                    p.len() - 1
2774                                ),
2775                            ));
2776                        }
2777                        if p[1].type_ != TYPE_CAPTURE {
2778                            return Err(predicate_error(
2779                                row,
2780                                format!(
2781                                    "First argument to #match? predicate must be a capture name. Got literal \"{}\".",
2782                                    string_values[p[1].value_id as usize],
2783                                ),
2784                            ));
2785                        }
2786                        if p[2].type_ == TYPE_CAPTURE {
2787                            return Err(predicate_error(
2788                                row,
2789                                format!(
2790                                    "Second argument to #match? predicate must be a literal. Got capture @{}.",
2791                                    capture_names[p[2].value_id as usize],
2792                                ),
2793                            ));
2794                        }
2795
2796                        let is_positive =
2797                            operator_name == "match?" || operator_name == "any-match?";
2798                        let match_all = match operator_name {
2799                            "match?" | "not-match?" => true,
2800                            "any-match?" | "any-not-match?" => false,
2801                            _ => unreachable!(),
2802                        };
2803                        let regex = &string_values[p[2].value_id as usize];
2804                        text_predicates.push(TextPredicateCapture::MatchString(
2805                            p[1].value_id,
2806                            regex::bytes::Regex::new(regex).map_err(|_| {
2807                                predicate_error(row, format!("Invalid regex '{regex}'"))
2808                            })?,
2809                            is_positive,
2810                            match_all,
2811                        ));
2812                    }
2813
2814                    "set!" => property_settings.push(Self::parse_property(
2815                        row,
2816                        operator_name,
2817                        &capture_names,
2818                        &string_values,
2819                        &p[1..],
2820                    )?),
2821
2822                    "is?" | "is-not?" => property_predicates.push((
2823                        Self::parse_property(
2824                            row,
2825                            operator_name,
2826                            &capture_names,
2827                            &string_values,
2828                            &p[1..],
2829                        )?,
2830                        operator_name == "is?",
2831                    )),
2832
2833                    "any-of?" | "not-any-of?" => {
2834                        if p.len() < 2 {
2835                            return Err(predicate_error(
2836                                row,
2837                                format!(
2838                                    "Wrong number of arguments to #any-of? predicate. Expected at least 1, got {}.",
2839                                    p.len() - 1
2840                                ),
2841                            ));
2842                        }
2843                        if p[1].type_ != TYPE_CAPTURE {
2844                            return Err(predicate_error(
2845                                row,
2846                                format!(
2847                                    "First argument to #any-of? predicate must be a capture name. Got literal \"{}\".",
2848                                    string_values[p[1].value_id as usize],
2849                                ),
2850                            ));
2851                        }
2852
2853                        let is_positive = operator_name == "any-of?";
2854                        let mut values = Vec::new();
2855                        for arg in &p[2..] {
2856                            if arg.type_ == TYPE_CAPTURE {
2857                                return Err(predicate_error(
2858                                    row,
2859                                    format!(
2860                                        "Arguments to #any-of? predicate must be literals. Got capture @{}.",
2861                                        capture_names[arg.value_id as usize],
2862                                    ),
2863                                ));
2864                            }
2865                            values.push(string_values[arg.value_id as usize]);
2866                        }
2867                        text_predicates.push(TextPredicateCapture::AnyString(
2868                            p[1].value_id,
2869                            values
2870                                .iter()
2871                                .map(|x| (*x).to_string().into())
2872                                .collect::<Vec<_>>()
2873                                .into(),
2874                            is_positive,
2875                        ));
2876                    }
2877
2878                    _ => general_predicates.push(QueryPredicate {
2879                        operator: operator_name.to_string().into(),
2880                        args: p[1..]
2881                            .iter()
2882                            .map(|a| {
2883                                if a.type_ == TYPE_CAPTURE {
2884                                    QueryPredicateArg::Capture(a.value_id)
2885                                } else {
2886                                    QueryPredicateArg::String(
2887                                        string_values[a.value_id as usize].to_string().into(),
2888                                    )
2889                                }
2890                            })
2891                            .collect(),
2892                    }),
2893                }
2894            }
2895
2896            text_predicates_vec.push(text_predicates.into());
2897            property_predicates_vec.push(property_predicates.into());
2898            property_settings_vec.push(property_settings.into());
2899            general_predicates_vec.push(general_predicates.into());
2900        }
2901
2902        let result = Self {
2903            ptr: unsafe { NonNull::new_unchecked(ptr.0) },
2904            capture_names: capture_names.into(),
2905            capture_quantifiers: capture_quantifiers_vec.into(),
2906            text_predicates: text_predicates_vec.into(),
2907            property_predicates: property_predicates_vec.into(),
2908            property_settings: property_settings_vec.into(),
2909            general_predicates: general_predicates_vec.into(),
2910        };
2911
2912        core::mem::forget(ptr);
2913
2914        Ok(result)
2915    }
2916
2917    /// Get the byte offset where the given pattern starts in the query's
2918    /// source.
2919    #[doc(alias = "ts_query_start_byte_for_pattern")]
2920    #[must_use]
2921    pub fn start_byte_for_pattern(&self, pattern_index: usize) -> usize {
2922        assert!(
2923            pattern_index < self.text_predicates.len(),
2924            "Pattern index is {pattern_index} but the pattern count is {}",
2925            self.text_predicates.len(),
2926        );
2927        unsafe {
2928            ffi::ts_query_start_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize
2929        }
2930    }
2931
2932    /// Get the byte offset where the given pattern ends in the query's
2933    /// source.
2934    #[doc(alias = "ts_query_end_byte_for_pattern")]
2935    #[must_use]
2936    pub fn end_byte_for_pattern(&self, pattern_index: usize) -> usize {
2937        assert!(
2938            pattern_index < self.text_predicates.len(),
2939            "Pattern index is {pattern_index} but the pattern count is {}",
2940            self.text_predicates.len(),
2941        );
2942        unsafe {
2943            ffi::ts_query_end_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize
2944        }
2945    }
2946
2947    /// Get the number of patterns in the query.
2948    #[doc(alias = "ts_query_pattern_count")]
2949    #[must_use]
2950    pub fn pattern_count(&self) -> usize {
2951        unsafe { ffi::ts_query_pattern_count(self.ptr.as_ptr()) as usize }
2952    }
2953
2954    /// Get the names of the captures used in the query.
2955    #[must_use]
2956    pub const fn capture_names(&self) -> &[&str] {
2957        &self.capture_names
2958    }
2959
2960    /// Get the quantifiers of the captures used in the query.
2961    #[must_use]
2962    pub const fn capture_quantifiers(&self, index: usize) -> &[CaptureQuantifier] {
2963        &self.capture_quantifiers[index]
2964    }
2965
2966    /// Get the index for a given capture name.
2967    #[must_use]
2968    pub fn capture_index_for_name(&self, name: &str) -> Option<u32> {
2969        self.capture_names
2970            .iter()
2971            .position(|n| *n == name)
2972            .map(|ix| ix as u32)
2973    }
2974
2975    /// Get the properties that are checked for the given pattern index.
2976    ///
2977    /// This includes predicates with the operators `is?` and `is-not?`.
2978    #[must_use]
2979    pub const fn property_predicates(&self, index: usize) -> &[(QueryProperty, bool)] {
2980        &self.property_predicates[index]
2981    }
2982
2983    /// Get the properties that are set for the given pattern index.
2984    ///
2985    /// This includes predicates with the operator `set!`.
2986    #[must_use]
2987    pub const fn property_settings(&self, index: usize) -> &[QueryProperty] {
2988        &self.property_settings[index]
2989    }
2990
2991    /// Get the other user-defined predicates associated with the given index.
2992    ///
2993    /// This includes predicate with operators other than:
2994    /// * `match?`
2995    /// * `eq?` and `not-eq?`
2996    /// * `is?` and `is-not?`
2997    /// * `set!`
2998    #[must_use]
2999    pub const fn general_predicates(&self, index: usize) -> &[QueryPredicate] {
3000        &self.general_predicates[index]
3001    }
3002
3003    /// Disable a certain capture within a query.
3004    ///
3005    /// This prevents the capture from being returned in matches, and also
3006    /// avoids any resource usage associated with recording the capture.
3007    #[doc(alias = "ts_query_disable_capture")]
3008    pub fn disable_capture(&mut self, name: &str) {
3009        unsafe {
3010            ffi::ts_query_disable_capture(
3011                self.ptr.as_ptr(),
3012                name.as_bytes().as_ptr().cast::<c_char>(),
3013                name.len() as u32,
3014            );
3015        }
3016    }
3017
3018    /// Disable a certain pattern within a query.
3019    ///
3020    /// This prevents the pattern from matching, and also avoids any resource
3021    /// usage associated with the pattern.
3022    #[doc(alias = "ts_query_disable_pattern")]
3023    pub fn disable_pattern(&mut self, index: usize) {
3024        unsafe { ffi::ts_query_disable_pattern(self.ptr.as_ptr(), index as u32) }
3025    }
3026
3027    /// Create a deep copy of this query.
3028    ///
3029    /// Queries are shareable across threads and cursors without cloning. You
3030    /// should only need this when you want an independent copy to mutate (e.g.
3031    /// via [`disable_capture`][Query::disable_capture] or
3032    /// [`disable_pattern`][Query::disable_pattern]).
3033    #[doc(alias = "ts_query_copy")]
3034    #[must_use]
3035    pub fn deep_clone(&self) -> Self {
3036        let ptr = unsafe { ffi::ts_query_copy(self.ptr.as_ptr()) };
3037        // SAFETY: from_raw_parts re-derives all Rust-side fields from the C
3038        // object. The source string is only used for predicate error row
3039        // numbers. Since this is a copy of an already-valid query, it cannot
3040        // return an error.
3041        unsafe { Self::from_raw_parts(ptr, "").unwrap_unchecked() }
3042    }
3043
3044    /// Check if a given pattern within a query has a single root node.
3045    #[doc(alias = "ts_query_is_pattern_rooted")]
3046    #[must_use]
3047    pub fn is_pattern_rooted(&self, index: usize) -> bool {
3048        unsafe { ffi::ts_query_is_pattern_rooted(self.ptr.as_ptr(), index as u32) }
3049    }
3050
3051    /// Check if a given pattern within a query has a single root node.
3052    #[doc(alias = "ts_query_is_pattern_non_local")]
3053    #[must_use]
3054    pub fn is_pattern_non_local(&self, index: usize) -> bool {
3055        unsafe { ffi::ts_query_is_pattern_non_local(self.ptr.as_ptr(), index as u32) }
3056    }
3057
3058    /// Check if a given step in a query is 'definite'.
3059    ///
3060    /// A query step is 'definite' if its parent pattern will be guaranteed to
3061    /// match successfully once it reaches the step.
3062    #[doc(alias = "ts_query_is_pattern_guaranteed_at_step")]
3063    #[must_use]
3064    pub fn is_pattern_guaranteed_at_step(&self, byte_offset: usize) -> bool {
3065        unsafe {
3066            ffi::ts_query_is_pattern_guaranteed_at_step(self.ptr.as_ptr(), byte_offset as u32)
3067        }
3068    }
3069
3070    fn parse_property(
3071        row: usize,
3072        function_name: &str,
3073        capture_names: &[&str],
3074        string_values: &[&str],
3075        args: &[ffi::TSQueryPredicateStep],
3076    ) -> Result<QueryProperty, QueryError> {
3077        if args.is_empty() || args.len() > 3 {
3078            return Err(predicate_error(
3079                row,
3080                format!(
3081                    "Wrong number of arguments to {function_name} predicate. Expected 1 to 3, got {}.",
3082                    args.len(),
3083                ),
3084            ));
3085        }
3086
3087        let mut capture_id = None;
3088        let mut key = None;
3089        let mut value = None;
3090
3091        for arg in args {
3092            if arg.type_ == ffi::TSQueryPredicateStepTypeCapture {
3093                if capture_id.is_some() {
3094                    return Err(predicate_error(
3095                        row,
3096                        format!(
3097                            "Invalid arguments to {function_name} predicate. Unexpected second capture name @{}",
3098                            capture_names[arg.value_id as usize]
3099                        ),
3100                    ));
3101                }
3102                capture_id = Some(arg.value_id as usize);
3103            } else if key.is_none() {
3104                key = Some(&string_values[arg.value_id as usize]);
3105            } else if value.is_none() {
3106                value = Some(string_values[arg.value_id as usize]);
3107            } else {
3108                return Err(predicate_error(
3109                    row,
3110                    format!(
3111                        "Invalid arguments to {function_name} predicate. Unexpected third argument @{}",
3112                        string_values[arg.value_id as usize]
3113                    ),
3114                ));
3115            }
3116        }
3117
3118        if let Some(key) = key {
3119            Ok(QueryProperty::new(key, value, capture_id))
3120        } else {
3121            Err(predicate_error(
3122                row,
3123                format!("Invalid arguments to {function_name} predicate. Missing key argument"),
3124            ))
3125        }
3126    }
3127}
3128
3129impl Default for QueryCursor {
3130    fn default() -> Self {
3131        Self::new()
3132    }
3133}
3134
3135impl QueryCursor {
3136    /// Create a new cursor for executing a given query.
3137    ///
3138    /// The cursor stores the state that is needed to iteratively search for
3139    /// matches.
3140    #[doc(alias = "ts_query_cursor_new")]
3141    #[must_use]
3142    pub fn new() -> Self {
3143        Self {
3144            ptr: unsafe { NonNull::new_unchecked(ffi::ts_query_cursor_new()) },
3145        }
3146    }
3147
3148    /// Return the maximum number of in-progress matches for this cursor.
3149    #[doc(alias = "ts_query_cursor_match_limit")]
3150    #[must_use]
3151    pub fn match_limit(&self) -> u32 {
3152        unsafe { ffi::ts_query_cursor_match_limit(self.ptr.as_ptr()) }
3153    }
3154
3155    /// Set the maximum number of in-progress matches for this cursor.  The
3156    /// limit must be > 0 and <= 65536.
3157    #[doc(alias = "ts_query_cursor_set_match_limit")]
3158    pub fn set_match_limit(&mut self, limit: u32) {
3159        unsafe {
3160            ffi::ts_query_cursor_set_match_limit(self.ptr.as_ptr(), limit);
3161        }
3162    }
3163
3164    /// Check if, on its last execution, this cursor exceeded its maximum number
3165    /// of in-progress matches.
3166    #[doc(alias = "ts_query_cursor_did_exceed_match_limit")]
3167    #[must_use]
3168    pub fn did_exceed_match_limit(&self) -> bool {
3169        unsafe { ffi::ts_query_cursor_did_exceed_match_limit(self.ptr.as_ptr()) }
3170    }
3171
3172    /// Iterate over all of the matches in the order that they were found.
3173    ///
3174    /// Each match contains the index of the pattern that matched, and a list of
3175    /// captures. Because multiple patterns can match the same set of nodes,
3176    /// one match may contain captures that appear *before* some of the
3177    /// captures from a previous match.
3178    ///
3179    /// Iterating over a `QueryMatches` object requires the `StreamingIterator`
3180    /// or `StreamingIteratorMut` trait to be in scope. This can be done via
3181    /// `use tree_sitter::StreamingIterator` or `use tree_sitter::StreamingIteratorMut`
3182    #[doc(alias = "ts_query_cursor_exec")]
3183    pub fn matches<'query, 'cursor: 'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>>(
3184        &'cursor mut self,
3185        query: &'query Query,
3186        node: Node<'tree>,
3187        text_provider: T,
3188    ) -> QueryMatches<'query, 'tree, 'static, T, I> {
3189        let ptr = self.ptr.as_ptr();
3190        unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) };
3191        QueryMatches {
3192            ptr,
3193            query,
3194            text_provider,
3195            buffer1: Vec::default(),
3196            buffer2: Vec::default(),
3197            current_match: None,
3198            _options: None,
3199            _phantom: PhantomData,
3200        }
3201    }
3202
3203    /// Iterate over all of the matches in the order that they were found, with options.
3204    ///
3205    /// Each match contains the index of the pattern that matched, and a list of
3206    /// captures. Because multiple patterns can match the same set of nodes,
3207    /// one match may contain captures that appear *before* some of the
3208    /// captures from a previous match.
3209    #[doc(alias = "ts_query_cursor_exec_with_options")]
3210    pub fn matches_with_options<
3211        'query,
3212        'cursor: 'query,
3213        'tree,
3214        'options,
3215        T: TextProvider<I>,
3216        I: AsRef<[u8]>,
3217    >(
3218        &'cursor mut self,
3219        query: &'query Query,
3220        node: Node<'tree>,
3221        text_provider: T,
3222        options: QueryCursorOptions<'options>,
3223    ) -> QueryMatches<'query, 'tree, 'options, T, I> {
3224        unsafe extern "C" fn progress(state: *mut ffi::TSQueryCursorState) -> bool {
3225            unsafe {
3226                let callback = (*state)
3227                    .payload
3228                    .cast::<QueryProgressCallback>()
3229                    .as_mut()
3230                    .unwrap();
3231                match callback(&QueryCursorState::from_raw(state)) {
3232                    ControlFlow::Continue(()) => false,
3233                    ControlFlow::Break(()) => true,
3234                }
3235            }
3236        }
3237
3238        let query_options = options.progress_callback.map(|cb| {
3239            QueryCursorOptionsDrop(
3240                Box::into_raw(Box::new(ffi::TSQueryCursorOptions {
3241                    payload: Box::into_raw(Box::new(cb)).cast::<c_void>(),
3242                    progress_callback: Some(progress),
3243                })),
3244                PhantomData,
3245            )
3246        });
3247
3248        let ptr = self.ptr.as_ptr();
3249        unsafe {
3250            ffi::ts_query_cursor_exec_with_options(
3251                ptr,
3252                query.ptr.as_ptr(),
3253                node.0,
3254                query_options.as_ref().map_or(ptr::null_mut(), |q| q.0),
3255            );
3256        }
3257        QueryMatches {
3258            ptr,
3259            query,
3260            text_provider,
3261            buffer1: Vec::default(),
3262            buffer2: Vec::default(),
3263            current_match: None,
3264            _options: query_options,
3265            _phantom: PhantomData,
3266        }
3267    }
3268
3269    /// Iterate over all of the individual captures in the order that they
3270    /// appear.
3271    ///
3272    /// This is useful if you don't care about which pattern matched, and just
3273    /// want a single, ordered sequence of captures.
3274    ///
3275    /// Iterating over a `QueryCaptures` object requires the `StreamingIterator`
3276    /// or `StreamingIteratorMut` trait to be in scope. This can be done via
3277    /// `use tree_sitter::StreamingIterator` or `use tree_sitter::StreamingIteratorMut`
3278    #[doc(alias = "ts_query_cursor_exec")]
3279    pub fn captures<'query, 'cursor: 'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>>(
3280        &'cursor mut self,
3281        query: &'query Query,
3282        node: Node<'tree>,
3283        text_provider: T,
3284    ) -> QueryCaptures<'query, 'tree, 'static, T, I> {
3285        let ptr = self.ptr.as_ptr();
3286        unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) };
3287        QueryCaptures {
3288            ptr,
3289            query,
3290            text_provider,
3291            buffer1: Vec::default(),
3292            buffer2: Vec::default(),
3293            current_match: None,
3294            _options: None,
3295            _phantom: PhantomData,
3296        }
3297    }
3298
3299    /// Iterate over all of the individual captures in the order that they
3300    /// appear, with options.
3301    ///
3302    /// This is useful if you don't care about which pattern matched, and just
3303    /// want a single, ordered sequence of captures.
3304    #[doc(alias = "ts_query_cursor_exec")]
3305    pub fn captures_with_options<
3306        'query,
3307        'cursor: 'query,
3308        'tree,
3309        'options,
3310        T: TextProvider<I>,
3311        I: AsRef<[u8]>,
3312    >(
3313        &'cursor mut self,
3314        query: &'query Query,
3315        node: Node<'tree>,
3316        text_provider: T,
3317        options: QueryCursorOptions<'options>,
3318    ) -> QueryCaptures<'query, 'tree, 'options, T, I> {
3319        unsafe extern "C" fn progress(state: *mut ffi::TSQueryCursorState) -> bool {
3320            unsafe {
3321                let callback = (*state)
3322                    .payload
3323                    .cast::<QueryProgressCallback>()
3324                    .as_mut()
3325                    .unwrap();
3326                match callback(&QueryCursorState::from_raw(state)) {
3327                    ControlFlow::Continue(()) => false,
3328                    ControlFlow::Break(()) => true,
3329                }
3330            }
3331        }
3332
3333        let query_options = options.progress_callback.map(|cb| {
3334            QueryCursorOptionsDrop(
3335                Box::into_raw(Box::new(ffi::TSQueryCursorOptions {
3336                    payload: Box::into_raw(Box::new(cb)).cast::<c_void>(),
3337                    progress_callback: Some(progress),
3338                })),
3339                PhantomData,
3340            )
3341        });
3342
3343        let ptr = self.ptr.as_ptr();
3344        unsafe {
3345            ffi::ts_query_cursor_exec_with_options(
3346                ptr,
3347                query.ptr.as_ptr(),
3348                node.0,
3349                query_options.as_ref().map_or(ptr::null_mut(), |q| q.0),
3350            );
3351        }
3352        QueryCaptures {
3353            ptr,
3354            query,
3355            text_provider,
3356            buffer1: Vec::default(),
3357            buffer2: Vec::default(),
3358            current_match: None,
3359            _options: query_options,
3360            _phantom: PhantomData,
3361        }
3362    }
3363
3364    /// Set the range in which the query will be executed, in terms of byte
3365    /// offsets.
3366    #[doc(alias = "ts_query_cursor_set_byte_range")]
3367    pub fn set_byte_range(&mut self, range: ops::Range<usize>) -> &mut Self {
3368        unsafe {
3369            ffi::ts_query_cursor_set_byte_range(
3370                self.ptr.as_ptr(),
3371                range.start as u32,
3372                range.end as u32,
3373            );
3374        }
3375        self
3376    }
3377
3378    /// Set the range in which the query will be executed, in terms of rows and
3379    /// columns.
3380    #[doc(alias = "ts_query_cursor_set_point_range")]
3381    pub fn set_point_range(&mut self, range: ops::Range<Point>) -> &mut Self {
3382        unsafe {
3383            ffi::ts_query_cursor_set_point_range(
3384                self.ptr.as_ptr(),
3385                range.start.into(),
3386                range.end.into(),
3387            );
3388        }
3389        self
3390    }
3391
3392    /// Set the byte range within which all matches must be fully contained.
3393    ///
3394    /// Set the range of bytes in which matches will be searched for. In contrast to
3395    /// `ts_query_cursor_set_byte_range`, this will restrict the query cursor to only return
3396    /// matches where _all_ nodes are _fully_ contained within the given range. Both functions
3397    /// can be used together, e.g. to search for any matches that intersect line 5000, as
3398    /// long as they are fully contained within lines 4500-5500
3399    #[doc(alias = "ts_query_cursor_set_containing_byte_range")]
3400    pub fn set_containing_byte_range(&mut self, range: ops::Range<usize>) -> &mut Self {
3401        unsafe {
3402            ffi::ts_query_cursor_set_containing_byte_range(
3403                self.ptr.as_ptr(),
3404                range.start as u32,
3405                range.end as u32,
3406            );
3407        }
3408        self
3409    }
3410
3411    /// Set the point range within which all matches must be fully contained.
3412    ///
3413    /// Set the range of bytes in which matches will be searched for. In contrast to
3414    /// `ts_query_cursor_set_point_range`, this will restrict the query cursor to only return
3415    /// matches where _all_ nodes are _fully_ contained within the given range. Both functions
3416    /// can be used together, e.g. to search for any matches that intersect line 5000, as
3417    /// long as they are fully contained within lines 4500-5500
3418    #[doc(alias = "ts_query_cursor_set_containing_point_range")]
3419    pub fn set_containing_point_range(&mut self, range: ops::Range<Point>) -> &mut Self {
3420        unsafe {
3421            ffi::ts_query_cursor_set_containing_point_range(
3422                self.ptr.as_ptr(),
3423                range.start.into(),
3424                range.end.into(),
3425            );
3426        }
3427        self
3428    }
3429
3430    /// Set the maximum start depth for a query cursor.
3431    ///
3432    /// This prevents cursors from exploring children nodes at a certain depth.
3433    /// Note if a pattern includes many children, then they will still be
3434    /// checked.
3435    ///
3436    /// The zero max start depth value can be used as a special behavior and
3437    /// it helps to destructure a subtree by staying on a node and using
3438    /// captures for interested parts. Note that the zero max start depth
3439    /// only limits a search depth for a pattern's root node but other nodes
3440    /// that are parts of the pattern may be searched at any depth depending on
3441    /// what is defined by the pattern structure.
3442    ///
3443    /// Set to `None` to remove the maximum start depth.
3444    #[doc(alias = "ts_query_cursor_set_max_start_depth")]
3445    pub fn set_max_start_depth(&mut self, max_start_depth: Option<u32>) -> &mut Self {
3446        unsafe {
3447            ffi::ts_query_cursor_set_max_start_depth(
3448                self.ptr.as_ptr(),
3449                max_start_depth.unwrap_or(u32::MAX),
3450            );
3451        }
3452        self
3453    }
3454}
3455
3456impl<'tree> QueryMatch<'_, 'tree> {
3457    #[must_use]
3458    pub const fn id(&self) -> u32 {
3459        self.id
3460    }
3461
3462    #[must_use]
3463    pub const fn captures(&self) -> &[QueryCapture<'tree>] {
3464        self.captures
3465    }
3466
3467    #[doc(alias = "ts_query_cursor_remove_match")]
3468    pub fn remove(&self) {
3469        unsafe { ffi::ts_query_cursor_remove_match(self.cursor, self.id) }
3470    }
3471
3472    pub fn nodes_for_capture_index(
3473        &self,
3474        capture_ix: u32,
3475    ) -> impl Iterator<Item = Node<'tree>> + '_ {
3476        self.captures
3477            .iter()
3478            .filter_map(move |capture| (capture.index == capture_ix).then_some(capture.node))
3479    }
3480
3481    fn new(m: &ffi::TSQueryMatch, cursor: *mut ffi::TSQueryCursor) -> Self {
3482        QueryMatch {
3483            cursor,
3484            id: m.id,
3485            pattern_index: m.pattern_index as usize,
3486            captures: if m.capture_count > 0 {
3487                unsafe {
3488                    slice::from_raw_parts(
3489                        m.captures.cast::<QueryCapture<'tree>>(),
3490                        m.capture_count as usize,
3491                    )
3492                }
3493            } else {
3494                Default::default()
3495            },
3496        }
3497    }
3498
3499    pub fn satisfies_text_predicates<I: AsRef<[u8]>>(
3500        &self,
3501        query: &Query,
3502        buffer1: &mut Vec<u8>,
3503        buffer2: &mut Vec<u8>,
3504        text_provider: &mut impl TextProvider<I>,
3505    ) -> bool {
3506        struct NodeText<'a, T> {
3507            buffer: &'a mut Vec<u8>,
3508            first_chunk: Option<T>,
3509        }
3510        impl<'a, T: AsRef<[u8]>> NodeText<'a, T> {
3511            const fn new(buffer: &'a mut Vec<u8>) -> Self {
3512                Self {
3513                    buffer,
3514                    first_chunk: None,
3515                }
3516            }
3517
3518            fn get_text(&mut self, chunks: &mut impl Iterator<Item = T>) -> &[u8] {
3519                self.first_chunk = chunks.next();
3520                if let Some(next_chunk) = chunks.next() {
3521                    self.buffer.clear();
3522                    self.buffer
3523                        .extend_from_slice(self.first_chunk.as_ref().unwrap().as_ref());
3524                    self.buffer.extend_from_slice(next_chunk.as_ref());
3525                    for chunk in chunks {
3526                        self.buffer.extend_from_slice(chunk.as_ref());
3527                    }
3528                    self.buffer.as_slice()
3529                } else if let Some(ref first_chunk) = self.first_chunk {
3530                    first_chunk.as_ref()
3531                } else {
3532                    &[]
3533                }
3534            }
3535        }
3536
3537        let mut node_text1 = NodeText::new(buffer1);
3538        let mut node_text2 = NodeText::new(buffer2);
3539
3540        query.text_predicates[self.pattern_index]
3541            .iter()
3542            .all(|predicate| match predicate {
3543                TextPredicateCapture::EqCapture(i, j, is_positive, match_all_nodes) => {
3544                    let mut nodes_1 = self.nodes_for_capture_index(*i).peekable();
3545                    let mut nodes_2 = self.nodes_for_capture_index(*j).peekable();
3546                    while nodes_1.peek().is_some() && nodes_2.peek().is_some() {
3547                        let node1 = nodes_1.next().unwrap();
3548                        let node2 = nodes_2.next().unwrap();
3549                        let mut text1 = text_provider.text(node1);
3550                        let mut text2 = text_provider.text(node2);
3551                        let text1 = node_text1.get_text(&mut text1);
3552                        let text2 = node_text2.get_text(&mut text2);
3553                        let is_positive_match = text1 == text2;
3554                        if is_positive_match != *is_positive && *match_all_nodes {
3555                            return false;
3556                        }
3557                        if is_positive_match == *is_positive && !*match_all_nodes {
3558                            return true;
3559                        }
3560                    }
3561                    nodes_1.next().is_none() && nodes_2.next().is_none()
3562                }
3563                TextPredicateCapture::EqString(i, s, is_positive, match_all_nodes) => {
3564                    let nodes = self.nodes_for_capture_index(*i);
3565                    for node in nodes {
3566                        let mut text = text_provider.text(node);
3567                        let text = node_text1.get_text(&mut text);
3568                        let is_positive_match = text == s.as_bytes();
3569                        if is_positive_match != *is_positive && *match_all_nodes {
3570                            return false;
3571                        }
3572                        if is_positive_match == *is_positive && !*match_all_nodes {
3573                            return true;
3574                        }
3575                    }
3576                    true
3577                }
3578                TextPredicateCapture::MatchString(i, r, is_positive, match_all_nodes) => {
3579                    let nodes = self.nodes_for_capture_index(*i);
3580                    for node in nodes {
3581                        let mut text = text_provider.text(node);
3582                        let text = node_text1.get_text(&mut text);
3583                        let is_positive_match = r.is_match(text);
3584                        if is_positive_match != *is_positive && *match_all_nodes {
3585                            return false;
3586                        }
3587                        if is_positive_match == *is_positive && !*match_all_nodes {
3588                            return true;
3589                        }
3590                    }
3591                    true
3592                }
3593                TextPredicateCapture::AnyString(i, v, is_positive) => {
3594                    let nodes = self.nodes_for_capture_index(*i);
3595                    for node in nodes {
3596                        let mut text = text_provider.text(node);
3597                        let text = node_text1.get_text(&mut text);
3598                        if (v.iter().any(|s| text == s.as_bytes())) != *is_positive {
3599                            return false;
3600                        }
3601                    }
3602                    true
3603                }
3604            })
3605    }
3606}
3607
3608impl QueryProperty {
3609    #[must_use]
3610    pub fn new(key: &str, value: Option<&str>, capture_id: Option<usize>) -> Self {
3611        Self {
3612            capture_id,
3613            key: key.to_string().into(),
3614            value: value.map(|s| s.to_string().into()),
3615        }
3616    }
3617}
3618
3619/// Provide a `StreamingIterator` instead of the traditional `Iterator`, as the
3620/// underlying object in the C library gets updated on each iteration. Copies would
3621/// have their internal state overwritten, leading to Undefined Behavior
3622impl<'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIterator
3623    for QueryMatches<'query, 'tree, '_, T, I>
3624{
3625    type Item = QueryMatch<'query, 'tree>;
3626
3627    fn advance(&mut self) {
3628        self.current_match = unsafe {
3629            loop {
3630                let mut m = MaybeUninit::<ffi::TSQueryMatch>::uninit();
3631                if ffi::ts_query_cursor_next_match(self.ptr, m.as_mut_ptr()) {
3632                    let result = QueryMatch::new(&m.assume_init(), self.ptr);
3633                    if result.satisfies_text_predicates(
3634                        self.query,
3635                        &mut self.buffer1,
3636                        &mut self.buffer2,
3637                        &mut self.text_provider,
3638                    ) {
3639                        break Some(result);
3640                    }
3641                } else {
3642                    break None;
3643                }
3644            }
3645        };
3646    }
3647
3648    fn get(&self) -> Option<&Self::Item> {
3649        self.current_match.as_ref()
3650    }
3651}
3652
3653impl<T: TextProvider<I>, I: AsRef<[u8]>> StreamingIteratorMut for QueryMatches<'_, '_, '_, T, I> {
3654    fn get_mut(&mut self) -> Option<&mut Self::Item> {
3655        self.current_match.as_mut()
3656    }
3657}
3658
3659impl<'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIterator
3660    for QueryCaptures<'query, 'tree, '_, T, I>
3661{
3662    type Item = (QueryMatch<'query, 'tree>, usize);
3663
3664    fn advance(&mut self) {
3665        self.current_match = unsafe {
3666            loop {
3667                let mut capture_index = 0u32;
3668                let mut m = MaybeUninit::<ffi::TSQueryMatch>::uninit();
3669                if ffi::ts_query_cursor_next_capture(
3670                    self.ptr,
3671                    m.as_mut_ptr(),
3672                    core::ptr::addr_of_mut!(capture_index),
3673                ) {
3674                    let result = QueryMatch::new(&m.assume_init(), self.ptr);
3675                    if result.satisfies_text_predicates(
3676                        self.query,
3677                        &mut self.buffer1,
3678                        &mut self.buffer2,
3679                        &mut self.text_provider,
3680                    ) {
3681                        break Some((result, capture_index as usize));
3682                    }
3683                    result.remove();
3684                } else {
3685                    break None;
3686                }
3687            }
3688        }
3689    }
3690
3691    fn get(&self) -> Option<&Self::Item> {
3692        self.current_match.as_ref()
3693    }
3694}
3695
3696impl<T: TextProvider<I>, I: AsRef<[u8]>> StreamingIteratorMut for QueryCaptures<'_, '_, '_, T, I> {
3697    fn get_mut(&mut self) -> Option<&mut Self::Item> {
3698        self.current_match.as_mut()
3699    }
3700}
3701
3702impl<T: TextProvider<I>, I: AsRef<[u8]>> QueryMatches<'_, '_, '_, T, I> {
3703    #[doc(alias = "ts_query_cursor_set_byte_range")]
3704    pub fn set_byte_range(&mut self, range: ops::Range<usize>) {
3705        unsafe {
3706            ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32);
3707        }
3708    }
3709
3710    #[doc(alias = "ts_query_cursor_set_point_range")]
3711    pub fn set_point_range(&mut self, range: ops::Range<Point>) {
3712        unsafe {
3713            ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into());
3714        }
3715    }
3716}
3717
3718impl<T: TextProvider<I>, I: AsRef<[u8]>> QueryCaptures<'_, '_, '_, T, I> {
3719    #[doc(alias = "ts_query_cursor_set_byte_range")]
3720    pub fn set_byte_range(&mut self, range: ops::Range<usize>) {
3721        unsafe {
3722            ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32);
3723        }
3724    }
3725
3726    #[doc(alias = "ts_query_cursor_set_point_range")]
3727    pub fn set_point_range(&mut self, range: ops::Range<Point>) {
3728        unsafe {
3729            ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into());
3730        }
3731    }
3732}
3733
3734impl fmt::Debug for QueryMatch<'_, '_> {
3735    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3736        write!(
3737            f,
3738            "QueryMatch {{ id: {}, pattern_index: {}, captures: {:?} }}",
3739            self.id, self.pattern_index, self.captures
3740        )
3741    }
3742}
3743
3744impl<F, R, I> TextProvider<I> for F
3745where
3746    F: FnMut(Node) -> R,
3747    R: Iterator<Item = I>,
3748    I: AsRef<[u8]>,
3749{
3750    type I = R;
3751
3752    fn text(&mut self, node: Node) -> Self::I {
3753        (self)(node)
3754    }
3755}
3756
3757impl<'a> TextProvider<&'a [u8]> for &'a [u8] {
3758    type I = iter::Once<&'a [u8]>;
3759
3760    fn text(&mut self, node: Node) -> Self::I {
3761        iter::once(&self[node.byte_range()])
3762    }
3763}
3764
3765impl PartialEq for Query {
3766    fn eq(&self, other: &Self) -> bool {
3767        self.ptr == other.ptr
3768    }
3769}
3770
3771impl Drop for Query {
3772    fn drop(&mut self) {
3773        unsafe { ffi::ts_query_delete(self.ptr.as_ptr()) }
3774    }
3775}
3776
3777impl Drop for QueryCursor {
3778    fn drop(&mut self) {
3779        unsafe { ffi::ts_query_cursor_delete(self.ptr.as_ptr()) }
3780    }
3781}
3782
3783impl Point {
3784    #[must_use]
3785    pub const fn new(row: usize, column: usize) -> Self {
3786        Self { row, column }
3787    }
3788}
3789
3790impl fmt::Display for Point {
3791    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3792        write!(f, "({}, {})", self.row, self.column)
3793    }
3794}
3795
3796impl From<Point> for ffi::TSPoint {
3797    fn from(val: Point) -> Self {
3798        Self {
3799            row: val.row as u32,
3800            column: val.column as u32,
3801        }
3802    }
3803}
3804
3805impl From<ffi::TSPoint> for Point {
3806    fn from(point: ffi::TSPoint) -> Self {
3807        Self {
3808            row: point.row as usize,
3809            column: point.column as usize,
3810        }
3811    }
3812}
3813
3814impl From<Range> for ffi::TSRange {
3815    fn from(val: Range) -> Self {
3816        Self {
3817            start_byte: val.start_byte as u32,
3818            end_byte: val.end_byte as u32,
3819            start_point: val.start_point.into(),
3820            end_point: val.end_point.into(),
3821        }
3822    }
3823}
3824
3825impl From<ffi::TSRange> for Range {
3826    fn from(range: ffi::TSRange) -> Self {
3827        Self {
3828            start_byte: range.start_byte as usize,
3829            end_byte: range.end_byte as usize,
3830            start_point: range.start_point.into(),
3831            end_point: range.end_point.into(),
3832        }
3833    }
3834}
3835
3836impl From<&InputEdit> for ffi::TSInputEdit {
3837    fn from(val: &InputEdit) -> Self {
3838        Self {
3839            start_byte: val.start_byte as u32,
3840            old_end_byte: val.old_end_byte as u32,
3841            new_end_byte: val.new_end_byte as u32,
3842            start_point: val.start_position.into(),
3843            old_end_point: val.old_end_position.into(),
3844            new_end_point: val.new_end_position.into(),
3845        }
3846    }
3847}
3848
3849impl<'a> LossyUtf8<'a> {
3850    #[must_use]
3851    pub const fn new(bytes: &'a [u8]) -> Self {
3852        LossyUtf8 {
3853            bytes,
3854            in_replacement: false,
3855        }
3856    }
3857}
3858
3859impl<'a> Iterator for LossyUtf8<'a> {
3860    type Item = &'a str;
3861
3862    fn next(&mut self) -> Option<&'a str> {
3863        if self.bytes.is_empty() {
3864            return None;
3865        }
3866        if self.in_replacement {
3867            self.in_replacement = false;
3868            return Some("\u{fffd}");
3869        }
3870        match core::str::from_utf8(self.bytes) {
3871            Ok(valid) => {
3872                self.bytes = &[];
3873                Some(valid)
3874            }
3875            Err(error) => {
3876                if let Some(error_len) = error.error_len() {
3877                    let error_start = error.valid_up_to();
3878                    if error_start > 0 {
3879                        let result =
3880                            unsafe { core::str::from_utf8_unchecked(&self.bytes[..error_start]) };
3881                        self.bytes = &self.bytes[(error_start + error_len)..];
3882                        self.in_replacement = true;
3883                        Some(result)
3884                    } else {
3885                        self.bytes = &self.bytes[error_len..];
3886                        Some("\u{fffd}")
3887                    }
3888                } else {
3889                    None
3890                }
3891            }
3892        }
3893    }
3894}
3895
3896#[must_use]
3897const fn predicate_error(row: usize, message: String) -> QueryError {
3898    QueryError {
3899        kind: QueryErrorKind::Predicate,
3900        row,
3901        column: 0,
3902        offset: 0,
3903        message,
3904    }
3905}
3906
3907impl fmt::Display for IncludedRangesError {
3908    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3909        write!(f, "Incorrect range by index: {}", self.0)
3910    }
3911}
3912
3913impl fmt::Display for LanguageError {
3914    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3915        match self {
3916            Self::Version(version) => {
3917                write!(
3918                    f,
3919                    "Incompatible language version {version:#x}. Expected {LANGUAGE_VERSION:#x}",
3920                )
3921            }
3922            Self::NotParseable => {
3923                write!(f, "Language cannot be used for parsing.")
3924            }
3925            #[cfg(feature = "wasm")]
3926            Self::Wasm => {
3927                write!(f, "Failed to load the Wasm store.")
3928            }
3929        }
3930    }
3931}
3932
3933impl fmt::Display for QueryError {
3934    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3935        let msg = match self.kind {
3936            QueryErrorKind::Field => "Invalid field name ",
3937            QueryErrorKind::NodeType => "Invalid node type ",
3938            QueryErrorKind::Capture => "Invalid capture name ",
3939            QueryErrorKind::Predicate => "Invalid predicate: ",
3940            QueryErrorKind::Structure => "Invalid pattern structure:\n",
3941            QueryErrorKind::Syntax => "Invalid syntax:\n",
3942            QueryErrorKind::Language => "",
3943        };
3944        if msg.is_empty() {
3945            write!(f, "{}", self.message)
3946        } else {
3947            write!(
3948                f,
3949                "Query error at {}:{}. {}{}",
3950                self.row + 1,
3951                self.column + 1,
3952                msg,
3953                self.message
3954            )
3955        }
3956    }
3957}
3958
3959#[doc(hidden)]
3960#[must_use]
3961pub fn format_sexp(sexp: &str, initial_indent_level: usize) -> String {
3962    let sexp = sexp.trim();
3963    let mut indent_level = initial_indent_level;
3964    let mut formatted = String::with_capacity(sexp.len());
3965    let mut has_field = false;
3966
3967    let mut c_iter = sexp.chars().peekable();
3968    let mut scratch = String::with_capacity(sexp.len());
3969    let mut quote = '\0';
3970    let mut saw_paren = false;
3971    let mut did_last = false;
3972    let mut first_token = true;
3973    let mut quote_suffixes = quote_suffix_minimum_depths(sexp);
3974    let mut byte_offset = 0;
3975
3976    let mut fetch_next_str = |next: &mut String, payload_quote: char, open_nodes: usize| {
3977        let root_token = first_token;
3978        first_token = false;
3979        let open_nodes = if root_token { 1 } else { open_nodes };
3980        next.clear();
3981        let mut separated = false;
3982        while let Some(c) = c_iter.next() {
3983            byte_offset += c.len_utf8();
3984            if quote != '\0' {
3985                // `to_sexp` does not escape quotes in anonymous MISSING names or
3986                // quoted UNEXPECTED characters, so their node boundary disambiguates
3987                // the delimiter. Named MISSING payloads are emitted without delimiters.
3988                if c == quote
3989                    && quote_closing_depth(c_iter.clone()).is_some_and(|depth| depth <= open_nodes)
3990                {
3991                    quote = '\0';
3992                }
3993            } else if next.is_empty() && c == payload_quote {
3994                let suffixes = &mut quote_suffixes[usize::from(c == '"')];
3995                while suffixes
3996                    .last()
3997                    .is_some_and(|&(offset, _)| offset < byte_offset)
3998                {
3999                    suffixes.pop();
4000                }
4001                if suffixes
4002                    .last()
4003                    .is_some_and(|&(_, depth)| depth <= open_nodes)
4004                {
4005                    quote = c;
4006                }
4007            } else if root_token
4008                && next == "("
4009                && c == '"'
4010                && sexp.len() > 3
4011                && sexp.ends_with("\")")
4012            {
4013                quote = c;
4014            } else if c == ' ' {
4015                separated = true;
4016                break;
4017            } else if c == ')' {
4018                saw_paren = true;
4019                break;
4020            }
4021            next.push(c);
4022        }
4023
4024        if c_iter.peek().is_none() && next.is_empty() {
4025            if saw_paren {
4026                saw_paren = false;
4027                return Some(false);
4028            }
4029            if !did_last {
4030                did_last = true;
4031                return Some(false);
4032            }
4033            return None;
4034        }
4035        let has_payload = separated
4036            && (next == "(MISSING" || next == "(UNEXPECTED")
4037            && c_iter.peek().is_some_and(|&c| c != '(' && c != ')')
4038            && !sexp_field_follows(c_iter.clone());
4039        Some(has_payload)
4040    };
4041
4042    while let Some(has_payload) = fetch_next_str(
4043        &mut scratch,
4044        '\0',
4045        indent_level.saturating_sub(initial_indent_level),
4046    ) {
4047        if scratch.is_empty() && indent_level > initial_indent_level {
4048            indent_level -= 1;
4049            write!(formatted, ")").unwrap();
4050        } else if scratch.starts_with('(') {
4051            if has_field {
4052                has_field = false;
4053            } else {
4054                if indent_level > 0 {
4055                    writeln!(formatted).unwrap();
4056                    for _ in 0..indent_level {
4057                        write!(formatted, "  ").unwrap();
4058                    }
4059                }
4060                indent_level += 1;
4061            }
4062
4063            write!(formatted, "{scratch}").unwrap();
4064
4065            if has_payload {
4066                let payload_quote = if scratch == "(UNEXPECTED" { '\'' } else { '"' };
4067                fetch_next_str(
4068                    &mut scratch,
4069                    payload_quote,
4070                    indent_level.saturating_sub(initial_indent_level),
4071                )
4072                .unwrap();
4073                if scratch.is_empty() {
4074                    while indent_level > initial_indent_level {
4075                        indent_level -= 1;
4076                        write!(formatted, ")").unwrap();
4077                    }
4078                } else {
4079                    write!(formatted, " {scratch}").unwrap();
4080                }
4081            }
4082        } else if scratch.ends_with(':') {
4083            writeln!(formatted).unwrap();
4084            for _ in 0..indent_level {
4085                write!(formatted, "  ").unwrap();
4086            }
4087            write!(formatted, "{scratch} ").unwrap();
4088            has_field = true;
4089            indent_level += 1;
4090        }
4091    }
4092
4093    formatted
4094}
4095
4096fn sexp_field_follows(mut chars: impl Iterator<Item = char>) -> bool {
4097    let mut last = None;
4098    for c in chars.by_ref() {
4099        match c {
4100            '(' | ')' | '\'' | '"' => return false,
4101            ' ' => break,
4102            _ => last = Some(c),
4103        }
4104    }
4105    last == Some(':') && chars.next() == Some('(')
4106}
4107
4108fn quote_suffix_minimum_depths(sexp: &str) -> [Vec<(usize, usize)>; 2] {
4109    let mut suffixes: [Vec<(usize, usize)>; 2] = [Vec::new(), Vec::new()];
4110    for (offset, c) in sexp.char_indices().rev() {
4111        if c != '\'' && c != '"' {
4112            continue;
4113        }
4114        if let Some(depth) = quote_closing_depth(sexp[offset + 1..].chars()) {
4115            let quotes = &mut suffixes[usize::from(c == '"')];
4116            // A later, shallower candidate answers the same existence query for longer.
4117            if quotes.last().is_none_or(|&(_, minimum)| depth < minimum) {
4118                quotes.push((offset, depth));
4119            }
4120        }
4121    }
4122    suffixes
4123}
4124
4125fn quote_closing_depth(mut chars: impl Iterator<Item = char>) -> Option<usize> {
4126    match chars.next() {
4127        None => Some(0),
4128        Some(')') => {
4129            let mut depth = 1;
4130            for c in chars {
4131                match c {
4132                    ')' => depth += 1,
4133                    c if c.is_whitespace() => return Some(depth),
4134                    _ => return None,
4135                }
4136            }
4137            Some(depth)
4138        }
4139        _ => None,
4140    }
4141}
4142
4143pub fn wasm_stdlib_symbols() -> impl Iterator<Item = &'static str> {
4144    const WASM_STDLIB_SYMBOLS: &str = include_str!(concat!(env!("OUT_DIR"), "/stdlib-symbols.txt"));
4145
4146    WASM_STDLIB_SYMBOLS
4147        .lines()
4148        .map(|s| s.trim_matches(|c| c == '"' || c == ','))
4149}
4150
4151unsafe extern "C" {
4152    fn ts_node_string_pretty(node: ffi::TSNode, initial_indent_level: usize) -> *mut c_char;
4153    static mut ts_current_free: unsafe extern "C" fn(ptr: *mut c_void);
4154}
4155
4156/// Frees a pointer that was returned by a tree-sitter C API using whichever `free`
4157/// function is currently installed via [`set_allocator`] or [`ffi::ts_set_allocator`].
4158#[inline]
4159unsafe fn ts_free(ptr: *mut c_void) {
4160    let f = unsafe { core::ptr::addr_of!(ts_current_free).read() };
4161    unsafe { f(ptr) };
4162}
4163
4164/// A complete set of memory allocation functions for the core C library.
4165#[derive(Copy, Clone)]
4166pub struct Allocator {
4167    pub malloc: unsafe extern "C" fn(size: usize) -> *mut c_void,
4168    pub calloc: unsafe extern "C" fn(nmemb: usize, size: usize) -> *mut c_void,
4169    pub realloc: unsafe extern "C" fn(ptr: *mut c_void, size: usize) -> *mut c_void,
4170    pub free: unsafe extern "C" fn(ptr: *mut c_void),
4171}
4172
4173/// Replaces the memory allocation functions used by the core C library.
4174///
4175/// Pass `Some` to install an allocator, or `None` to restore libc defaults.
4176///
4177/// # Safety
4178///
4179/// All of the following must hold:
4180///
4181/// - The four functions must belong to a single allocator family.
4182///
4183/// - The functions must not return null for non-zero allocs.
4184///
4185/// - Returned pointers must satisfy the alignment that libc `malloc` provides.
4186///
4187/// - Call this before any other tree-sitter API call, and do not call it again
4188///   while live tree-sitter objects exist.
4189///
4190/// - This function is not thread-safe.
4191#[doc(alias = "ts_set_allocator")]
4192pub unsafe fn set_allocator(allocator: Option<Allocator>) {
4193    let (m, c, r, f) = match allocator {
4194        Some(a) => (
4195            Some(a.malloc),
4196            Some(a.calloc),
4197            Some(a.realloc),
4198            Some(a.free),
4199        ),
4200        None => (None, None, None, None),
4201    };
4202    unsafe { ffi::ts_set_allocator(m, c, r, f) };
4203}
4204
4205#[cfg(feature = "std")]
4206#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
4207impl error::Error for IncludedRangesError {}
4208#[cfg(feature = "std")]
4209#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
4210impl error::Error for LanguageError {}
4211#[cfg(feature = "std")]
4212#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
4213impl error::Error for QueryError {}
4214
4215#[cfg(not(target_family = "wasm"))]
4216unsafe impl Send for Language {}
4217#[cfg(not(target_family = "wasm"))]
4218unsafe impl Sync for Language {}
4219
4220unsafe impl Send for Node<'_> {}
4221unsafe impl Sync for Node<'_> {}
4222
4223#[cfg(not(target_family = "wasm"))]
4224unsafe impl Send for LookaheadIterator {}
4225#[cfg(not(target_family = "wasm"))]
4226unsafe impl Sync for LookaheadIterator {}
4227
4228#[cfg(not(target_family = "wasm"))]
4229unsafe impl Send for LookaheadNamesIterator<'_> {}
4230#[cfg(not(target_family = "wasm"))]
4231unsafe impl Sync for LookaheadNamesIterator<'_> {}
4232
4233#[cfg(not(target_family = "wasm"))]
4234unsafe impl Send for Parser {}
4235#[cfg(not(target_family = "wasm"))]
4236unsafe impl Sync for Parser {}
4237
4238unsafe impl Send for Query {}
4239unsafe impl Sync for Query {}
4240
4241unsafe impl Send for QueryCursor {}
4242unsafe impl Sync for QueryCursor {}
4243
4244unsafe impl Send for Tree {}
4245unsafe impl Sync for Tree {}
4246
4247unsafe impl Send for TreeCursor<'_> {}
4248unsafe impl Sync for TreeCursor<'_> {}