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