1#![doc = include_str!("./README.md")]
2#![cfg_attr(not(feature = "std"), no_std)]
3
4mod core_wrapper;
5pub use core_wrapper::core as core_transpiled;
6
7pub mod ffi;
8mod util;
9
10#[cfg(not(feature = "std"))]
11extern crate alloc;
12#[cfg(not(feature = "std"))]
13use alloc::{boxed::Box, format, string::String, string::ToString, vec::Vec};
14use core::{
15 ffi::{c_char, c_void, CStr},
16 fmt::{self, Write},
17 hash, iter,
18 marker::PhantomData,
19 mem::MaybeUninit,
20 num::NonZeroU16,
21 ops::{self, Deref},
22 ptr::{self, NonNull},
23 slice, str,
24 sync::atomic::AtomicUsize,
25};
26#[cfg(feature = "std")]
27use std::error;
28#[cfg(feature = "capi")]
29#[cfg(all(feature = "std", feature = "capi", any(unix, target_os = "wasi")))]
30use std::os::fd::AsRawFd;
31#[cfg(all(windows, feature = "std", feature = "capi"))]
32use std::os::windows::io::AsRawHandle;
33
34use streaming_iterator::{StreamingIterator, StreamingIteratorMut};
35use tree_sitter_language::LanguageFn;
36
37#[cfg(feature = "wasm")]
38mod wasm_language;
39#[cfg(feature = "wasm")]
40pub use wasm_language::*;
41
42#[doc(alias = "TREE_SITTER_LANGUAGE_VERSION")]
50pub const LANGUAGE_VERSION: usize = ffi::TREE_SITTER_LANGUAGE_VERSION as usize;
51
52#[doc(alias = "TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION")]
55pub const MIN_COMPATIBLE_LANGUAGE_VERSION: usize =
56 ffi::TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION as usize;
57
58pub const PARSER_HEADER: &str = include_str!("../src/parser.h");
59
60#[doc(alias = "TSLanguage")]
63#[derive(Debug, PartialEq, Eq, Hash)]
64#[repr(transparent)]
65pub struct Language(*const ffi::TSLanguage);
66
67pub struct LanguageRef<'a>(*const ffi::TSLanguage, PhantomData<&'a ()>);
68
69#[doc(alias = "TSTree")]
71pub struct Tree(NonNull<ffi::TSTree>);
72
73#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, PartialOrd, Ord)]
77pub struct Point {
78 pub row: usize,
79 pub column: usize,
80}
81
82#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
85pub struct Range {
86 pub start_byte: usize,
87 pub end_byte: usize,
88 pub start_point: Point,
89 pub end_point: Point,
90}
91
92#[derive(Clone, Copy, Debug, PartialEq, Eq)]
94pub struct InputEdit {
95 pub start_byte: usize,
96 pub old_end_byte: usize,
97 pub new_end_byte: usize,
98 pub start_position: Point,
99 pub old_end_position: Point,
100 pub new_end_position: Point,
101}
102
103#[doc(alias = "TSNode")]
105#[derive(Clone, Copy)]
106#[repr(transparent)]
107pub struct Node<'tree>(ffi::TSNode, PhantomData<&'tree ()>);
108
109#[doc(alias = "TSParser")]
112pub struct Parser(NonNull<ffi::TSParser>);
113
114#[doc(alias = "TSLookaheadIterator")]
117pub struct LookaheadIterator(NonNull<ffi::TSLookaheadIterator>);
118struct LookaheadNamesIterator<'a>(&'a mut LookaheadIterator);
119
120#[derive(Debug, PartialEq, Eq)]
122pub enum LogType {
123 Parse,
124 Lex,
125}
126
127type FieldId = NonZeroU16;
128
129type Logger<'a> = Box<dyn FnMut(LogType, &str) + 'a>;
131
132#[doc(alias = "TSTreeCursor")]
134pub struct TreeCursor<'cursor>(ffi::TSTreeCursor, PhantomData<&'cursor ()>);
135
136#[doc(alias = "TSQuery")]
138#[derive(Debug)]
139#[allow(clippy::type_complexity)]
140pub struct Query {
141 ptr: NonNull<ffi::TSQuery>,
142 capture_names: Box<[&'static str]>,
143 capture_quantifiers: Box<[Box<[CaptureQuantifier]>]>,
144 text_predicates: Box<[Box<[TextPredicateCapture]>]>,
145 property_settings: Box<[Box<[QueryProperty]>]>,
146 property_predicates: Box<[Box<[(QueryProperty, bool)]>]>,
147 general_predicates: Box<[Box<[QueryPredicate]>]>,
148}
149
150#[derive(Debug, PartialEq, Eq, Clone, Copy)]
152pub enum CaptureQuantifier {
153 Zero,
154 ZeroOrOne,
155 ZeroOrMore,
156 One,
157 OneOrMore,
158}
159
160impl From<ffi::TSQuantifier> for CaptureQuantifier {
161 fn from(value: ffi::TSQuantifier) -> Self {
162 match value {
163 ffi::TSQuantifierZero => Self::Zero,
164 ffi::TSQuantifierZeroOrOne => Self::ZeroOrOne,
165 ffi::TSQuantifierZeroOrMore => Self::ZeroOrMore,
166 ffi::TSQuantifierOne => Self::One,
167 ffi::TSQuantifierOneOrMore => Self::OneOrMore,
168 _ => panic!("Unrecognized quantifier: {value}"),
169 }
170 }
171}
172
173#[doc(alias = "TSQueryCursor")]
175pub struct QueryCursor {
176 ptr: NonNull<ffi::TSQueryCursor>,
177}
178
179#[derive(Debug, PartialEq, Eq)]
181pub struct QueryProperty {
182 pub key: Box<str>,
183 pub value: Option<Box<str>>,
184 pub capture_id: Option<usize>,
185}
186
187#[derive(Debug, PartialEq, Eq)]
188pub enum QueryPredicateArg {
189 Capture(u32),
190 String(Box<str>),
191}
192
193#[derive(Debug, PartialEq, Eq)]
195pub struct QueryPredicate {
196 pub operator: Box<str>,
197 pub args: Box<[QueryPredicateArg]>,
198}
199
200pub struct QueryMatch<'cursor, 'tree> {
202 pub pattern_index: usize,
203 pub captures: &'cursor [QueryCapture<'tree>],
204 id: u32,
205 cursor: *mut ffi::TSQueryCursor,
206}
207
208pub struct QueryMatches<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> {
210 ptr: *mut ffi::TSQueryCursor,
211 query: &'query Query,
212 text_provider: T,
213 buffer1: Vec<u8>,
214 buffer2: Vec<u8>,
215 current_match: Option<QueryMatch<'query, 'tree>>,
216 _phantom: PhantomData<(&'tree (), I)>,
217}
218
219pub struct QueryCaptures<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> {
221 ptr: *mut ffi::TSQueryCursor,
222 query: &'query Query,
223 text_provider: T,
224 buffer1: Vec<u8>,
225 buffer2: Vec<u8>,
226 current_match: Option<(QueryMatch<'query, 'tree>, usize)>,
227 _phantom: PhantomData<(&'tree (), I)>,
228}
229
230pub trait TextProvider<I>
231where
232 I: AsRef<[u8]>,
233{
234 type I: Iterator<Item = I>;
235 fn text(&mut self, node: Node) -> Self::I;
236}
237
238#[derive(Clone, Copy, Debug)]
241#[repr(C)]
242pub struct QueryCapture<'tree> {
243 pub node: Node<'tree>,
244 pub index: u32,
245}
246
247#[derive(Debug, PartialEq, Eq)]
250pub struct LanguageError {
251 version: usize,
252}
253
254#[derive(Debug, PartialEq, Eq)]
256pub struct IncludedRangesError(pub usize);
257
258#[derive(Debug, PartialEq, Eq)]
260pub struct QueryError {
261 pub row: usize,
262 pub column: usize,
263 pub offset: usize,
264 pub message: String,
265 pub kind: QueryErrorKind,
266}
267
268#[derive(Debug, PartialEq, Eq)]
269pub enum QueryErrorKind {
270 Syntax,
271 NodeType,
272 Field,
273 Capture,
274 Predicate,
275 Structure,
276 Language,
277}
278
279#[derive(Debug)]
280enum TextPredicateCapture {
286 EqString(u32, Box<str>, bool, bool),
287 EqCapture(u32, u32, bool, bool),
288 MatchString(u32, regex::bytes::Regex, bool, bool),
289 AnyString(u32, Box<[Box<str>]>, bool),
290}
291
292pub struct LossyUtf8<'a> {
295 bytes: &'a [u8],
296 in_replacement: bool,
297}
298
299impl Language {
300 #[must_use]
301 pub fn new(builder: LanguageFn) -> Self {
302 Self(unsafe { builder.into_raw()().cast() })
303 }
304
305 #[doc(alias = "ts_language_version")]
308 #[must_use]
309 pub fn version(&self) -> usize {
310 unsafe { ffi::ts_language_version(self.0) as usize }
311 }
312
313 #[doc(alias = "ts_language_symbol_count")]
315 #[must_use]
316 pub fn node_kind_count(&self) -> usize {
317 unsafe { ffi::ts_language_symbol_count(self.0) as usize }
318 }
319
320 #[doc(alias = "ts_language_state_count")]
322 #[must_use]
323 pub fn parse_state_count(&self) -> usize {
324 unsafe { ffi::ts_language_state_count(self.0) as usize }
325 }
326
327 #[doc(alias = "ts_language_symbol_name")]
329 #[must_use]
330 pub fn node_kind_for_id(&self, id: u16) -> Option<&'static str> {
331 let ptr = unsafe { ffi::ts_language_symbol_name(self.0, id) };
332 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
333 }
334
335 #[doc(alias = "ts_language_symbol_for_name")]
337 #[must_use]
338 pub fn id_for_node_kind(&self, kind: &str, named: bool) -> u16 {
339 unsafe {
340 ffi::ts_language_symbol_for_name(
341 self.0,
342 kind.as_bytes().as_ptr().cast::<c_char>(),
343 kind.len() as u32,
344 named,
345 )
346 }
347 }
348
349 #[must_use]
352 pub fn node_kind_is_named(&self, id: u16) -> bool {
353 unsafe { ffi::ts_language_symbol_type(self.0, id) == ffi::TSSymbolTypeRegular }
354 }
355
356 #[doc(alias = "ts_language_symbol_type")]
357 #[must_use]
358 pub fn node_kind_is_visible(&self, id: u16) -> bool {
359 unsafe { ffi::ts_language_symbol_type(self.0, id) <= ffi::TSSymbolTypeAnonymous }
360 }
361
362 #[doc(alias = "ts_language_field_count")]
364 #[must_use]
365 pub fn field_count(&self) -> usize {
366 unsafe { ffi::ts_language_field_count(self.0) as usize }
367 }
368
369 #[doc(alias = "ts_language_field_name_for_id")]
371 #[must_use]
372 pub fn field_name_for_id(&self, field_id: u16) -> Option<&'static str> {
373 let ptr = unsafe { ffi::ts_language_field_name_for_id(self.0, field_id) };
374 (!ptr.is_null()).then(|| unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
375 }
376
377 #[doc(alias = "ts_language_field_id_for_name")]
379 #[must_use]
380 pub fn field_id_for_name(&self, field_name: impl AsRef<[u8]>) -> Option<FieldId> {
381 let field_name = field_name.as_ref();
382 let id = unsafe {
383 ffi::ts_language_field_id_for_name(
384 self.0,
385 field_name.as_ptr().cast::<c_char>(),
386 field_name.len() as u32,
387 )
388 };
389 FieldId::new(id)
390 }
391
392 #[doc(alias = "ts_language_next_state")]
401 #[must_use]
402 pub fn next_state(&self, state: u16, id: u16) -> u16 {
403 unsafe { ffi::ts_language_next_state(self.0, state, id) }
404 }
405
406 #[doc(alias = "ts_lookahead_iterator_new")]
420 #[must_use]
421 pub fn lookahead_iterator(&self, state: u16) -> Option<LookaheadIterator> {
422 let ptr = unsafe { ffi::ts_lookahead_iterator_new(self.0, state) };
423 (!ptr.is_null()).then(|| unsafe { LookaheadIterator::from_raw(ptr) })
424 }
425}
426
427impl From<LanguageFn> for Language {
428 fn from(value: LanguageFn) -> Self {
429 Self::new(value)
430 }
431}
432
433impl Clone for Language {
434 fn clone(&self) -> Self {
435 unsafe { Self(ffi::ts_language_copy(self.0)) }
436 }
437}
438
439impl Drop for Language {
440 fn drop(&mut self) {
441 unsafe { ffi::ts_language_delete(self.0) }
442 }
443}
444
445impl<'a> Deref for LanguageRef<'a> {
446 type Target = Language;
447
448 fn deref(&self) -> &Self::Target {
449 unsafe { &*(core::ptr::addr_of!(self.0).cast::<Language>()) }
450 }
451}
452
453impl Default for Parser {
454 fn default() -> Self {
455 Self::new()
456 }
457}
458
459impl Parser {
460 #[doc(alias = "ts_parser_new")]
462 #[must_use]
463 pub fn new() -> Self {
464 unsafe {
465 let parser = ffi::ts_parser_new();
466 Self(NonNull::new_unchecked(parser))
467 }
468 }
469
470 #[doc(alias = "ts_parser_set_language")]
481 pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> {
482 let version = language.version();
483 if (MIN_COMPATIBLE_LANGUAGE_VERSION..=LANGUAGE_VERSION).contains(&version) {
484 unsafe {
485 ffi::ts_parser_set_language(self.0.as_ptr(), language.0);
486 }
487 Ok(())
488 } else {
489 Err(LanguageError { version })
490 }
491 }
492
493 #[doc(alias = "ts_parser_language")]
495 #[must_use]
496 pub fn language(&self) -> Option<LanguageRef<'_>> {
497 let ptr = unsafe { ffi::ts_parser_language(self.0.as_ptr()) };
498 (!ptr.is_null()).then_some(LanguageRef(ptr, PhantomData))
499 }
500
501 #[doc(alias = "ts_parser_logger")]
503 #[must_use]
504 pub fn logger(&self) -> Option<&Logger> {
505 let logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
506 unsafe { logger.payload.cast::<Logger>().as_ref() }
507 }
508
509 #[doc(alias = "ts_parser_set_logger")]
511 pub fn set_logger(&mut self, logger: Option<Logger>) {
512 let prev_logger = unsafe { ffi::ts_parser_logger(self.0.as_ptr()) };
513 if !prev_logger.payload.is_null() {
514 drop(unsafe { Box::from_raw(prev_logger.payload.cast::<Logger>()) });
515 }
516
517 let c_logger;
518 if let Some(logger) = logger {
519 let container = Box::new(logger);
520
521 unsafe extern "C" fn log(
522 payload: *mut c_void,
523 c_log_type: ffi::TSLogType,
524 c_message: *const c_char,
525 ) {
526 let callback = payload.cast::<Logger>().as_mut().unwrap();
527 if let Ok(message) = CStr::from_ptr(c_message).to_str() {
528 let log_type = if c_log_type == ffi::TSLogTypeParse {
529 LogType::Parse
530 } else {
531 LogType::Lex
532 };
533 callback(log_type, message);
534 }
535 }
536
537 let raw_container = Box::into_raw(container);
538
539 c_logger = ffi::TSLogger {
540 payload: raw_container.cast::<c_void>(),
541 log: Some(log),
542 };
543 } else {
544 c_logger = ffi::TSLogger {
545 payload: ptr::null_mut(),
546 log: None,
547 };
548 }
549
550 unsafe { ffi::ts_parser_set_logger(self.0.as_ptr(), c_logger) };
551 }
552
553 #[cfg(feature = "capi")]
554 #[doc(alias = "ts_parser_print_dot_graphs")]
559 #[cfg(not(target_os = "wasi"))]
560 #[cfg(feature = "std")]
561 pub fn print_dot_graphs(
562 &mut self,
563 #[cfg(unix)] file: &impl AsRawFd,
564 #[cfg(windows)] file: &impl AsRawHandle,
565 ) {
566 #[cfg(unix)]
567 {
568 let fd = file.as_raw_fd();
569 unsafe {
570 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(fd));
571 }
572 }
573
574 #[cfg(windows)]
575 {
576 let handle = file.as_raw_handle();
577 unsafe {
578 ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), ffi::_ts_dup(handle));
579 }
580 }
581 }
582
583 #[doc(alias = "ts_parser_print_dot_graphs")]
585 pub fn stop_printing_dot_graphs(&mut self) {
586 unsafe { ffi::ts_parser_print_dot_graphs(self.0.as_ptr(), -1) }
587 }
588
589 #[doc(alias = "ts_parser_parse")]
602 pub fn parse(&mut self, text: impl AsRef<[u8]>, old_tree: Option<&Tree>) -> Option<Tree> {
603 let bytes = text.as_ref();
604 let len = bytes.len();
605 self.parse_with(
606 &mut |i, _| (i < len).then(|| &bytes[i..]).unwrap_or_default(),
607 old_tree,
608 )
609 }
610
611 pub fn parse_utf16(
619 &mut self,
620 input: impl AsRef<[u16]>,
621 old_tree: Option<&Tree>,
622 ) -> Option<Tree> {
623 let code_points = input.as_ref();
624 let len = code_points.len();
625 self.parse_utf16_with(
626 &mut |i, _| (i < len).then(|| &code_points[i..]).unwrap_or_default(),
627 old_tree,
628 )
629 }
630
631 pub fn parse_with<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
642 &mut self,
643 callback: &mut F,
644 old_tree: Option<&Tree>,
645 ) -> Option<Tree> {
646 let mut payload: (&mut F, Option<T>) = (callback, None);
652
653 unsafe extern "C" fn read<T: AsRef<[u8]>, F: FnMut(usize, Point) -> T>(
655 payload: *mut c_void,
656 byte_offset: u32,
657 position: ffi::TSPoint,
658 bytes_read: *mut u32,
659 ) -> *const c_char {
660 let (callback, text) = payload.cast::<(&mut F, Option<T>)>().as_mut().unwrap();
661 *text = Some(callback(byte_offset as usize, position.into()));
662 let slice = text.as_ref().unwrap().as_ref();
663 *bytes_read = slice.len() as u32;
664 slice.as_ptr().cast::<c_char>()
665 }
666
667 let c_input = ffi::TSInput {
668 payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
669 read: Some(read::<T, F>),
670 encoding: ffi::TSInputEncodingUTF8,
671 };
672
673 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
674 unsafe {
675 let c_new_tree = ffi::ts_parser_parse(self.0.as_ptr(), c_old_tree, c_input);
676 NonNull::new(c_new_tree).map(Tree)
677 }
678 }
679
680 pub fn parse_utf16_with<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
691 &mut self,
692 callback: &mut F,
693 old_tree: Option<&Tree>,
694 ) -> Option<Tree> {
695 let mut payload: (&mut F, Option<T>) = (callback, None);
701
702 unsafe extern "C" fn read<T: AsRef<[u16]>, F: FnMut(usize, Point) -> T>(
704 payload: *mut c_void,
705 byte_offset: u32,
706 position: ffi::TSPoint,
707 bytes_read: *mut u32,
708 ) -> *const c_char {
709 let (callback, text) = payload.cast::<(&mut F, Option<T>)>().as_mut().unwrap();
710 *text = Some(callback(
711 (byte_offset / 2) as usize,
712 Point {
713 row: position.row as usize,
714 column: position.column as usize / 2,
715 },
716 ));
717 let slice = text.as_ref().unwrap().as_ref();
718 *bytes_read = slice.len() as u32 * 2;
719 slice.as_ptr().cast::<c_char>()
720 }
721
722 let c_input = ffi::TSInput {
723 payload: core::ptr::addr_of_mut!(payload).cast::<c_void>(),
724 read: Some(read::<T, F>),
725 encoding: ffi::TSInputEncodingUTF16,
726 };
727
728 let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr());
729 unsafe {
730 let c_new_tree = ffi::ts_parser_parse(self.0.as_ptr(), c_old_tree, c_input);
731 NonNull::new(c_new_tree).map(Tree)
732 }
733 }
734
735 #[doc(alias = "ts_parser_reset")]
743 pub fn reset(&mut self) {
744 unsafe { ffi::ts_parser_reset(self.0.as_ptr()) }
745 }
746
747 #[doc(alias = "ts_parser_timeout_micros")]
751 #[must_use]
752 pub fn timeout_micros(&self) -> u64 {
753 unsafe { ffi::ts_parser_timeout_micros(self.0.as_ptr()) }
754 }
755
756 #[doc(alias = "ts_parser_set_timeout_micros")]
762 pub fn set_timeout_micros(&mut self, timeout_micros: u64) {
763 unsafe { ffi::ts_parser_set_timeout_micros(self.0.as_ptr(), timeout_micros) }
764 }
765
766 #[doc(alias = "ts_parser_set_included_ranges")]
784 pub fn set_included_ranges(&mut self, ranges: &[Range]) -> Result<(), IncludedRangesError> {
785 let ts_ranges = ranges.iter().copied().map(Into::into).collect::<Vec<_>>();
786 let result = unsafe {
787 ffi::ts_parser_set_included_ranges(
788 self.0.as_ptr(),
789 ts_ranges.as_ptr(),
790 ts_ranges.len() as u32,
791 )
792 };
793
794 if result {
795 Ok(())
796 } else {
797 let mut prev_end_byte = 0;
798 for (i, range) in ranges.iter().enumerate() {
799 if range.start_byte < prev_end_byte || range.end_byte < range.start_byte {
800 return Err(IncludedRangesError(i));
801 }
802 prev_end_byte = range.end_byte;
803 }
804 Err(IncludedRangesError(0))
805 }
806 }
807
808 #[doc(alias = "ts_parser_included_ranges")]
810 #[must_use]
811 pub fn included_ranges(&self) -> Vec<Range> {
812 let mut count = 0u32;
813 unsafe {
814 let ptr =
815 ffi::ts_parser_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
816 let ranges = slice::from_raw_parts(ptr, count as usize);
817 let result = ranges.iter().copied().map(Into::into).collect();
818 result
819 }
820 }
821
822 #[doc(alias = "ts_parser_cancellation_flag")]
828 #[must_use]
829 pub unsafe fn cancellation_flag(&self) -> Option<&AtomicUsize> {
830 ffi::ts_parser_cancellation_flag(self.0.as_ptr())
831 .cast::<AtomicUsize>()
832 .as_ref()
833 }
834
835 #[doc(alias = "ts_parser_set_cancellation_flag")]
846 pub unsafe fn set_cancellation_flag(&mut self, flag: Option<&AtomicUsize>) {
847 if let Some(flag) = flag {
848 ffi::ts_parser_set_cancellation_flag(
849 self.0.as_ptr(),
850 (flag as *const AtomicUsize).cast::<usize>(),
851 );
852 } else {
853 ffi::ts_parser_set_cancellation_flag(self.0.as_ptr(), ptr::null());
854 }
855 }
856}
857
858impl Drop for Parser {
859 fn drop(&mut self) {
860 self.stop_printing_dot_graphs();
861 self.set_logger(None);
862 unsafe { ffi::ts_parser_delete(self.0.as_ptr()) }
863 }
864}
865
866impl Tree {
867 #[doc(alias = "ts_tree_root_node")]
869 #[must_use]
870 pub fn root_node(&self) -> Node {
871 Node::new(unsafe { ffi::ts_tree_root_node(self.0.as_ptr()) }).unwrap()
872 }
873
874 #[doc(alias = "ts_tree_root_node_with_offset")]
877 #[must_use]
878 pub fn root_node_with_offset(&self, offset_bytes: usize, offset_extent: Point) -> Node {
879 Node::new(unsafe {
880 ffi::ts_tree_root_node_with_offset(
881 self.0.as_ptr(),
882 offset_bytes as u32,
883 offset_extent.into(),
884 )
885 })
886 .unwrap()
887 }
888
889 #[doc(alias = "ts_tree_language")]
891 #[must_use]
892 pub fn language(&self) -> LanguageRef {
893 LanguageRef(
894 unsafe { ffi::ts_tree_language(self.0.as_ptr()) },
895 PhantomData,
896 )
897 }
898
899 #[doc(alias = "ts_tree_edit")]
905 pub fn edit(&mut self, edit: &InputEdit) {
906 let edit = edit.into();
907 unsafe { ffi::ts_tree_edit(self.0.as_ptr(), &edit) };
908 }
909
910 #[must_use]
912 pub fn walk(&self) -> TreeCursor {
913 self.root_node().walk()
914 }
915
916 #[doc(alias = "ts_tree_get_changed_ranges")]
926 #[must_use]
927 pub fn changed_ranges(&self, other: &Self) -> impl ExactSizeIterator<Item = Range> {
928 let mut count = 0u32;
929 unsafe {
930 let ptr = ffi::ts_tree_get_changed_ranges(
931 self.0.as_ptr(),
932 other.0.as_ptr(),
933 core::ptr::addr_of_mut!(count),
934 );
935 util::CBufferIter::new(ptr, count as usize).map(Into::into)
936 }
937 }
938
939 #[doc(alias = "ts_tree_included_ranges")]
941 #[must_use]
942 pub fn included_ranges(&self) -> Vec<Range> {
943 let mut count = 0u32;
944 unsafe {
945 let ptr = ffi::ts_tree_included_ranges(self.0.as_ptr(), core::ptr::addr_of_mut!(count));
946 let ranges = slice::from_raw_parts(ptr, count as usize);
947 let result = ranges.iter().copied().map(Into::into).collect();
948 ffi::ts_free(ptr.cast::<c_void>());
949 result
950 }
951 }
952
953 #[cfg(feature = "capi")]
954 #[doc(alias = "ts_tree_print_dot_graph")]
959 #[cfg(not(target_os = "wasi"))]
960 #[cfg(feature = "std")]
961 pub fn print_dot_graph(
962 &self,
963 #[cfg(unix)] file: &impl AsRawFd,
964 #[cfg(windows)] file: &impl AsRawHandle,
965 ) {
966 #[cfg(unix)]
967 {
968 let fd = file.as_raw_fd();
969 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), fd) }
970 }
971
972 #[cfg(windows)]
973 {
974 let handle = file.as_raw_handle();
975 unsafe { ffi::ts_tree_print_dot_graph(self.0.as_ptr(), handle as i32) }
976 }
977 }
978}
979
980impl fmt::Debug for Tree {
981 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
982 write!(f, "{{Tree {:?}}}", self.root_node())
983 }
984}
985
986impl Drop for Tree {
987 fn drop(&mut self) {
988 unsafe { ffi::ts_tree_delete(self.0.as_ptr()) }
989 }
990}
991
992impl Clone for Tree {
993 fn clone(&self) -> Self {
994 unsafe { Self(NonNull::new_unchecked(ffi::ts_tree_copy(self.0.as_ptr()))) }
995 }
996}
997
998impl<'tree> Node<'tree> {
999 fn new(node: ffi::TSNode) -> Option<Self> {
1000 (!node.id.is_null()).then_some(Node(node, PhantomData))
1001 }
1002
1003 #[must_use]
1010 pub fn id(&self) -> usize {
1011 self.0.id as usize
1012 }
1013
1014 #[doc(alias = "ts_node_symbol")]
1016 #[must_use]
1017 pub fn kind_id(&self) -> u16 {
1018 unsafe { ffi::ts_node_symbol(self.0) }
1019 }
1020
1021 #[doc(alias = "ts_node_grammar_symbol")]
1024 #[must_use]
1025 pub fn grammar_id(&self) -> u16 {
1026 unsafe { ffi::ts_node_grammar_symbol(self.0) }
1027 }
1028
1029 #[doc(alias = "ts_node_type")]
1031 #[must_use]
1032 pub fn kind(&self) -> &'static str {
1033 unsafe { CStr::from_ptr(ffi::ts_node_type(self.0)) }
1034 .to_str()
1035 .unwrap()
1036 }
1037
1038 #[doc(alias = "ts_node_grammar_type")]
1041 #[must_use]
1042 pub fn grammar_name(&self) -> &'static str {
1043 unsafe { CStr::from_ptr(ffi::ts_node_grammar_type(self.0)) }
1044 .to_str()
1045 .unwrap()
1046 }
1047
1048 #[doc(alias = "ts_node_language")]
1050 #[must_use]
1051 pub fn language(&self) -> LanguageRef {
1052 LanguageRef(unsafe { ffi::ts_node_language(self.0) }, PhantomData)
1053 }
1054
1055 #[doc(alias = "ts_node_is_named")]
1060 #[must_use]
1061 pub fn is_named(&self) -> bool {
1062 unsafe { ffi::ts_node_is_named(self.0) }
1063 }
1064
1065 #[doc(alias = "ts_node_is_extra")]
1070 #[must_use]
1071 pub fn is_extra(&self) -> bool {
1072 unsafe { ffi::ts_node_is_extra(self.0) }
1073 }
1074
1075 #[doc(alias = "ts_node_has_changes")]
1077 #[must_use]
1078 pub fn has_changes(&self) -> bool {
1079 unsafe { ffi::ts_node_has_changes(self.0) }
1080 }
1081
1082 #[doc(alias = "ts_node_has_error")]
1085 #[must_use]
1086 pub fn has_error(&self) -> bool {
1087 unsafe { ffi::ts_node_has_error(self.0) }
1088 }
1089
1090 #[doc(alias = "ts_node_is_error")]
1095 #[must_use]
1096 pub fn is_error(&self) -> bool {
1097 unsafe { ffi::ts_node_is_error(self.0) }
1098 }
1099
1100 #[doc(alias = "ts_node_parse_state")]
1102 #[must_use]
1103 pub fn parse_state(&self) -> u16 {
1104 unsafe { ffi::ts_node_parse_state(self.0) }
1105 }
1106
1107 #[doc(alias = "ts_node_next_parse_state")]
1109 #[must_use]
1110 pub fn next_parse_state(&self) -> u16 {
1111 unsafe { ffi::ts_node_next_parse_state(self.0) }
1112 }
1113
1114 #[doc(alias = "ts_node_is_missing")]
1119 #[must_use]
1120 pub fn is_missing(&self) -> bool {
1121 unsafe { ffi::ts_node_is_missing(self.0) }
1122 }
1123
1124 #[doc(alias = "ts_node_start_byte")]
1126 #[must_use]
1127 pub fn start_byte(&self) -> usize {
1128 unsafe { ffi::ts_node_start_byte(self.0) as usize }
1129 }
1130
1131 #[doc(alias = "ts_node_end_byte")]
1133 #[must_use]
1134 pub fn end_byte(&self) -> usize {
1135 unsafe { ffi::ts_node_end_byte(self.0) as usize }
1136 }
1137
1138 #[must_use]
1140 pub fn byte_range(&self) -> core::ops::Range<usize> {
1141 self.start_byte()..self.end_byte()
1142 }
1143
1144 #[must_use]
1147 pub fn range(&self) -> Range {
1148 Range {
1149 start_byte: self.start_byte(),
1150 end_byte: self.end_byte(),
1151 start_point: self.start_position(),
1152 end_point: self.end_position(),
1153 }
1154 }
1155
1156 #[doc(alias = "ts_node_start_point")]
1158 #[must_use]
1159 pub fn start_position(&self) -> Point {
1160 let result = unsafe { ffi::ts_node_start_point(self.0) };
1161 result.into()
1162 }
1163
1164 #[doc(alias = "ts_node_end_point")]
1166 #[must_use]
1167 pub fn end_position(&self) -> Point {
1168 let result = unsafe { ffi::ts_node_end_point(self.0) };
1169 result.into()
1170 }
1171
1172 #[doc(alias = "ts_node_child")]
1179 #[must_use]
1180 pub fn child(&self, i: usize) -> Option<Self> {
1181 Self::new(unsafe { ffi::ts_node_child(self.0, i as u32) })
1182 }
1183
1184 #[doc(alias = "ts_node_child_count")]
1186 #[must_use]
1187 pub fn child_count(&self) -> usize {
1188 unsafe { ffi::ts_node_child_count(self.0) as usize }
1189 }
1190
1191 #[doc(alias = "ts_node_named_child")]
1198 #[must_use]
1199 pub fn named_child(&self, i: usize) -> Option<Self> {
1200 Self::new(unsafe { ffi::ts_node_named_child(self.0, i as u32) })
1201 }
1202
1203 #[doc(alias = "ts_node_named_child_count")]
1207 #[must_use]
1208 pub fn named_child_count(&self) -> usize {
1209 unsafe { ffi::ts_node_named_child_count(self.0) as usize }
1210 }
1211
1212 #[doc(alias = "ts_node_child_by_field_name")]
1217 #[must_use]
1218 pub fn child_by_field_name(&self, field_name: impl AsRef<[u8]>) -> Option<Self> {
1219 let field_name = field_name.as_ref();
1220 Self::new(unsafe {
1221 ffi::ts_node_child_by_field_name(
1222 self.0,
1223 field_name.as_ptr().cast::<c_char>(),
1224 field_name.len() as u32,
1225 )
1226 })
1227 }
1228
1229 #[doc(alias = "ts_node_child_by_field_id")]
1234 #[must_use]
1235 pub fn child_by_field_id(&self, field_id: u16) -> Option<Self> {
1236 Self::new(unsafe { ffi::ts_node_child_by_field_id(self.0, field_id) })
1237 }
1238
1239 #[doc(alias = "ts_node_field_name_for_child")]
1241 #[must_use]
1242 pub fn field_name_for_child(&self, child_index: u32) -> Option<&'static str> {
1243 unsafe {
1244 let ptr = ffi::ts_node_field_name_for_child(self.0, child_index);
1245 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1246 }
1247 }
1248
1249 pub fn field_name_for_named_child(&self, named_child_index: u32) -> Option<&'static str> {
1251 unsafe {
1252 let ptr = ffi::ts_node_field_name_for_named_child(self.0, named_child_index);
1253 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1254 }
1255 }
1256
1257 pub fn children<'cursor>(
1267 &self,
1268 cursor: &'cursor mut TreeCursor<'tree>,
1269 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1270 cursor.reset(*self);
1271 cursor.goto_first_child();
1272 (0..self.child_count()).map(move |_| {
1273 let result = cursor.node();
1274 cursor.goto_next_sibling();
1275 result
1276 })
1277 }
1278
1279 pub fn named_children<'cursor>(
1283 &self,
1284 cursor: &'cursor mut TreeCursor<'tree>,
1285 ) -> impl ExactSizeIterator<Item = Node<'tree>> + 'cursor {
1286 cursor.reset(*self);
1287 cursor.goto_first_child();
1288 (0..self.named_child_count()).map(move |_| {
1289 while !cursor.node().is_named() {
1290 if !cursor.goto_next_sibling() {
1291 break;
1292 }
1293 }
1294 let result = cursor.node();
1295 cursor.goto_next_sibling();
1296 result
1297 })
1298 }
1299
1300 pub fn children_by_field_name<'cursor>(
1304 &self,
1305 field_name: &str,
1306 cursor: &'cursor mut TreeCursor<'tree>,
1307 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1308 let field_id = self.language().field_id_for_name(field_name);
1309 let mut done = field_id.is_none();
1310 if !done {
1311 cursor.reset(*self);
1312 cursor.goto_first_child();
1313 }
1314 iter::from_fn(move || {
1315 if !done {
1316 while cursor.field_id() != field_id {
1317 if !cursor.goto_next_sibling() {
1318 return None;
1319 }
1320 }
1321 let result = cursor.node();
1322 if !cursor.goto_next_sibling() {
1323 done = true;
1324 }
1325 return Some(result);
1326 }
1327 None
1328 })
1329 }
1330
1331 pub fn children_by_field_id<'cursor>(
1335 &self,
1336 field_id: FieldId,
1337 cursor: &'cursor mut TreeCursor<'tree>,
1338 ) -> impl Iterator<Item = Node<'tree>> + 'cursor {
1339 cursor.reset(*self);
1340 cursor.goto_first_child();
1341 let mut done = false;
1342 iter::from_fn(move || {
1343 if !done {
1344 while cursor.field_id() != Some(field_id) {
1345 if !cursor.goto_next_sibling() {
1346 return None;
1347 }
1348 }
1349 let result = cursor.node();
1350 if !cursor.goto_next_sibling() {
1351 done = true;
1352 }
1353 return Some(result);
1354 }
1355 None
1356 })
1357 }
1358
1359 #[doc(alias = "ts_node_parent")]
1363 #[must_use]
1364 pub fn parent(&self) -> Option<Self> {
1365 Self::new(unsafe { ffi::ts_node_parent(self.0) })
1366 }
1367
1368 #[doc(alias = "ts_node_child_containing_descendant")]
1372 #[must_use]
1373 #[deprecated(since = "0.24.0", note = "Prefer child_with_descendant instead")]
1374 pub fn child_containing_descendant(&self, descendant: Self) -> Option<Self> {
1375 Self::new(unsafe { ffi::ts_node_child_containing_descendant(self.0, descendant.0) })
1376 }
1377
1378 #[doc(alias = "ts_node_child_with_descendant")]
1383 #[must_use]
1384 pub fn child_with_descendant(&self, descendant: Self) -> Option<Self> {
1385 Self::new(unsafe { ffi::ts_node_child_with_descendant(self.0, descendant.0) })
1386 }
1387
1388 #[doc(alias = "ts_node_next_sibling")]
1390 #[must_use]
1391 pub fn next_sibling(&self) -> Option<Self> {
1392 Self::new(unsafe { ffi::ts_node_next_sibling(self.0) })
1393 }
1394
1395 #[doc(alias = "ts_node_prev_sibling")]
1397 #[must_use]
1398 pub fn prev_sibling(&self) -> Option<Self> {
1399 Self::new(unsafe { ffi::ts_node_prev_sibling(self.0) })
1400 }
1401
1402 #[doc(alias = "ts_node_next_named_sibling")]
1404 #[must_use]
1405 pub fn next_named_sibling(&self) -> Option<Self> {
1406 Self::new(unsafe { ffi::ts_node_next_named_sibling(self.0) })
1407 }
1408
1409 #[doc(alias = "ts_node_prev_named_sibling")]
1411 #[must_use]
1412 pub fn prev_named_sibling(&self) -> Option<Self> {
1413 Self::new(unsafe { ffi::ts_node_prev_named_sibling(self.0) })
1414 }
1415
1416 #[doc(alias = "ts_node_first_child_for_byte")]
1418 #[must_use]
1419 pub fn first_child_for_byte(&self, byte: usize) -> Option<Self> {
1420 Self::new(unsafe { ffi::ts_node_first_child_for_byte(self.0, byte as u32) })
1421 }
1422
1423 #[doc(alias = "ts_node_first_named_child_for_point")]
1425 #[must_use]
1426 pub fn first_named_child_for_byte(&self, byte: usize) -> Option<Self> {
1427 Self::new(unsafe { ffi::ts_node_first_named_child_for_byte(self.0, byte as u32) })
1428 }
1429
1430 #[doc(alias = "ts_node_descendant_count")]
1432 #[must_use]
1433 pub fn descendant_count(&self) -> usize {
1434 unsafe { ffi::ts_node_descendant_count(self.0) as usize }
1435 }
1436
1437 #[doc(alias = "ts_node_descendant_for_byte_range")]
1439 #[must_use]
1440 pub fn descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
1441 Self::new(unsafe {
1442 ffi::ts_node_descendant_for_byte_range(self.0, start as u32, end as u32)
1443 })
1444 }
1445
1446 #[doc(alias = "ts_node_named_descendant_for_byte_range")]
1448 #[must_use]
1449 pub fn named_descendant_for_byte_range(&self, start: usize, end: usize) -> Option<Self> {
1450 Self::new(unsafe {
1451 ffi::ts_node_named_descendant_for_byte_range(self.0, start as u32, end as u32)
1452 })
1453 }
1454
1455 #[doc(alias = "ts_node_descendant_for_point_range")]
1457 #[must_use]
1458 pub fn descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
1459 Self::new(unsafe {
1460 ffi::ts_node_descendant_for_point_range(self.0, start.into(), end.into())
1461 })
1462 }
1463
1464 #[doc(alias = "ts_node_named_descendant_for_point_range")]
1466 #[must_use]
1467 pub fn named_descendant_for_point_range(&self, start: Point, end: Point) -> Option<Self> {
1468 Self::new(unsafe {
1469 ffi::ts_node_named_descendant_for_point_range(self.0, start.into(), end.into())
1470 })
1471 }
1472
1473 #[doc(alias = "ts_node_string")]
1474 #[must_use]
1475 pub fn to_sexp(&self) -> String {
1476 let c_string = unsafe { ffi::ts_node_string(self.0) };
1477 let result = unsafe { CStr::from_ptr(c_string) }
1478 .to_str()
1479 .unwrap()
1480 .to_string();
1481 unsafe { ffi::ts_free(c_string.cast::<c_void>()) };
1482 result
1483 }
1484
1485 pub fn utf8_text<'a>(&self, source: &'a [u8]) -> Result<&'a str, str::Utf8Error> {
1486 str::from_utf8(&source[self.start_byte()..self.end_byte()])
1487 }
1488
1489 #[must_use]
1490 pub fn utf16_text<'a>(&self, source: &'a [u16]) -> &'a [u16] {
1491 &source[self.start_byte()..self.end_byte()]
1492 }
1493
1494 #[doc(alias = "ts_tree_cursor_new")]
1496 #[must_use]
1497 pub fn walk(&self) -> TreeCursor<'tree> {
1498 TreeCursor(unsafe { ffi::ts_tree_cursor_new(self.0) }, PhantomData)
1499 }
1500
1501 #[doc(alias = "ts_node_edit")]
1509 pub fn edit(&mut self, edit: &InputEdit) {
1510 let edit = edit.into();
1511 unsafe { ffi::ts_node_edit(core::ptr::addr_of_mut!(self.0), &edit) }
1512 }
1513}
1514
1515impl PartialEq for Node<'_> {
1516 fn eq(&self, other: &Self) -> bool {
1517 self.0.id == other.0.id
1518 }
1519}
1520
1521impl Eq for Node<'_> {}
1522
1523impl hash::Hash for Node<'_> {
1524 fn hash<H: hash::Hasher>(&self, state: &mut H) {
1525 self.0.id.hash(state);
1526 self.0.context[0].hash(state);
1527 self.0.context[1].hash(state);
1528 self.0.context[2].hash(state);
1529 self.0.context[3].hash(state);
1530 }
1531}
1532
1533impl fmt::Debug for Node<'_> {
1534 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1535 write!(
1536 f,
1537 "{{Node {} {} - {}}}",
1538 self.kind(),
1539 self.start_position(),
1540 self.end_position()
1541 )
1542 }
1543}
1544
1545impl fmt::Display for Node<'_> {
1546 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1547 let sexp = self.to_sexp();
1548 if sexp.is_empty() {
1549 write!(f, "")
1550 } else if !f.alternate() {
1551 write!(f, "{sexp}")
1552 } else {
1553 write!(f, "{}", format_sexp(&sexp, f.width().unwrap_or(0)))
1554 }
1555 }
1556}
1557
1558impl<'cursor> TreeCursor<'cursor> {
1559 #[doc(alias = "ts_tree_cursor_current_node")]
1561 #[must_use]
1562 pub fn node(&self) -> Node<'cursor> {
1563 Node(
1564 unsafe { ffi::ts_tree_cursor_current_node(&self.0) },
1565 PhantomData,
1566 )
1567 }
1568
1569 #[doc(alias = "ts_tree_cursor_current_field_id")]
1573 #[must_use]
1574 pub fn field_id(&self) -> Option<FieldId> {
1575 let id = unsafe { ffi::ts_tree_cursor_current_field_id(&self.0) };
1576 FieldId::new(id)
1577 }
1578
1579 #[doc(alias = "ts_tree_cursor_current_field_name")]
1581 #[must_use]
1582 pub fn field_name(&self) -> Option<&'static str> {
1583 unsafe {
1584 let ptr = ffi::ts_tree_cursor_current_field_name(&self.0);
1585 (!ptr.is_null()).then(|| CStr::from_ptr(ptr).to_str().unwrap())
1586 }
1587 }
1588
1589 #[doc(alias = "ts_tree_cursor_current_depth")]
1592 #[must_use]
1593 pub fn depth(&self) -> u32 {
1594 unsafe { ffi::ts_tree_cursor_current_depth(&self.0) }
1595 }
1596
1597 #[doc(alias = "ts_tree_cursor_current_descendant_index")]
1600 #[must_use]
1601 pub fn descendant_index(&self) -> usize {
1602 unsafe { ffi::ts_tree_cursor_current_descendant_index(&self.0) as usize }
1603 }
1604
1605 #[doc(alias = "ts_tree_cursor_goto_first_child")]
1610 pub fn goto_first_child(&mut self) -> bool {
1611 unsafe { ffi::ts_tree_cursor_goto_first_child(&mut self.0) }
1612 }
1613
1614 #[doc(alias = "ts_tree_cursor_goto_last_child")]
1623 pub fn goto_last_child(&mut self) -> bool {
1624 unsafe { ffi::ts_tree_cursor_goto_last_child(&mut self.0) }
1625 }
1626
1627 #[doc(alias = "ts_tree_cursor_goto_parent")]
1633 pub fn goto_parent(&mut self) -> bool {
1634 unsafe { ffi::ts_tree_cursor_goto_parent(&mut self.0) }
1635 }
1636
1637 #[doc(alias = "ts_tree_cursor_goto_next_sibling")]
1642 pub fn goto_next_sibling(&mut self) -> bool {
1643 unsafe { ffi::ts_tree_cursor_goto_next_sibling(&mut self.0) }
1644 }
1645
1646 #[doc(alias = "ts_tree_cursor_goto_descendant")]
1650 pub fn goto_descendant(&mut self, descendant_index: usize) {
1651 unsafe { ffi::ts_tree_cursor_goto_descendant(&mut self.0, descendant_index as u32) }
1652 }
1653
1654 #[doc(alias = "ts_tree_cursor_goto_previous_sibling")]
1665 pub fn goto_previous_sibling(&mut self) -> bool {
1666 unsafe { ffi::ts_tree_cursor_goto_previous_sibling(&mut self.0) }
1667 }
1668
1669 #[doc(alias = "ts_tree_cursor_goto_first_child_for_byte")]
1675 pub fn goto_first_child_for_byte(&mut self, index: usize) -> Option<usize> {
1676 let result =
1677 unsafe { ffi::ts_tree_cursor_goto_first_child_for_byte(&mut self.0, index as u32) };
1678 (result >= 0).then_some(result as usize)
1679 }
1680
1681 #[doc(alias = "ts_tree_cursor_goto_first_child_for_point")]
1687 pub fn goto_first_child_for_point(&mut self, point: Point) -> Option<usize> {
1688 let result =
1689 unsafe { ffi::ts_tree_cursor_goto_first_child_for_point(&mut self.0, point.into()) };
1690 (result >= 0).then_some(result as usize)
1691 }
1692
1693 #[doc(alias = "ts_tree_cursor_reset")]
1696 pub fn reset(&mut self, node: Node<'cursor>) {
1697 unsafe { ffi::ts_tree_cursor_reset(&mut self.0, node.0) };
1698 }
1699
1700 #[doc(alias = "ts_tree_cursor_reset_to")]
1705 pub fn reset_to(&mut self, cursor: &Self) {
1706 unsafe { ffi::ts_tree_cursor_reset_to(&mut self.0, &cursor.0) };
1707 }
1708}
1709
1710impl Clone for TreeCursor<'_> {
1711 fn clone(&self) -> Self {
1712 TreeCursor(unsafe { ffi::ts_tree_cursor_copy(&self.0) }, PhantomData)
1713 }
1714}
1715
1716impl Drop for TreeCursor<'_> {
1717 fn drop(&mut self) {
1718 unsafe { ffi::ts_tree_cursor_delete(&mut self.0) }
1719 }
1720}
1721
1722impl LookaheadIterator {
1723 #[doc(alias = "ts_lookahead_iterator_language")]
1725 #[must_use]
1726 pub fn language(&self) -> LanguageRef<'_> {
1727 LanguageRef(
1728 unsafe { ffi::ts_lookahead_iterator_language(self.0.as_ptr()) },
1729 PhantomData,
1730 )
1731 }
1732
1733 #[doc(alias = "ts_lookahead_iterator_current_symbol")]
1735 #[must_use]
1736 pub fn current_symbol(&self) -> u16 {
1737 unsafe { ffi::ts_lookahead_iterator_current_symbol(self.0.as_ptr()) }
1738 }
1739
1740 #[doc(alias = "ts_lookahead_iterator_current_symbol_name")]
1742 #[must_use]
1743 pub fn current_symbol_name(&self) -> &'static str {
1744 unsafe {
1745 CStr::from_ptr(ffi::ts_lookahead_iterator_current_symbol_name(
1746 self.0.as_ptr(),
1747 ))
1748 .to_str()
1749 .unwrap()
1750 }
1751 }
1752
1753 #[doc(alias = "ts_lookahead_iterator_reset")]
1758 pub fn reset(&mut self, language: &Language, state: u16) -> bool {
1759 unsafe { ffi::ts_lookahead_iterator_reset(self.0.as_ptr(), language.0, state) }
1760 }
1761
1762 #[doc(alias = "ts_lookahead_iterator_reset_state")]
1767 pub fn reset_state(&mut self, state: u16) -> bool {
1768 unsafe { ffi::ts_lookahead_iterator_reset_state(self.0.as_ptr(), state) }
1769 }
1770
1771 pub fn iter_names(&mut self) -> impl Iterator<Item = &'static str> + '_ {
1773 LookaheadNamesIterator(self)
1774 }
1775}
1776
1777impl Iterator for LookaheadNamesIterator<'_> {
1778 type Item = &'static str;
1779
1780 #[doc(alias = "ts_lookahead_iterator_next")]
1781 fn next(&mut self) -> Option<Self::Item> {
1782 unsafe { ffi::ts_lookahead_iterator_next(self.0 .0.as_ptr()) }
1783 .then(|| self.0.current_symbol_name())
1784 }
1785}
1786
1787impl Iterator for LookaheadIterator {
1788 type Item = u16;
1789
1790 #[doc(alias = "ts_lookahead_iterator_next")]
1791 fn next(&mut self) -> Option<Self::Item> {
1792 unsafe { ffi::ts_lookahead_iterator_next(self.0.as_ptr()) }.then(|| self.current_symbol())
1794 }
1795}
1796
1797impl Drop for LookaheadIterator {
1798 #[doc(alias = "ts_lookahead_iterator_delete")]
1799 fn drop(&mut self) {
1800 unsafe { ffi::ts_lookahead_iterator_delete(self.0.as_ptr()) }
1801 }
1802}
1803
1804impl Query {
1805 pub fn new(language: &Language, source: &str) -> Result<Self, QueryError> {
1812 let mut error_offset = 0u32;
1813 let mut error_type: ffi::TSQueryError = 0;
1814 let bytes = source.as_bytes();
1815
1816 let ptr = unsafe {
1818 ffi::ts_query_new(
1819 language.0,
1820 bytes.as_ptr().cast::<c_char>(),
1821 bytes.len() as u32,
1822 core::ptr::addr_of_mut!(error_offset),
1823 core::ptr::addr_of_mut!(error_type),
1824 )
1825 };
1826
1827 if ptr.is_null() {
1829 if error_type == ffi::TSQueryErrorLanguage {
1830 return Err(QueryError {
1831 row: 0,
1832 column: 0,
1833 offset: 0,
1834 message: LanguageError {
1835 version: language.version(),
1836 }
1837 .to_string(),
1838 kind: QueryErrorKind::Language,
1839 });
1840 }
1841
1842 let offset = error_offset as usize;
1843 let mut line_start = 0;
1844 let mut row = 0;
1845 let mut line_containing_error = None;
1846 for line in source.lines() {
1847 let line_end = line_start + line.len() + 1;
1848 if line_end > offset {
1849 line_containing_error = Some(line);
1850 break;
1851 }
1852 line_start = line_end;
1853 row += 1;
1854 }
1855 let column = offset - line_start;
1856
1857 let kind;
1858 let message;
1859 match error_type {
1860 ffi::TSQueryErrorNodeType | ffi::TSQueryErrorField | ffi::TSQueryErrorCapture => {
1862 let suffix = source.split_at(offset).1;
1863 let in_quotes = source.as_bytes()[offset - 1] == b'"';
1864 let mut end_offset = suffix.len();
1865 if let Some(pos) = suffix
1866 .char_indices()
1867 .take_while(|(_, c)| *c != '\n')
1868 .find_map(|(i, c)| match c {
1869 '"' if in_quotes
1870 && i > 0
1871 && suffix.chars().nth(i - 1) != Some('\\') =>
1872 {
1873 Some(i)
1874 }
1875 c if !in_quotes
1876 && (c.is_whitespace() || c == '(' || c == ')' || c == ':') =>
1877 {
1878 Some(i)
1879 }
1880 _ => None,
1881 })
1882 {
1883 end_offset = pos;
1884 }
1885 message = suffix.split_at(end_offset).0.to_string();
1886 kind = match error_type {
1887 ffi::TSQueryErrorNodeType => QueryErrorKind::NodeType,
1888 ffi::TSQueryErrorField => QueryErrorKind::Field,
1889 ffi::TSQueryErrorCapture => QueryErrorKind::Capture,
1890 _ => unreachable!(),
1891 };
1892 }
1893
1894 _ => {
1896 message = line_containing_error.map_or_else(
1897 || "Unexpected EOF".to_string(),
1898 |line| line.to_string() + "\n" + &" ".repeat(offset - line_start) + "^",
1899 );
1900 kind = match error_type {
1901 ffi::TSQueryErrorStructure => QueryErrorKind::Structure,
1902 _ => QueryErrorKind::Syntax,
1903 };
1904 }
1905 };
1906
1907 return Err(QueryError {
1908 row,
1909 column,
1910 offset,
1911 message,
1912 kind,
1913 });
1914 }
1915
1916 unsafe { Self::from_raw_parts(ptr, source) }
1917 }
1918
1919 #[doc(hidden)]
1920 unsafe fn from_raw_parts(ptr: *mut ffi::TSQuery, source: &str) -> Result<Self, QueryError> {
1921 let ptr = {
1922 struct TSQueryDrop(*mut ffi::TSQuery);
1923 impl Drop for TSQueryDrop {
1924 fn drop(&mut self) {
1925 unsafe { ffi::ts_query_delete(self.0) }
1926 }
1927 }
1928 TSQueryDrop(ptr)
1929 };
1930
1931 let string_count = unsafe { ffi::ts_query_string_count(ptr.0) };
1932 let capture_count = unsafe { ffi::ts_query_capture_count(ptr.0) };
1933 let pattern_count = unsafe { ffi::ts_query_pattern_count(ptr.0) as usize };
1934
1935 let mut capture_names = Vec::with_capacity(capture_count as usize);
1936 let mut capture_quantifiers_vec = Vec::with_capacity(pattern_count as usize);
1937 let mut text_predicates_vec = Vec::with_capacity(pattern_count);
1938 let mut property_predicates_vec = Vec::with_capacity(pattern_count);
1939 let mut property_settings_vec = Vec::with_capacity(pattern_count);
1940 let mut general_predicates_vec = Vec::with_capacity(pattern_count);
1941
1942 for i in 0..capture_count {
1944 unsafe {
1945 let mut length = 0u32;
1946 let name =
1947 ffi::ts_query_capture_name_for_id(ptr.0, i, core::ptr::addr_of_mut!(length))
1948 .cast::<u8>();
1949 let name = slice::from_raw_parts(name, length as usize);
1950 let name = str::from_utf8_unchecked(name);
1951 capture_names.push(name);
1952 }
1953 }
1954
1955 for i in 0..pattern_count {
1957 let mut capture_quantifiers = Vec::with_capacity(capture_count as usize);
1958 for j in 0..capture_count {
1959 unsafe {
1960 let quantifier = ffi::ts_query_capture_quantifier_for_id(ptr.0, i as u32, j);
1961 capture_quantifiers.push(quantifier.into());
1962 }
1963 }
1964 capture_quantifiers_vec.push(capture_quantifiers.into());
1965 }
1966
1967 let string_values = (0..string_count)
1969 .map(|i| unsafe {
1970 let mut length = 0u32;
1971 let value =
1972 ffi::ts_query_string_value_for_id(ptr.0, i, core::ptr::addr_of_mut!(length))
1973 .cast::<u8>();
1974 let value = slice::from_raw_parts(value, length as usize);
1975 let value = str::from_utf8_unchecked(value);
1976 value
1977 })
1978 .collect::<Vec<_>>();
1979
1980 for i in 0..pattern_count {
1982 let predicate_steps = unsafe {
1983 let mut length = 0u32;
1984 let raw_predicates = ffi::ts_query_predicates_for_pattern(
1985 ptr.0,
1986 i as u32,
1987 core::ptr::addr_of_mut!(length),
1988 );
1989 (length > 0)
1990 .then(|| slice::from_raw_parts(raw_predicates, length as usize))
1991 .unwrap_or_default()
1992 };
1993
1994 let byte_offset = unsafe { ffi::ts_query_start_byte_for_pattern(ptr.0, i as u32) };
1995 let row = source
1996 .char_indices()
1997 .take_while(|(i, _)| *i < byte_offset as usize)
1998 .filter(|(_, c)| *c == '\n')
1999 .count();
2000
2001 use ffi::TSQueryPredicateStepType as T;
2002 const TYPE_DONE: T = ffi::TSQueryPredicateStepTypeDone;
2003 const TYPE_CAPTURE: T = ffi::TSQueryPredicateStepTypeCapture;
2004 const TYPE_STRING: T = ffi::TSQueryPredicateStepTypeString;
2005
2006 let mut text_predicates = Vec::new();
2007 let mut property_predicates = Vec::new();
2008 let mut property_settings = Vec::new();
2009 let mut general_predicates = Vec::new();
2010 for p in predicate_steps.split(|s| s.type_ == TYPE_DONE) {
2011 if p.is_empty() {
2012 continue;
2013 }
2014
2015 if p[0].type_ != TYPE_STRING {
2016 return Err(predicate_error(
2017 row,
2018 format!(
2019 "Expected predicate to start with a function name. Got @{}.",
2020 capture_names[p[0].value_id as usize],
2021 ),
2022 ));
2023 }
2024
2025 let operator_name = string_values[p[0].value_id as usize];
2027 match operator_name {
2028 "eq?" | "not-eq?" | "any-eq?" | "any-not-eq?" => {
2029 if p.len() != 3 {
2030 return Err(predicate_error(
2031 row,
2032 format!(
2033 "Wrong number of arguments to #eq? predicate. Expected 2, got {}.",
2034 p.len() - 1
2035 ),
2036 ));
2037 }
2038 if p[1].type_ != TYPE_CAPTURE {
2039 return Err(predicate_error(row, format!(
2040 "First argument to #eq? predicate must be a capture name. Got literal \"{}\".",
2041 string_values[p[1].value_id as usize],
2042 )));
2043 }
2044
2045 let is_positive = operator_name == "eq?" || operator_name == "any-eq?";
2046 let match_all = match operator_name {
2047 "eq?" | "not-eq?" => true,
2048 "any-eq?" | "any-not-eq?" => false,
2049 _ => unreachable!(),
2050 };
2051 text_predicates.push(if p[2].type_ == TYPE_CAPTURE {
2052 TextPredicateCapture::EqCapture(
2053 p[1].value_id,
2054 p[2].value_id,
2055 is_positive,
2056 match_all,
2057 )
2058 } else {
2059 TextPredicateCapture::EqString(
2060 p[1].value_id,
2061 string_values[p[2].value_id as usize].to_string().into(),
2062 is_positive,
2063 match_all,
2064 )
2065 });
2066 }
2067
2068 "match?" | "not-match?" | "any-match?" | "any-not-match?" => {
2069 if p.len() != 3 {
2070 return Err(predicate_error(row, format!(
2071 "Wrong number of arguments to #match? predicate. Expected 2, got {}.",
2072 p.len() - 1
2073 )));
2074 }
2075 if p[1].type_ != TYPE_CAPTURE {
2076 return Err(predicate_error(row, format!(
2077 "First argument to #match? predicate must be a capture name. Got literal \"{}\".",
2078 string_values[p[1].value_id as usize],
2079 )));
2080 }
2081 if p[2].type_ == TYPE_CAPTURE {
2082 return Err(predicate_error(row, format!(
2083 "Second argument to #match? predicate must be a literal. Got capture @{}.",
2084 capture_names[p[2].value_id as usize],
2085 )));
2086 }
2087
2088 let is_positive =
2089 operator_name == "match?" || operator_name == "any-match?";
2090 let match_all = match operator_name {
2091 "match?" | "not-match?" => true,
2092 "any-match?" | "any-not-match?" => false,
2093 _ => unreachable!(),
2094 };
2095 let regex = &string_values[p[2].value_id as usize];
2096 text_predicates.push(TextPredicateCapture::MatchString(
2097 p[1].value_id,
2098 regex::bytes::Regex::new(regex).map_err(|_| {
2099 predicate_error(row, format!("Invalid regex '{regex}'"))
2100 })?,
2101 is_positive,
2102 match_all,
2103 ));
2104 }
2105
2106 "set!" => property_settings.push(Self::parse_property(
2107 row,
2108 operator_name,
2109 &capture_names,
2110 &string_values,
2111 &p[1..],
2112 )?),
2113
2114 "is?" | "is-not?" => property_predicates.push((
2115 Self::parse_property(
2116 row,
2117 operator_name,
2118 &capture_names,
2119 &string_values,
2120 &p[1..],
2121 )?,
2122 operator_name == "is?",
2123 )),
2124
2125 "any-of?" | "not-any-of?" => {
2126 if p.len() < 2 {
2127 return Err(predicate_error(row, format!(
2128 "Wrong number of arguments to #any-of? predicate. Expected at least 1, got {}.",
2129 p.len() - 1
2130 )));
2131 }
2132 if p[1].type_ != TYPE_CAPTURE {
2133 return Err(predicate_error(row, format!(
2134 "First argument to #any-of? predicate must be a capture name. Got literal \"{}\".",
2135 string_values[p[1].value_id as usize],
2136 )));
2137 }
2138
2139 let is_positive = operator_name == "any-of?";
2140 let mut values = Vec::new();
2141 for arg in &p[2..] {
2142 if arg.type_ == TYPE_CAPTURE {
2143 return Err(predicate_error(row, format!(
2144 "Arguments to #any-of? predicate must be literals. Got capture @{}.",
2145 capture_names[arg.value_id as usize],
2146 )));
2147 }
2148 values.push(string_values[arg.value_id as usize]);
2149 }
2150 text_predicates.push(TextPredicateCapture::AnyString(
2151 p[1].value_id,
2152 values
2153 .iter()
2154 .map(|x| (*x).to_string().into())
2155 .collect::<Vec<_>>()
2156 .into(),
2157 is_positive,
2158 ));
2159 }
2160
2161 _ => general_predicates.push(QueryPredicate {
2162 operator: operator_name.to_string().into(),
2163 args: p[1..]
2164 .iter()
2165 .map(|a| {
2166 if a.type_ == TYPE_CAPTURE {
2167 QueryPredicateArg::Capture(a.value_id)
2168 } else {
2169 QueryPredicateArg::String(
2170 string_values[a.value_id as usize].to_string().into(),
2171 )
2172 }
2173 })
2174 .collect(),
2175 }),
2176 }
2177 }
2178
2179 text_predicates_vec.push(text_predicates.into());
2180 property_predicates_vec.push(property_predicates.into());
2181 property_settings_vec.push(property_settings.into());
2182 general_predicates_vec.push(general_predicates.into());
2183 }
2184
2185 let result = Self {
2186 ptr: unsafe { NonNull::new_unchecked(ptr.0) },
2187 capture_names: capture_names.into(),
2188 capture_quantifiers: capture_quantifiers_vec.into(),
2189 text_predicates: text_predicates_vec.into(),
2190 property_predicates: property_predicates_vec.into(),
2191 property_settings: property_settings_vec.into(),
2192 general_predicates: general_predicates_vec.into(),
2193 };
2194
2195 core::mem::forget(ptr);
2196
2197 Ok(result)
2198 }
2199
2200 #[doc(alias = "ts_query_start_byte_for_pattern")]
2203 #[must_use]
2204 pub fn start_byte_for_pattern(&self, pattern_index: usize) -> usize {
2205 assert!(
2206 pattern_index < self.text_predicates.len(),
2207 "Pattern index is {pattern_index} but the pattern count is {}",
2208 self.text_predicates.len(),
2209 );
2210 unsafe {
2211 ffi::ts_query_start_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize
2212 }
2213 }
2214
2215 #[doc(alias = "ts_query_end_byte_for_pattern")]
2218 #[must_use]
2219 pub fn end_byte_for_pattern(&self, pattern_index: usize) -> usize {
2220 assert!(
2221 pattern_index < self.text_predicates.len(),
2222 "Pattern index is {pattern_index} but the pattern count is {}",
2223 self.text_predicates.len(),
2224 );
2225 unsafe {
2226 ffi::ts_query_end_byte_for_pattern(self.ptr.as_ptr(), pattern_index as u32) as usize
2227 }
2228 }
2229
2230 #[doc(alias = "ts_query_pattern_count")]
2232 #[must_use]
2233 pub fn pattern_count(&self) -> usize {
2234 unsafe { ffi::ts_query_pattern_count(self.ptr.as_ptr()) as usize }
2235 }
2236
2237 #[must_use]
2239 pub const fn capture_names(&self) -> &[&str] {
2240 &self.capture_names
2241 }
2242
2243 #[must_use]
2245 pub const fn capture_quantifiers(&self, index: usize) -> &[CaptureQuantifier] {
2246 &self.capture_quantifiers[index]
2247 }
2248
2249 #[must_use]
2251 pub fn capture_index_for_name(&self, name: &str) -> Option<u32> {
2252 self.capture_names
2253 .iter()
2254 .position(|n| *n == name)
2255 .map(|ix| ix as u32)
2256 }
2257
2258 #[must_use]
2262 pub const fn property_predicates(&self, index: usize) -> &[(QueryProperty, bool)] {
2263 &self.property_predicates[index]
2264 }
2265
2266 #[must_use]
2270 pub const fn property_settings(&self, index: usize) -> &[QueryProperty] {
2271 &self.property_settings[index]
2272 }
2273
2274 #[must_use]
2282 pub const fn general_predicates(&self, index: usize) -> &[QueryPredicate] {
2283 &self.general_predicates[index]
2284 }
2285
2286 #[doc(alias = "ts_query_disable_capture")]
2291 pub fn disable_capture(&mut self, name: &str) {
2292 unsafe {
2293 ffi::ts_query_disable_capture(
2294 self.ptr.as_ptr(),
2295 name.as_bytes().as_ptr().cast::<c_char>(),
2296 name.len() as u32,
2297 );
2298 }
2299 }
2300
2301 #[doc(alias = "ts_query_disable_pattern")]
2306 pub fn disable_pattern(&mut self, index: usize) {
2307 unsafe { ffi::ts_query_disable_pattern(self.ptr.as_ptr(), index as u32) }
2308 }
2309
2310 #[doc(alias = "ts_query_is_pattern_rooted")]
2312 #[must_use]
2313 pub fn is_pattern_rooted(&self, index: usize) -> bool {
2314 unsafe { ffi::ts_query_is_pattern_rooted(self.ptr.as_ptr(), index as u32) }
2315 }
2316
2317 #[doc(alias = "ts_query_is_pattern_non_local")]
2319 #[must_use]
2320 pub fn is_pattern_non_local(&self, index: usize) -> bool {
2321 unsafe { ffi::ts_query_is_pattern_non_local(self.ptr.as_ptr(), index as u32) }
2322 }
2323
2324 #[doc(alias = "ts_query_is_pattern_guaranteed_at_step")]
2329 #[must_use]
2330 pub fn is_pattern_guaranteed_at_step(&self, byte_offset: usize) -> bool {
2331 unsafe {
2332 ffi::ts_query_is_pattern_guaranteed_at_step(self.ptr.as_ptr(), byte_offset as u32)
2333 }
2334 }
2335
2336 fn parse_property(
2337 row: usize,
2338 function_name: &str,
2339 capture_names: &[&str],
2340 string_values: &[&str],
2341 args: &[ffi::TSQueryPredicateStep],
2342 ) -> Result<QueryProperty, QueryError> {
2343 if args.is_empty() || args.len() > 3 {
2344 return Err(predicate_error(
2345 row,
2346 format!(
2347 "Wrong number of arguments to {function_name} predicate. Expected 1 to 3, got {}.",
2348 args.len(),
2349 ),
2350 ));
2351 }
2352
2353 let mut capture_id = None;
2354 let mut key = None;
2355 let mut value = None;
2356
2357 for arg in args {
2358 if arg.type_ == ffi::TSQueryPredicateStepTypeCapture {
2359 if capture_id.is_some() {
2360 return Err(predicate_error(
2361 row,
2362 format!(
2363 "Invalid arguments to {function_name} predicate. Unexpected second capture name @{}",
2364 capture_names[arg.value_id as usize]
2365 ),
2366 ));
2367 }
2368 capture_id = Some(arg.value_id as usize);
2369 } else if key.is_none() {
2370 key = Some(&string_values[arg.value_id as usize]);
2371 } else if value.is_none() {
2372 value = Some(string_values[arg.value_id as usize]);
2373 } else {
2374 return Err(predicate_error(
2375 row,
2376 format!(
2377 "Invalid arguments to {function_name} predicate. Unexpected third argument @{}",
2378 string_values[arg.value_id as usize]
2379 ),
2380 ));
2381 }
2382 }
2383
2384 if let Some(key) = key {
2385 Ok(QueryProperty::new(key, value, capture_id))
2386 } else {
2387 Err(predicate_error(
2388 row,
2389 format!("Invalid arguments to {function_name} predicate. Missing key argument",),
2390 ))
2391 }
2392 }
2393}
2394
2395impl Default for QueryCursor {
2396 fn default() -> Self {
2397 Self::new()
2398 }
2399}
2400
2401impl QueryCursor {
2402 #[doc(alias = "ts_query_cursor_new")]
2407 #[must_use]
2408 pub fn new() -> Self {
2409 Self {
2410 ptr: unsafe { NonNull::new_unchecked(ffi::ts_query_cursor_new()) },
2411 }
2412 }
2413
2414 #[doc(alias = "ts_query_cursor_match_limit")]
2416 #[must_use]
2417 pub fn match_limit(&self) -> u32 {
2418 unsafe { ffi::ts_query_cursor_match_limit(self.ptr.as_ptr()) }
2419 }
2420
2421 #[doc(alias = "ts_query_cursor_set_match_limit")]
2424 pub fn set_match_limit(&mut self, limit: u32) {
2425 unsafe {
2426 ffi::ts_query_cursor_set_match_limit(self.ptr.as_ptr(), limit);
2427 }
2428 }
2429
2430 #[doc(alias = "ts_query_cursor_set_timeout_micros")]
2435 pub fn set_timeout_micros(&mut self, timeout: u64) {
2436 unsafe {
2437 ffi::ts_query_cursor_set_timeout_micros(self.ptr.as_ptr(), timeout);
2438 }
2439 }
2440
2441 #[doc(alias = "ts_query_cursor_timeout_micros")]
2445 #[must_use]
2446 pub fn timeout_micros(&self) -> u64 {
2447 unsafe { ffi::ts_query_cursor_timeout_micros(self.ptr.as_ptr()) }
2448 }
2449
2450 #[doc(alias = "ts_query_cursor_did_exceed_match_limit")]
2453 #[must_use]
2454 pub fn did_exceed_match_limit(&self) -> bool {
2455 unsafe { ffi::ts_query_cursor_did_exceed_match_limit(self.ptr.as_ptr()) }
2456 }
2457
2458 #[doc(alias = "ts_query_cursor_exec")]
2465 pub fn matches<'query, 'cursor: 'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>>(
2466 &'cursor mut self,
2467 query: &'query Query,
2468 node: Node<'tree>,
2469 text_provider: T,
2470 ) -> QueryMatches<'query, 'tree, T, I> {
2471 let ptr = self.ptr.as_ptr();
2472 unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) };
2473 QueryMatches {
2474 ptr,
2475 query,
2476 text_provider,
2477 buffer1: Vec::default(),
2478 buffer2: Vec::default(),
2479 current_match: None,
2480 _phantom: PhantomData,
2481 }
2482 }
2483
2484 #[doc(alias = "ts_query_cursor_exec")]
2490 pub fn captures<'query, 'cursor: 'query, 'tree, T: TextProvider<I>, I: AsRef<[u8]>>(
2491 &'cursor mut self,
2492 query: &'query Query,
2493 node: Node<'tree>,
2494 text_provider: T,
2495 ) -> QueryCaptures<'query, 'tree, T, I> {
2496 let ptr = self.ptr.as_ptr();
2497 unsafe { ffi::ts_query_cursor_exec(ptr, query.ptr.as_ptr(), node.0) };
2498 QueryCaptures {
2499 ptr,
2500 query,
2501 text_provider,
2502 buffer1: Vec::default(),
2503 buffer2: Vec::default(),
2504 current_match: None,
2505 _phantom: PhantomData,
2506 }
2507 }
2508
2509 #[doc(alias = "ts_query_cursor_set_byte_range")]
2512 pub fn set_byte_range(&mut self, range: ops::Range<usize>) -> &mut Self {
2513 unsafe {
2514 ffi::ts_query_cursor_set_byte_range(
2515 self.ptr.as_ptr(),
2516 range.start as u32,
2517 range.end as u32,
2518 );
2519 }
2520 self
2521 }
2522
2523 #[doc(alias = "ts_query_cursor_set_point_range")]
2526 pub fn set_point_range(&mut self, range: ops::Range<Point>) -> &mut Self {
2527 unsafe {
2528 ffi::ts_query_cursor_set_point_range(
2529 self.ptr.as_ptr(),
2530 range.start.into(),
2531 range.end.into(),
2532 );
2533 }
2534 self
2535 }
2536
2537 #[doc(alias = "ts_query_cursor_set_max_start_depth")]
2552 pub fn set_max_start_depth(&mut self, max_start_depth: Option<u32>) -> &mut Self {
2553 unsafe {
2554 ffi::ts_query_cursor_set_max_start_depth(
2555 self.ptr.as_ptr(),
2556 max_start_depth.unwrap_or(u32::MAX),
2557 );
2558 }
2559 self
2560 }
2561}
2562
2563impl<'tree> QueryMatch<'_, 'tree> {
2564 #[must_use]
2565 pub const fn id(&self) -> u32 {
2566 self.id
2567 }
2568
2569 #[doc(alias = "ts_query_cursor_remove_match")]
2570 pub fn remove(&self) {
2571 unsafe { ffi::ts_query_cursor_remove_match(self.cursor, self.id) }
2572 }
2573
2574 pub fn nodes_for_capture_index(
2575 &self,
2576 capture_ix: u32,
2577 ) -> impl Iterator<Item = Node<'tree>> + '_ {
2578 self.captures
2579 .iter()
2580 .filter_map(move |capture| (capture.index == capture_ix).then_some(capture.node))
2581 }
2582
2583 fn new(m: &ffi::TSQueryMatch, cursor: *mut ffi::TSQueryCursor) -> Self {
2584 QueryMatch {
2585 cursor,
2586 id: m.id,
2587 pattern_index: m.pattern_index as usize,
2588 captures: (m.capture_count > 0)
2589 .then(|| unsafe {
2590 slice::from_raw_parts(
2591 m.captures.cast::<QueryCapture<'tree>>(),
2592 m.capture_count as usize,
2593 )
2594 })
2595 .unwrap_or_default(),
2596 }
2597 }
2598
2599 pub fn satisfies_text_predicates<I: AsRef<[u8]>>(
2600 &self,
2601 query: &Query,
2602 buffer1: &mut Vec<u8>,
2603 buffer2: &mut Vec<u8>,
2604 text_provider: &mut impl TextProvider<I>,
2605 ) -> bool {
2606 struct NodeText<'a, T> {
2607 buffer: &'a mut Vec<u8>,
2608 first_chunk: Option<T>,
2609 }
2610 impl<'a, T: AsRef<[u8]>> NodeText<'a, T> {
2611 fn new(buffer: &'a mut Vec<u8>) -> Self {
2612 Self {
2613 buffer,
2614 first_chunk: None,
2615 }
2616 }
2617
2618 fn get_text(&mut self, chunks: &mut impl Iterator<Item = T>) -> &[u8] {
2619 self.first_chunk = chunks.next();
2620 if let Some(next_chunk) = chunks.next() {
2621 self.buffer.clear();
2622 self.buffer
2623 .extend_from_slice(self.first_chunk.as_ref().unwrap().as_ref());
2624 self.buffer.extend_from_slice(next_chunk.as_ref());
2625 for chunk in chunks {
2626 self.buffer.extend_from_slice(chunk.as_ref());
2627 }
2628 self.buffer.as_slice()
2629 } else if let Some(ref first_chunk) = self.first_chunk {
2630 first_chunk.as_ref()
2631 } else {
2632 &[]
2633 }
2634 }
2635 }
2636
2637 let mut node_text1 = NodeText::new(buffer1);
2638 let mut node_text2 = NodeText::new(buffer2);
2639
2640 query.text_predicates[self.pattern_index]
2641 .iter()
2642 .all(|predicate| match predicate {
2643 TextPredicateCapture::EqCapture(i, j, is_positive, match_all_nodes) => {
2644 let mut nodes_1 = self.nodes_for_capture_index(*i);
2645 let mut nodes_2 = self.nodes_for_capture_index(*j);
2646 while let (Some(node1), Some(node2)) = (nodes_1.next(), nodes_2.next()) {
2647 let mut text1 = text_provider.text(node1);
2648 let mut text2 = text_provider.text(node2);
2649 let text1 = node_text1.get_text(&mut text1);
2650 let text2 = node_text2.get_text(&mut text2);
2651 let is_positive_match = text1 == text2;
2652 if is_positive_match != *is_positive && *match_all_nodes {
2653 return false;
2654 }
2655 if is_positive_match == *is_positive && !*match_all_nodes {
2656 return true;
2657 }
2658 }
2659 nodes_1.next().is_none() && nodes_2.next().is_none()
2660 }
2661 TextPredicateCapture::EqString(i, s, is_positive, match_all_nodes) => {
2662 let nodes = self.nodes_for_capture_index(*i);
2663 for node in nodes {
2664 let mut text = text_provider.text(node);
2665 let text = node_text1.get_text(&mut text);
2666 let is_positive_match = text == s.as_bytes();
2667 if is_positive_match != *is_positive && *match_all_nodes {
2668 return false;
2669 }
2670 if is_positive_match == *is_positive && !*match_all_nodes {
2671 return true;
2672 }
2673 }
2674 true
2675 }
2676 TextPredicateCapture::MatchString(i, r, is_positive, match_all_nodes) => {
2677 let nodes = self.nodes_for_capture_index(*i);
2678 for node in nodes {
2679 let mut text = text_provider.text(node);
2680 let text = node_text1.get_text(&mut text);
2681 let is_positive_match = r.is_match(text);
2682 if is_positive_match != *is_positive && *match_all_nodes {
2683 return false;
2684 }
2685 if is_positive_match == *is_positive && !*match_all_nodes {
2686 return true;
2687 }
2688 }
2689 true
2690 }
2691 TextPredicateCapture::AnyString(i, v, is_positive) => {
2692 let nodes = self.nodes_for_capture_index(*i);
2693 for node in nodes {
2694 let mut text = text_provider.text(node);
2695 let text = node_text1.get_text(&mut text);
2696 if (v.iter().any(|s| text == s.as_bytes())) != *is_positive {
2697 return false;
2698 }
2699 }
2700 true
2701 }
2702 })
2703 }
2704}
2705
2706impl QueryProperty {
2707 #[must_use]
2708 pub fn new(key: &str, value: Option<&str>, capture_id: Option<usize>) -> Self {
2709 Self {
2710 capture_id,
2711 key: key.to_string().into(),
2712 value: value.map(|s| s.to_string().into()),
2713 }
2714 }
2715}
2716
2717impl<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIterator
2721 for QueryMatches<'query, 'tree, T, I>
2722{
2723 type Item = QueryMatch<'query, 'tree>;
2724
2725 fn advance(&mut self) {
2726 self.current_match = unsafe {
2727 loop {
2728 let mut m = MaybeUninit::<ffi::TSQueryMatch>::uninit();
2729 if ffi::ts_query_cursor_next_match(self.ptr, m.as_mut_ptr()) {
2730 let result = QueryMatch::new(&m.assume_init(), self.ptr);
2731 if result.satisfies_text_predicates(
2732 self.query,
2733 &mut self.buffer1,
2734 &mut self.buffer2,
2735 &mut self.text_provider,
2736 ) {
2737 break Some(result);
2738 }
2739 } else {
2740 break None;
2741 }
2742 }
2743 };
2744 }
2745
2746 fn get(&self) -> Option<&Self::Item> {
2747 self.current_match.as_ref()
2748 }
2749}
2750
2751impl<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIteratorMut
2752 for QueryMatches<'query, 'tree, T, I>
2753{
2754 fn get_mut(&mut self) -> Option<&mut Self::Item> {
2755 self.current_match.as_mut()
2756 }
2757}
2758
2759impl<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIterator
2760 for QueryCaptures<'query, 'tree, T, I>
2761{
2762 type Item = (QueryMatch<'query, 'tree>, usize);
2763
2764 fn advance(&mut self) {
2765 self.current_match = unsafe {
2766 loop {
2767 let mut capture_index = 0u32;
2768 let mut m = MaybeUninit::<ffi::TSQueryMatch>::uninit();
2769 if ffi::ts_query_cursor_next_capture(
2770 self.ptr,
2771 m.as_mut_ptr(),
2772 core::ptr::addr_of_mut!(capture_index),
2773 ) {
2774 let result = QueryMatch::new(&m.assume_init(), self.ptr);
2775 if result.satisfies_text_predicates(
2776 self.query,
2777 &mut self.buffer1,
2778 &mut self.buffer2,
2779 &mut self.text_provider,
2780 ) {
2781 break Some((result, capture_index as usize));
2782 }
2783 result.remove();
2784 } else {
2785 break None;
2786 }
2787 }
2788 }
2789 }
2790
2791 fn get(&self) -> Option<&Self::Item> {
2792 self.current_match.as_ref()
2793 }
2794}
2795
2796impl<'query, 'tree: 'query, T: TextProvider<I>, I: AsRef<[u8]>> StreamingIteratorMut
2797 for QueryCaptures<'query, 'tree, T, I>
2798{
2799 fn get_mut(&mut self) -> Option<&mut Self::Item> {
2800 self.current_match.as_mut()
2801 }
2802}
2803
2804impl<T: TextProvider<I>, I: AsRef<[u8]>> QueryMatches<'_, '_, T, I> {
2805 #[doc(alias = "ts_query_cursor_set_byte_range")]
2806 pub fn set_byte_range(&mut self, range: ops::Range<usize>) {
2807 unsafe {
2808 ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32);
2809 }
2810 }
2811
2812 #[doc(alias = "ts_query_cursor_set_point_range")]
2813 pub fn set_point_range(&mut self, range: ops::Range<Point>) {
2814 unsafe {
2815 ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into());
2816 }
2817 }
2818}
2819
2820impl<T: TextProvider<I>, I: AsRef<[u8]>> QueryCaptures<'_, '_, T, I> {
2821 #[doc(alias = "ts_query_cursor_set_byte_range")]
2822 pub fn set_byte_range(&mut self, range: ops::Range<usize>) {
2823 unsafe {
2824 ffi::ts_query_cursor_set_byte_range(self.ptr, range.start as u32, range.end as u32);
2825 }
2826 }
2827
2828 #[doc(alias = "ts_query_cursor_set_point_range")]
2829 pub fn set_point_range(&mut self, range: ops::Range<Point>) {
2830 unsafe {
2831 ffi::ts_query_cursor_set_point_range(self.ptr, range.start.into(), range.end.into());
2832 }
2833 }
2834}
2835
2836impl fmt::Debug for QueryMatch<'_, '_> {
2837 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2838 write!(
2839 f,
2840 "QueryMatch {{ id: {}, pattern_index: {}, captures: {:?} }}",
2841 self.id, self.pattern_index, self.captures
2842 )
2843 }
2844}
2845
2846impl<F, R, I> TextProvider<I> for F
2847where
2848 F: FnMut(Node) -> R,
2849 R: Iterator<Item = I>,
2850 I: AsRef<[u8]>,
2851{
2852 type I = R;
2853
2854 fn text(&mut self, node: Node) -> Self::I {
2855 (self)(node)
2856 }
2857}
2858
2859impl<'a> TextProvider<&'a [u8]> for &'a [u8] {
2860 type I = iter::Once<&'a [u8]>;
2861
2862 fn text(&mut self, node: Node) -> Self::I {
2863 iter::once(&self[node.byte_range()])
2864 }
2865}
2866
2867impl PartialEq for Query {
2868 fn eq(&self, other: &Self) -> bool {
2869 self.ptr == other.ptr
2870 }
2871}
2872
2873impl Drop for Query {
2874 fn drop(&mut self) {
2875 unsafe { ffi::ts_query_delete(self.ptr.as_ptr()) }
2876 }
2877}
2878
2879impl Drop for QueryCursor {
2880 fn drop(&mut self) {
2881 unsafe { ffi::ts_query_cursor_delete(self.ptr.as_ptr()) }
2882 }
2883}
2884
2885impl Point {
2886 #[must_use]
2887 pub const fn new(row: usize, column: usize) -> Self {
2888 Self { row, column }
2889 }
2890}
2891
2892impl fmt::Display for Point {
2893 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2894 write!(f, "({}, {})", self.row, self.column)
2895 }
2896}
2897
2898impl From<Point> for ffi::TSPoint {
2899 fn from(val: Point) -> Self {
2900 Self {
2901 row: val.row as u32,
2902 column: val.column as u32,
2903 }
2904 }
2905}
2906
2907impl From<ffi::TSPoint> for Point {
2908 fn from(point: ffi::TSPoint) -> Self {
2909 Self {
2910 row: point.row as usize,
2911 column: point.column as usize,
2912 }
2913 }
2914}
2915
2916impl From<Range> for ffi::TSRange {
2917 fn from(val: Range) -> Self {
2918 Self {
2919 start_byte: val.start_byte as u32,
2920 end_byte: val.end_byte as u32,
2921 start_point: val.start_point.into(),
2922 end_point: val.end_point.into(),
2923 }
2924 }
2925}
2926
2927impl From<ffi::TSRange> for Range {
2928 fn from(range: ffi::TSRange) -> Self {
2929 Self {
2930 start_byte: range.start_byte as usize,
2931 end_byte: range.end_byte as usize,
2932 start_point: range.start_point.into(),
2933 end_point: range.end_point.into(),
2934 }
2935 }
2936}
2937
2938impl From<&'_ InputEdit> for ffi::TSInputEdit {
2939 fn from(val: &'_ InputEdit) -> Self {
2940 Self {
2941 start_byte: val.start_byte as u32,
2942 old_end_byte: val.old_end_byte as u32,
2943 new_end_byte: val.new_end_byte as u32,
2944 start_point: val.start_position.into(),
2945 old_end_point: val.old_end_position.into(),
2946 new_end_point: val.new_end_position.into(),
2947 }
2948 }
2949}
2950
2951impl<'a> LossyUtf8<'a> {
2952 #[must_use]
2953 pub const fn new(bytes: &'a [u8]) -> Self {
2954 LossyUtf8 {
2955 bytes,
2956 in_replacement: false,
2957 }
2958 }
2959}
2960
2961impl<'a> Iterator for LossyUtf8<'a> {
2962 type Item = &'a str;
2963
2964 fn next(&mut self) -> Option<&'a str> {
2965 if self.bytes.is_empty() {
2966 return None;
2967 }
2968 if self.in_replacement {
2969 self.in_replacement = false;
2970 return Some("\u{fffd}");
2971 }
2972 match core::str::from_utf8(self.bytes) {
2973 Ok(valid) => {
2974 self.bytes = &[];
2975 Some(valid)
2976 }
2977 Err(error) => {
2978 if let Some(error_len) = error.error_len() {
2979 let error_start = error.valid_up_to();
2980 if error_start > 0 {
2981 let result =
2982 unsafe { core::str::from_utf8_unchecked(&self.bytes[..error_start]) };
2983 self.bytes = &self.bytes[(error_start + error_len)..];
2984 self.in_replacement = true;
2985 Some(result)
2986 } else {
2987 self.bytes = &self.bytes[error_len..];
2988 Some("\u{fffd}")
2989 }
2990 } else {
2991 None
2992 }
2993 }
2994 }
2995 }
2996}
2997
2998#[must_use]
2999const fn predicate_error(row: usize, message: String) -> QueryError {
3000 QueryError {
3001 kind: QueryErrorKind::Predicate,
3002 row,
3003 column: 0,
3004 offset: 0,
3005 message,
3006 }
3007}
3008
3009impl fmt::Display for IncludedRangesError {
3010 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3011 write!(f, "Incorrect range by index: {}", self.0)
3012 }
3013}
3014
3015impl fmt::Display for LanguageError {
3016 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3017 write!(
3018 f,
3019 "Incompatible language version {}. Expected minimum {}, maximum {}",
3020 self.version, MIN_COMPATIBLE_LANGUAGE_VERSION, LANGUAGE_VERSION,
3021 )
3022 }
3023}
3024
3025impl fmt::Display for QueryError {
3026 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
3027 let msg = match self.kind {
3028 QueryErrorKind::Field => "Invalid field name ",
3029 QueryErrorKind::NodeType => "Invalid node type ",
3030 QueryErrorKind::Capture => "Invalid capture name ",
3031 QueryErrorKind::Predicate => "Invalid predicate: ",
3032 QueryErrorKind::Structure => "Impossible pattern:\n",
3033 QueryErrorKind::Syntax => "Invalid syntax:\n",
3034 QueryErrorKind::Language => "",
3035 };
3036 if msg.is_empty() {
3037 write!(f, "{}", self.message)
3038 } else {
3039 write!(
3040 f,
3041 "Query error at {}:{}. {}{}",
3042 self.row + 1,
3043 self.column + 1,
3044 msg,
3045 self.message
3046 )
3047 }
3048 }
3049}
3050
3051#[doc(hidden)]
3052#[must_use]
3053pub fn format_sexp(sexp: &str, initial_indent_level: usize) -> String {
3054 let mut indent_level = initial_indent_level;
3055 let mut formatted = String::new();
3056 let mut has_field = false;
3057
3058 let mut c_iter = sexp.chars().peekable();
3059 let mut s = String::with_capacity(sexp.len());
3060 let mut quote = '\0';
3061 let mut saw_paren = false;
3062 let mut did_last = false;
3063
3064 let mut fetch_next_str = |next: &mut String| {
3065 next.clear();
3066 while let Some(c) = c_iter.next() {
3067 if c == '\'' || c == '"' {
3068 quote = c;
3069 } else if c == ' ' || (c == ')' && quote != '\0') {
3070 if let Some(next_c) = c_iter.peek() {
3071 if *next_c == quote {
3072 next.push(c);
3073 next.push(*next_c);
3074 c_iter.next();
3075 quote = '\0';
3076 continue;
3077 }
3078 }
3079 break;
3080 }
3081 if c == ')' {
3082 saw_paren = true;
3083 break;
3084 }
3085 next.push(c);
3086 }
3087
3088 if c_iter.peek().is_none() && next.is_empty() {
3090 if saw_paren {
3091 saw_paren = false;
3093 return Some(());
3094 }
3095 if !did_last {
3096 did_last = true;
3098 return Some(());
3099 }
3100 return None;
3101 }
3102 Some(())
3103 };
3104
3105 while fetch_next_str(&mut s).is_some() {
3106 if s.is_empty() && indent_level > 0 {
3107 indent_level -= 1;
3109 write!(formatted, ")").unwrap();
3110 } else if s.starts_with('(') {
3111 if has_field {
3112 has_field = false;
3113 } else {
3114 if indent_level > 0 {
3115 writeln!(formatted).unwrap();
3116 for _ in 0..indent_level {
3117 write!(formatted, " ").unwrap();
3118 }
3119 }
3120 indent_level += 1;
3121 }
3122
3123 write!(formatted, "{s}").unwrap();
3125
3126 if s.starts_with("(MISSING") || s.starts_with("(UNEXPECTED") {
3128 fetch_next_str(&mut s).unwrap();
3129 if s.is_empty() {
3130 while indent_level > 0 {
3131 indent_level -= 1;
3132 write!(formatted, ")").unwrap();
3133 }
3134 } else {
3135 write!(formatted, " {s}").unwrap();
3136 }
3137 }
3138 } else if s.ends_with(':') {
3139 writeln!(formatted).unwrap();
3141 for _ in 0..indent_level {
3142 write!(formatted, " ").unwrap();
3143 }
3144 write!(formatted, "{s} ").unwrap();
3145 has_field = true;
3146 indent_level += 1;
3147 }
3148 }
3149
3150 formatted
3151}
3152
3153pub fn wasm_stdlib_symbols() -> impl Iterator<Item = &'static str> {
3154 const WASM_STDLIB_SYMBOLS: &str = include_str!(concat!(env!("OUT_DIR"), "/stdlib-symbols.txt"));
3155
3156 WASM_STDLIB_SYMBOLS
3157 .lines()
3158 .map(|s| s.trim_matches(|c| c == '"' || c == ','))
3159}
3160
3161#[doc(alias = "ts_set_allocator")]
3167pub unsafe fn set_allocator(
3168 new_malloc: Option<unsafe extern "C" fn(usize) -> *mut c_void>,
3169 new_calloc: Option<unsafe extern "C" fn(usize, usize) -> *mut c_void>,
3170 new_realloc: Option<unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void>,
3171 new_free: Option<unsafe extern "C" fn(*mut c_void)>,
3172) {
3173 ffi::ts_set_allocator(new_malloc, new_calloc, new_realloc, new_free);
3174}
3175
3176#[cfg(feature = "std")]
3177impl error::Error for IncludedRangesError {}
3178#[cfg(feature = "std")]
3179impl error::Error for LanguageError {}
3180#[cfg(feature = "std")]
3181impl error::Error for QueryError {}
3182
3183unsafe impl Send for Language {}
3184unsafe impl Sync for Language {}
3185
3186unsafe impl Send for Node<'_> {}
3187unsafe impl Sync for Node<'_> {}
3188
3189unsafe impl Send for LookaheadIterator {}
3190unsafe impl Sync for LookaheadIterator {}
3191
3192unsafe impl Send for LookaheadNamesIterator<'_> {}
3193unsafe impl Sync for LookaheadNamesIterator<'_> {}
3194
3195unsafe impl Send for Parser {}
3196unsafe impl Sync for Parser {}
3197
3198unsafe impl Send for Query {}
3199unsafe impl Sync for Query {}
3200
3201unsafe impl Send for QueryCursor {}
3202unsafe impl Sync for QueryCursor {}
3203
3204unsafe impl Send for Tree {}
3205unsafe impl Sync for Tree {}
3206
3207unsafe impl Send for TreeCursor<'_> {}
3208unsafe impl Sync for TreeCursor<'_> {}