### next_state example Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.LanguageRef.html Example of using the next_state method to get the next parse state. ```rust let state = language.next_state(node.parse_state(), node.grammar_id()); ``` -------------------------------- ### iter() example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of the `iter()` method on an Option, showing how to get an iterator over the contained value. ```rust let x = Some(4); assert_eq!(x.iter().next(), Some(&4)); let x: Option = None; assert_eq!(x.iter().next(), None); ``` -------------------------------- ### From Example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Example showing how to create an Option from a value using `Option::from`. ```Rust let o: Option = Option::from(67); assert_eq!(Some(67), o); ``` -------------------------------- ### insert() example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of the `insert()` method on a mutable Option, showing how to insert a value and get a mutable reference to it. ```rust let mut opt = None; let val = opt.insert(1); assert_eq!(*val, 1); assert_eq!(opt.unwrap(), 1); let val = opt.insert(2); assert_eq!(*val, 2); *val = 3; assert_eq!(opt.unwrap(), 3); ``` -------------------------------- ### Context Example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Example showing how to use the `context` and `with_context` methods from the `anyhow` crate to add context to Option values. ```Rust use anyhow::{Context, Result}; fn maybe_get() -> Option { ... } fn demo() -> Result<()> { let t = maybe_get().context("there is no T")?; ... } ``` -------------------------------- ### expect example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of `expect` for Option. ```rust let x = Some("value"); assert_eq!(x.expect("fruits are healthy"), "value"); ``` ```rust let x: Option<&str> = None; x.expect("fruits are healthy"); // panics with `fruits are healthy` ``` ```rust let item = slice.get(0) .expect("slice should not be empty"); ``` -------------------------------- ### Get a list of all supertype symbols for the language. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get a list of all supertype symbols for the language. ```rust pub fn supertypes(&self) -> &[u16] ``` -------------------------------- ### iter_mut() example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of the `iter_mut()` method on an Option, showing how to get a mutable iterator over the contained value. ```rust let mut x = Some(4); match x.iter_mut().next() { Some(v) => *v = 42, None => {}, } assert_eq!(x, Some(42)); let mut x: Option = None; assert_eq!(x.iter_mut().next(), None); ``` -------------------------------- ### Get the metadata for this language. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get the metadata for this language. This information is generated by the CLI, and relies on the language author providing the correct metadata in the language’s `tree-sitter.json` file. See also `LanguageMetadata`. ```rust pub fn metadata(&self) -> Option ``` -------------------------------- ### as_slice example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of `as_slice` for Option. ```rust assert_eq!( [Some(1234).as_slice(), None.as_slice()], [&[1234][..], &[][..]], ); ``` ```rust for i in [Some(1234_u16), None] { assert_eq!(i.as_ref(), i.as_slice().first()); } ``` -------------------------------- ### map example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of `map` for Option. -------------------------------- ### unwrap example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of `unwrap` for Option. ```rust let x = Some("air"); assert_eq!(x.unwrap(), "air"); ``` ```rust let x: Option<&str> = None; assert_eq!(x.unwrap(), "air"); // fails ``` -------------------------------- ### Language Copy Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/opt/rustwide/target/x86_64-unknown-linux-gnu/debug/build/tree-sitter-79baf157f28736af/out/bindings.rs.html Gets another reference to the given language. ```rust pub fn ts_language_copy(self_: *const TSLanguage) -> *const TSLanguage; ``` -------------------------------- ### unwrap_or_default example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of `unwrap_or_default` for Option. ```rust let x: Option = None; let y: Option = Some(12); assert_eq!(x.unwrap_or_default(), 0); assert_eq!(y.unwrap_or_default(), 12); ``` -------------------------------- ### Get the ABI version number that indicates which version of the Tree-sitter CLI that was used to generate this `Language`. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get the ABI version number that indicates which version of the Tree-sitter CLI that was used to generate this `Language`. ```rust pub fn abi_version(&self) -> usize ``` -------------------------------- ### Walk the tree Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Tree.html Create a new `TreeCursor` starting from the root of the tree. ```rust pub fn walk(&self) -> TreeCursor<'_> ``` -------------------------------- ### unwrap_or_else example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of `unwrap_or_else` for Option. ```rust let k = 10; assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4); assert_eq!(None.unwrap_or_else(|| 2 * k), 20); ``` -------------------------------- ### Default Option Example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Example demonstrating how to get the default value for an Option, which is None. ```Rust let opt: Option = Option::default(); assert!(opt.is_none()); ``` -------------------------------- ### Search Tricks Source: https://docs.rs/tree-sitter/latest/help.html Examples of how to use prefixes and special characters to refine search queries in rustdoc. ```text Prefix searches with a type followed by a colon (e.g., `fn:`) to restrict the search to a given item kind. Accepted kinds are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `constant`. ``` ```text Search functions by type signature (e.g., `vec -> usize` or `-> vec` or `String, enum:Cow -> bool`) ``` ```text You can look for items with an exact name by putting double quotes around your request: `"string"` ``` ```text Look for functions that accept or return slices and arrays by writing square brackets (e.g., `-> [u8]` or `[] -> Option`) ``` ```text Look for items inside another one by searching for a path: `vec::Vec` ``` -------------------------------- ### Rust Library Initialization and Features Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html This snippet shows the initial configuration of the Rust library, including conditional compilation for tests, doctests, and standard library usage, as well as feature flags for documentation and WebAssembly. ```rust #![cfg_attr(not(any(test, doctest)), doc = include_str!("./README.md"))] #![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(docsrs, feature(doc_cfg))] ``` -------------------------------- ### ts_node_start_point Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/fn.ts_node_start_point.html Get the node’s start position in terms of rows and columns. ```rust pub unsafe extern "C" fn ts_node_start_point(self_: TSNode) -> TSPoint ``` -------------------------------- ### Basic Usage Source: https://docs.rs/tree-sitter/latest/tree_sitter/index.html Demonstrates the fundamental steps to initialize a parser, add a language, and parse source code. ```Rust use tree_sitter::{InputEdit, Language, Parser, Point}; let mut parser = Parser::new(); ``` ```TOML [dependencies] tree-sitter = "0.24" tree-sitter-rust = "0.23" ``` ```Rust parser.set_language(&tree_sitter_rust::LANGUAGE.into()).expect("Error loading Rust grammar"); ``` ```Rust let source_code = "fn test() {}"; let mut tree = parser.parse(source_code, None).unwrap(); let root_node = tree.root_node(); assert_eq!(root_node.kind(), "source_file"); assert_eq!(root_node.start_position().column, 0); assert_eq!(root_node.end_position().column, 12); ``` -------------------------------- ### Basic Usage: Parser Initialization Source: https://docs.rs/tree-sitter/latest/index.html Initializes a new Tree-sitter parser. ```rust use tree_sitter::{InputEdit, Language, Parser, Point}; let mut parser = Parser::new(); ``` -------------------------------- ### ts_query_start_byte_for_pattern Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/fn.ts_query_start_byte_for_pattern.html Get the byte offset where the given pattern starts in the query’s source. ```rust pub unsafe extern "C" fn ts_query_start_byte_for_pattern( self_: *const TSQuery, pattern_index: u32, ) -> u32 ``` -------------------------------- ### Using Wasm Grammar Files: Parser Initialization Source: https://docs.rs/tree-sitter/latest/index.html Initializes a parser with a Wasm store for using Wasm grammar files. ```rust use tree_sitter::{wasmtime::Engine, Parser, WasmStore}; let engine = Engine::default(); let store = WasmStore::new(&engine).unwrap(); let mut parser = Parser::new(); parser.set_wasm_store(store).unwrap(); ``` -------------------------------- ### Getting the first child for a byte offset Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Node.html Finds the first child node that starts at or after the given byte offset. ```rust pub fn first_child_for_byte(&self, byte: usize) -> Option ``` -------------------------------- ### xor() example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of the `xor()` method on an Option, showing how it returns Some if exactly one of the Options is Some. ```rust let x = Some(2); let y: Option = None; assert_eq!(x.xor(y), Some(2)); let x: Option = None; let y = Some(2); assert_eq!(x.xor(y), Some(2)); let x = Some(2); let y = Some(2); assert_eq!(x.xor(y), None); let x: Option = None; let y: Option = None; assert_eq!(x.xor(y), None); ``` -------------------------------- ### Creating a TreeCursor Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Node.html Creates a new TreeCursor starting from the current node. ```rust pub fn walk(&self) -> TreeCursor<'tree> ``` -------------------------------- ### Keyboard Shortcuts Source: https://docs.rs/tree-sitter/latest/help.html A list of keyboard shortcuts available in rustdoc for navigation and interaction. ```text `?` Show this help dialog ``` ```text `S` / `/` Focus the search field ``` ```text `↑` Move up in search results ``` ```text `↓` Move down in search results ``` ```text `←` / `→` Switch result tab (when results focused) ``` ```text `⏎` Go to active search result ``` ```text `+` / `=` Expand all sections ``` ```text `-` Collapse all sections ``` ```text `_` Collapse all sections, including impl blocks ``` -------------------------------- ### ts_node_first_named_child_for_byte Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/fn.ts_node_first_named_child_for_byte.html Get the node’s first named child that contains or starts after the given byte offset. ```rust pub unsafe extern "C" fn ts_node_first_named_child_for_byte( self_: TSNode, byte: u32, ) -> TSNode ``` -------------------------------- ### Standard Library and Core Dependencies Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html This section lists the dependencies and imports for the library, differentiating between standard library (`std`) and no-standard-library (`no_std`) environments. It includes common types like `Box`, `String`, `Vec`, and core modules for FFI, formatting, hashing, iteration, and memory management. ```rust #[cfg(not(feature = "std"))] extern crate alloc; #[cfg(not(feature = "std"))] use alloc::{boxed::Box, format, string::String, string::ToString, vec::Vec}; use core:: ffi::{c_char, c_void, CStr}, fmt::{self, Write}, hash, iter, marker::PhantomData, mem::MaybeUninit, num::NonZeroU16, ops::{self, ControlFlow, Deref}, ptr::{self, NonNull}, slice, str, }; #[cfg(feature = "std")] use std::error; #[cfg(all(unix, feature = "std"))] use std::os::fd::AsRawFd; #[cfg(all(windows, feature = "std"))] use std::os::windows::io::AsRawHandle; ``` -------------------------------- ### ts_query_cursor_exec_with_options Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/fn.ts_query_cursor_exec_with_options.html Start running a given query on a given node, with some options. ```rust pub unsafe extern "C" fn ts_query_cursor_exec_with_options( self_: *mut TSQueryCursor, query: *const TSQuery, node: TSNode, query_options: *const TSQueryCursorOptions, ) ``` -------------------------------- ### Get the next parse state. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get the next parse state. Combine this with `lookahead_iterator` to generate completion suggestions or valid symbols in error nodes. Example: ⓘ``` let state = language.next_state(node.parse_state(), node.grammar_id()); ``` ```rust pub fn next_state(&self, state: u16, id: u16) -> u16 ``` -------------------------------- ### Getting the first named child for a byte offset Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Node.html Finds the first named child node that starts at or after the given byte offset. ```rust pub fn first_named_child_for_byte(&self, byte: usize) -> Option ``` -------------------------------- ### Predicate Logic Example Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html This snippet demonstrates the internal logic for processing predicate steps, including handling different predicate types like equality and matching, and validating arguments. ```Rust let raw_predicates = ffi::ts_query_predicates_for_pattern( ptr.0, i as u32, core::ptr::addr_of_mut!(length), ); (length > 0) .then(|| slice::from_raw_parts(raw_predicates, length as usize)) .unwrap_or_default() }; let byte_offset = unsafe { ffi::ts_query_start_byte_for_pattern(ptr.0, i as u32) }; let row = source .char_indices() .take_while(|(i, _)| *i < byte_offset as usize) .filter(|(_, c)| *c == '\n') .count(); use ffi::TSQueryPredicateStepType as T; const TYPE_DONE: T = ffi::TSQueryPredicateStepTypeDone; const TYPE_CAPTURE: T = ffi::TSQueryPredicateStepTypeCapture; const TYPE_STRING: T = ffi::TSQueryPredicateStepTypeString; let mut text_predicates = Vec::new(); let mut property_predicates = Vec::new(); let mut property_settings = Vec::new(); let mut general_predicates = Vec::new(); for p in predicate_steps.split(|s| s.type_ == TYPE_DONE) { if p.is_empty() { continue; } if p[0].type_ != TYPE_STRING { return Err(predicate_error( row, format!( "Expected predicate to start with a function name. Got @{}.", capture_names[p[0].value_id as usize], ), )); } // Build a predicate for each of the known predicate function names. let operator_name = string_values[p[0].value_id as usize]; match operator_name { "eq?" | "not-eq?" | "any-eq?" | "any-not-eq?" => { if p.len() != 3 { return Err(predicate_error( row, format!( "Wrong number of arguments to #eq? predicate. Expected 2, got {}.", p.len() - 1 ), )); } if p[1].type_ != TYPE_CAPTURE { return Err(predicate_error(row, format!( "First argument to #eq? predicate must be a capture name. Got literal \"{}\".", string_values[p[1].value_id as usize], ))); } let is_positive = operator_name == "eq?" || operator_name == "any-eq?"; let match_all = match operator_name { "eq?" | "not-eq?" => true, "any-eq?" | "any-not-eq?" => false, _ => unreachable!(), }; text_predicates.push(if p[2].type_ == TYPE_CAPTURE { TextPredicateCapture::EqCapture( p[1].value_id, p[2].value_id, is_positive, match_all, ) } else { TextPredicateCapture::EqString( p[1].value_id, string_values[p[2].value_id as usize].to_string().into(), is_positive, match_all, ) }); } "match?" | "not-match?" | "any-match?" | "any-not-match?" => { if p.len() != 3 { return Err(predicate_error(row, format!( "Wrong number of arguments to #match? predicate. Expected 2, got {}.", p.len() - 1 ))); } if p[1].type_ != TYPE_CAPTURE { return Err(predicate_error(row, format!( "First argument to #match? predicate must be a capture name. Got literal \"{}\".", string_values[p[1].value_id as usize], ))); } ``` -------------------------------- ### Get language Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Tree.html Get the language that was used to parse the syntax tree. ```rust pub fn language(&self) -> LanguageRef<'_> ``` -------------------------------- ### Get root node Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Tree.html Get the root node of the syntax tree. ```rust pub fn root_node(&self) -> Node<'_> ``` -------------------------------- ### Lexer Macros Source: https://docs.rs/tree-sitter/latest/tree_sitter/constant.PARSER_HEADER.html Macros for advancing the lexer, skipping tokens, and accepting tokens. ```c #define ADVANCE(state_value) \ { \ state = state_value; \ goto next_state; \ } #define ADVANCE_MAP(...) \ { \ static const uint16_t map[] = { __VA_ARGS__ }; \ for (uint32_t i = 0; i < sizeof(map) / sizeof(map[0]); i += 2) { \ if (map[i] == lookahead) { \ state = map[i + 1]; \ goto next_state; \ } \ } \ } #define SKIP(state_value) \ { \ skip = true; \ state = state_value; \ goto next_state; \ } #define ACCEPT_TOKEN(symbol_value) \ result = true; \ lexer->result_symbol = symbol_value; \ lexer->mark_end(lexer); #define END_STATE() return result; ``` -------------------------------- ### Node Start Position Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html Retrieves the start position (row and column) of the node. ```rust pub fn start_position(&self) -> Point { let result = unsafe { ffi::ts_node_start_point(self.0) }; result.into() } ``` -------------------------------- ### Example: as_mut Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates converting &mut Option to Option<&mut T> using as_mut. ```rust let mut x = Some(2); match x.as_mut() { Some(v) => *v = 42, None => {}, } assert_eq!(x, Some(42)); ``` -------------------------------- ### Set Maximum Start Depth Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/opt/rustwide/target/x86_64-unknown-linux-gnu/debug/build/tree-sitter-79baf157f28736af/out/bindings.rs.html Sets the maximum start depth for a query cursor, preventing it from exploring children nodes beyond a certain depth. Setting it to UINT32_MAX removes the maximum start depth limit. ```rust pub fn ts_query_cursor_set_max_start_depth(self_: *mut TSQueryCursor, max_start_depth: u32); ``` -------------------------------- ### Query Cursor Execution and Iteration Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/opt/rustwide/target/x86_64-unknown-linux-gnu/debug/build/tree-sitter-79baf157f28736af/out/bindings.rs.html This snippet describes the process of creating a query cursor, executing a query, and iterating over the results using `ts_query_cursor_exec`, `ts_query_cursor_next_match`, and `ts_query_cursor_next_capture`. ```rust #[doc = " Create a new cursor for executing a given query.\n\n The cursor stores the state that is needed to iteratively search\n for matches. To use the query cursor, first call [`ts_query_cursor_exec`]\n to start running a given query on a given syntax node. Then, there are\n two options for consuming the results of the query:\n 1. Repeatedly call [`ts_query_cursor_next_match`] to iterate over all of the\n *matches* in the order that they were found. Each match contains the\n index of the pattern that matched, and an array of captures. Because\n multiple patterns can match the same set of nodes, one match may contain\n captures that appear *before* some of the captures from a previous match.\n 2. Repeatedly call [`ts_query_cursor_next_capture`] to iterate over all of the\n individual *captures* in the order that they appear. This is useful if\n don't care about which pattern matched, and just want a single ordered\n sequence of captures.\n\n If you don't care about consuming all of the results, you can stop calling\n [`ts_query_cursor_next_match`] or [`ts_query_cursor_next_capture`] at any point.\n You can then start executing another query on another node by calling\n [`ts_query_cursor_exec`] again."] pub fn ts_query_cursor_new() -> *mut TSQueryCursor; ``` -------------------------------- ### and() example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of the `and()` method on an Option, showing how it returns the second Option if the first is Some, otherwise None. ```rust let x = Some(2); let y: Option<&str> = None; assert_eq!(x.and(y), None); let x: Option = None; let y = Some("foo"); assert_eq!(x.and(y), None); let x = Some(2); let y = Some("foo"); assert_eq!(x.and(y), Some("foo")); let x: Option = None; let y: Option<&str> = None; assert_eq!(x.and(y), None); ``` -------------------------------- ### Get the number of valid states in this language. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get the number of valid states in this language. ```rust pub fn parse_state_count(&self) -> usize ``` -------------------------------- ### Query New Method Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html Constructs a new `Query` from a language and a string of S-expression patterns. ```rust pub fn new(language: &Language, source: &str) -> Result { let ptr = Self::new_raw(language, source)?; unsafe { Self::from_raw_parts(ptr, source) } } ``` -------------------------------- ### Get the name of this language. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get the name of this language. This returns `None` in older parsers. ```rust pub fn name(&self) -> Option<&'static str> ``` -------------------------------- ### Get the numerical id for the given field name. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get the numerical id for the given field name. ```rust pub fn field_id_for_name( &self, field_name: impl AsRef<[u8]>, ) -> Option ``` -------------------------------- ### Node Methods Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html This section details various methods available on the Node struct for navigating and querying the syntax tree. ```rust /// Get this node's first child that contains or starts after the given byte offset. #[doc(alias = "ts_node_first_child_for_byte")] #[must_use] pub fn first_child_for_byte(&self, byte: usize) -> Option { Self::new(unsafe { ffi::ts_node_first_child_for_byte(self.0, byte as u32) }) } /// Get this node's first named child that contains or starts after the given byte offset. #[doc(alias = "ts_node_first_named_child_for_byte")] #[must_use] pub fn first_named_child_for_byte(&self, byte: usize) -> Option { Self::new(unsafe { ffi::ts_node_first_named_child_for_byte(self.0, byte as u32) }) } /// Get the node's number of descendants, including one for the node itself. #[doc(alias = "ts_node_descendant_count")] #[must_use] pub fn descendant_count(&self) -> usize { unsafe { ffi::ts_node_descendant_count(self.0) as usize } } /// Get the smallest node within this node that spans the given byte range. #[doc(alias = "ts_node_descendant_for_byte_range")] #[must_use] pub fn descendant_for_byte_range(&self, start: usize, end: usize) -> Option { Self::new(unsafe { ffi::ts_node_descendant_for_byte_range(self.0, start as u32, end as u32) }) } /// Get the smallest named node within this node that spans the given byte range. #[doc(alias = "ts_node_named_descendant_for_byte_range")] #[must_use] pub fn named_descendant_for_byte_range(&self, start: usize, end: usize) -> Option { Self::new(unsafe { ffi::ts_node_named_descendant_for_byte_range(self.0, start as u32, end as u32) }) } /// Get the smallest node within this node that spans the given point range. #[doc(alias = "ts_node_descendant_for_point_range")] #[must_use] pub fn descendant_for_point_range(&self, start: Point, end: Point) -> Option { Self::new(unsafe { ffi::ts_node_descendant_for_point_range(self.0, start.into(), end.into()) }) } /// Get the smallest named node within this node that spans the given point range. #[doc(alias = "ts_node_named_descendant_for_point_range")] #[must_use] pub fn named_descendant_for_point_range(&self, start: Point, end: Point) -> Option { Self::new(unsafe { ffi::ts_node_named_descendant_for_point_range(self.0, start.into(), end.into()) }) } /// Get an S-expression representing the node. #[doc(alias = "ts_node_string")] #[must_use] pub fn to_sexp(&self) -> String { let c_string = unsafe { ffi::ts_node_string(self.0) }; let result = unsafe { CStr::from_ptr(c_string) } .to_str() .unwrap() .to_string(); unsafe { (FREE_FN)(c_string.cast::()) }; result } pub fn utf8_text<'a>(&self, source: &'a [u8]) -> Result<&'a str, str::Utf8Error> { str::from_utf8(&source[self.start_byte()..self.end_byte()]) } #[must_use] pub fn utf16_text<'a>(&self, source: &'a [u16]) -> &'a [u16] { &source[self.start_byte() / 2..self.end_byte() / 2] } /// Create a new [`TreeCursor`] starting from this node. /// /// Note that the given node is considered the root of the cursor, /// and the cursor cannot walk outside this node. #[doc(alias = "ts_tree_cursor_new")] #[must_use] pub fn walk(&self) -> TreeCursor<'tree> { TreeCursor(unsafe { ffi::ts_tree_cursor_new(self.0) }, PhantomData) } /// Edit this node to keep it in-sync with source code that has been edited. /// /// This function is only rarely needed. When you edit a syntax tree with /// the [`Tree::edit`] method, all of the nodes that you retrieve from /// the tree afterward will already reflect the edit. You only need to /// use [`Node::edit`] when you have a specific [`Node`] instance that /// you want to keep and continue to use after an edit. #[doc(alias = "ts_node_edit")] pub fn edit(&mut self, edit: &InputEdit) { let edit = edit.into(); unsafe { ffi::ts_node_edit(core::ptr::addr_of_mut!(self.0), &edit) } } ``` -------------------------------- ### Get the field name for the given numerical id. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get the field name for the given numerical id. ```rust pub fn field_name_for_id(&self, field_id: u16) -> Option<&'static str> ``` -------------------------------- ### or() example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of the `or()` method on an Option, showing how it returns the first Option if it's Some, otherwise the second Option. ```rust let x = Some(2); let y = None; assert_eq!(x.or(y), Some(2)); let x = None; let y = Some(100); assert_eq!(x.or(y), Some(100)); let x = Some(2); let y = Some(100); assert_eq!(x.or(y), Some(2)); let x: Option = None; let y = None; assert_eq!(x.or(y), None); ``` -------------------------------- ### Get the number of distinct field names in this language. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get the number of distinct field names in this language. ```rust pub fn field_count(&self) -> usize ``` -------------------------------- ### Using Wasm Grammar Files Source: https://docs.rs/tree-sitter/latest/tree_sitter/index.html Illustrates how to use Tree-sitter with WebAssembly grammar files, requiring the 'wasm' feature. ```Rust use tree_sitter::{wasmtime::Engine, Parser, WasmStore}; let engine = Engine::default(); let store = WasmStore::new(&engine).unwrap(); let mut parser = Parser::new(); parser.set_wasm_store(store).unwrap(); ``` ```Rust const JAVASCRIPT_GRAMMAR: &[u8] = include_bytes!("path/to/tree-sitter-javascript.wasm"); let mut store = WasmStore::new(&engine).unwrap(); let javascript = store .load_language("javascript", JAVASCRIPT_GRAMMAR) .unwrap(); // The language may be loaded from a different WasmStore than the one set on // the parser but it must use the same underlying WasmEngine. parser.set_language(&javascript).unwrap(); ``` ```Rust let source_code = "let x = 1;"; let tree = parser.parse(source_code, None).unwrap(); assert_eq!( tree.root_node().to_sexp(), "(program (lexical_declaration (variable_declarator name: (identifier) value: (number))))" ); ``` -------------------------------- ### Get the numeric id for the given node kind. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get the numeric id for the given node kind. ```rust pub fn id_for_node_kind(&self, kind: &str, named: bool) -> u16 ``` -------------------------------- ### Property Setting and Predicate Handling Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html Code snippet illustrating the parsing logic for 'set!', 'is?', 'is-not?', 'any-of?', and 'not-any-of?' operators, including argument validation and data structure population. ```rust "set!" => property_settings.push(Self::parse_property( row, operator_name, &capture_names, &string_values, &p[1..], )?), "is?" | "is-not?" => property_predicates.push(( Self::parse_property( row, operator_name, &capture_names, &string_values, &p[1..], )?, operator_name == "is?", )), "any-of?" | "not-any-of?" => { if p.len() < 2 { return Err(predicate_error(row, format!( "Wrong number of arguments to #any-of? predicate. Expected at least 1, got {}.", p.len() - 1 ))); } if p[1].type_ != TYPE_CAPTURE { return Err(predicate_error(row, format!( "First argument to #any-of? predicate must be a capture name. Got literal \"{}\".", string_values[p[1].value_id as usize], ))); } let is_positive = operator_name == "any-of?"; let mut values = Vec::new(); for arg in &p[2..] { if arg.type_ == TYPE_CAPTURE { return Err(predicate_error(row, format!( "Arguments to #any-of? predicate must be literals. Got capture @{}.", capture_names[arg.value_id as usize], ))); } values.push(string_values[arg.value_id as usize]); } text_predicates.push(TextPredicateCapture::AnyString( p[1].value_id, values .iter() .map(|x| (*x).to_string().into()) .collect::>() .into(), is_positive, )); } _ => general_predicates.push(QueryPredicate { operator: operator_name.to_string().into(), args: p[1..] .iter() .map(|a| { if a.type_ == TYPE_CAPTURE { QueryPredicateArg::Capture(a.value_id) } else { QueryPredicateArg::String( string_values[a.value_id as usize].to_string().into(), ) } }) .collect(), }), ``` -------------------------------- ### Get the number of distinct node types in this language. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get the number of distinct node types in this language. ```rust pub fn node_kind_count(&self) -> usize ``` -------------------------------- ### Match String Predicate Handling Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html Code snippet demonstrating the logic for handling the '#match?' and '#any-match?' predicates, including regex compilation and argument validation. ```rust if p[2].type_ == TYPE_CAPTURE { return Err(predicate_error(row, format!("Second argument to #match? predicate must be a literal. Got capture @{}.", capture_names[p[2].value_id as usize], ))); } let is_positive = operator_name == "match?" || operator_name == "any-match?"; let match_all = match operator_name { "match?" | "not-match?" => true, "any-match?" | "any-not-match?" => false, _ => unreachable!(), }; let regex = &string_values[p[2].value_id as usize]; text_predicates.push(TextPredicateCapture::MatchString( p[1].value_id, regex::bytes::Regex::new(regex).map_err(|_| { predicate_error(row, format!("Invalid regex '{regex}'")) })?, is_positive, match_all, )); ``` -------------------------------- ### Get root node with offset Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Tree.html Get the root node of the syntax tree, but with its position shifted forward by the given offset. ```rust pub fn root_node_with_offset( &self, offset_bytes: usize, offset_extent: Point, ) -> Node<'_> ``` -------------------------------- ### Option Reduce Example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of the `reduce` method on Option, which is a nightly-only experimental API. ```Rust #![feature(option_reduce)] let s12 = Some(12); let s17 = Some(17); let n = None; let f = |a, b| a + b; assert_eq!(s12.reduce(s17, f), Some(29)); assert_eq!(s12.reduce(n, f), Some(12)); assert_eq!(n.reduce(s17, f), Some(17)); assert_eq!(n.reduce(n, f), None); ``` -------------------------------- ### QueryCursor Raw Pointer Conversion Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/ffi.rs.html Demonstrates converting a `QueryCursor` to and from its raw C pointer representation. ```rust impl QueryCursor { /// Consumes the [`QueryCursor`], returning a raw pointer to the underlying C structure. #[must_use] pub fn into_raw(self) -> *mut TSQueryCursor { ManuallyDrop::new(self).ptr.as_ptr() } } ``` -------------------------------- ### Get the name of the node kind for the given numerical id. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get the name of the node kind for the given numerical id. ```rust pub fn node_kind_for_id(&self, id: u16) -> Option<&'static str> ``` -------------------------------- ### Get a list of all subtype symbols for a given supertype symbol. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Get a list of all subtype symbols for a given supertype symbol. ```rust pub fn subtypes_for_supertype(&self, supertype: u16) -> &[u16] ``` -------------------------------- ### Using Wasm Grammar Files: Loading Language Source: https://docs.rs/tree-sitter/latest/index.html Loads a language grammar from a Wasm file and sets it on the parser. ```rust const JAVASCRIPT_GRAMMAR: &[u8] = include_bytes!("path/to/tree-sitter-javascript.wasm"); let mut store = WasmStore::new(&engine).unwrap(); let javascript = store .load_language("javascript", JAVASCRIPT_GRAMMAR) .unwrap(); // The language may be loaded from a different WasmStore than the one set on // the parser but it must use the same underlying WasmEngine. parser.set_language(&javascript).unwrap(); ``` -------------------------------- ### Set Maximum Start Depth Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html Sets the maximum start depth for a query cursor, preventing it from exploring children nodes beyond a certain depth. Setting it to `None` removes the limit. ```rust /// Set the maximum start depth for a query cursor. /// /// This prevents cursors from exploring children nodes at a certain depth. /// Note if a pattern includes many children, then they will still be /// checked. /// /// The zero max start depth value can be used as a special behavior and /// it helps to destructure a subtree by staying on a node and using /// captures for interested parts. Note that the zero max start depth /// only limits a search depth for a pattern's root node but other nodes /// that are parts of the pattern may be searched at any depth depending on /// what is defined by the pattern structure. /// /// Set to `None` to remove the maximum start depth. #[doc(alias = "ts_query_cursor_set_max_start_depth")] pub fn set_max_start_depth(&mut self, max_start_depth: Option) -> &mut Self { unsafe { ffi::ts_query_cursor_set_max_start_depth( self.ptr.as_ptr(), max_start_depth.unwrap_or(u32::MAX), ); } self } ``` -------------------------------- ### Parsing with Options Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html This snippet demonstrates how to parse input with specific options, including custom encoding and decode callbacks, and optionally using an old tree to resume parsing. ```rust let c_input = TSInput { payload: text.as_ptr() as *const c_char, buffer_len: text.len() as u32, encoding: ffi::TSInputEncodingUTF8, start_index: ptr::null(), read: None, decode: None, }; let parse_options = ffi::TSParseOptions { // Use this custom read callback read: Some(read::), encoding: ffi::TSInputEncodingCustom, // Use this custom decode callback decode: Some(decode_fn::), }; let c_old_tree = old_tree.map_or(ptr::null_mut(), |t| t.0.as_ptr()); unsafe { let c_new_tree = ffi::ts_parser_parse_with_options( self.0.as_ptr(), c_old_tree, c_input, parse_options, ); NonNull::new(c_new_tree).map(Tree) } ``` -------------------------------- ### Creates a new `Language` from a `LanguageFn`. Source: https://docs.rs/tree-sitter/latest/tree_sitter/struct.Language.html Creates a new `Language` from a `LanguageFn`. ```rust pub fn new(builder: LanguageFn) -> Self ``` -------------------------------- ### Query Cursor Execution with Options Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/opt/rustwide/target/x86_64-unknown-linux-gnu/debug/build/tree-sitter-79baf157f28736af/out/bindings.rs.html Function to start executing a given query on a given node with additional options. ```rust #[doc = " Start running a given query on a given node, with some options."] pub fn ts_query_cursor_exec_with_options( self_: *mut TSQueryCursor, query: *const TSQuery, node: TSNode, query_options: *const TSQueryCursorOptions, ); ``` -------------------------------- ### ts_node_next_parse_state Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/fn.ts_node_next_parse_state.html Get the parse state after this node. ```rust pub unsafe extern "C" fn ts_node_next_parse_state( self_: TSNode, ) -> TSStateId ``` -------------------------------- ### Example: as_ref Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Shows how to convert &Option to Option<&T> using as_ref, preserving the original Option. ```rust let text: Option = Some("Hello, world!".to_string()); // First, cast `Option` to `Option<&String>` with `as_ref`, // then consume *that* with `map`, leaving `text` on the stack. let text_length: Option = text.as_ref().map(|s| s.len()); println!("still can print text: {:?}", text); ``` -------------------------------- ### Basic Usage: Setting the Language Source: https://docs.rs/tree-sitter/latest/index.html Assigns a language grammar to the parser. ```rust parser.set_language(&tree_sitter_rust::LANGUAGE.into()).expect("Error loading Rust grammar"); ``` -------------------------------- ### ts_node_end_byte Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/fn.ts_node_end_byte.html Get the node’s end byte. ```Rust pub unsafe extern "C" fn ts_node_end_byte(self_: TSNode) -> u32 ``` -------------------------------- ### Using Wasm Grammar Files: Parsing Source Code Source: https://docs.rs/tree-sitter/latest/index.html Parses source code using a language loaded from a Wasm grammar file. ```rust let source_code = "let x = 1;"; let tree = parser.parse(source_code, None).unwrap(); assert_eq!( tree.root_node().to_sexp(), "(program (lexical_declaration (variable_declarator name: (identifier) value: (number))))" ); ``` -------------------------------- ### ts_language_state_count Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/fn.ts_language_state_count.html Get the number of valid states in this language. ```rust pub unsafe extern "C" fn ts_language_state_count( self_: *const TSLanguage, ) -> u32 ``` -------------------------------- ### or_else() example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of the `or_else()` method on an Option, showing how it lazily evaluates a closure to provide a default value. ```rust fn nobody() -> Option<&'static str> { None } fn vikings() -> Option<&'static str> { Some("vikings") } assert_eq!(Some("barbarians").or_else(vikings), Some("barbarians")); assert_eq!(None.or_else(vikings), Some("vikings")); assert_eq!(None.or_else(nobody), None); ``` -------------------------------- ### unwrap_unchecked example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of `unwrap_unchecked` for Option. ```rust let x = Some("air"); assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); ``` ```rust let x: Option<&str> = None; assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); // Undefined behavior! ``` -------------------------------- ### Query New Raw Method Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html Constructs a raw `TSQuery` pointer, responsible for its eventual freeing. ```rust pub fn new_raw(language: &Language, source: &str) -> Result<*mut ffi::TSQuery, QueryError> { let mut error_offset = 0u32; let mut error_type: ffi::TSQueryError = 0; let bytes = source.as_bytes(); // Compile the query. let ptr = unsafe { ffi::ts_query_new( language.0, bytes.as_ptr().cast::(), bytes.len() as u32, core::ptr::addr_of_mut!(error_offset), core::ptr::addr_of_mut!(error_type), ) }; if !ptr.is_null() { return Ok(ptr); } // On failure, build an error based on the error code and offset. if error_type == ffi::TSQueryErrorLanguage { return Err(QueryError { row: 0, column: 0, offset: 0, message: LanguageError::Version(language.abi_version()).to_string(), kind: QueryErrorKind::Language, }); } let offset = error_offset as usize; let mut line_start = 0; let mut row = 0; let mut line_containing_error = None; for line in source.lines() { let line_end = line_start + line.len() + 1; if line_end > offset { line_containing_error = Some(line); break; } line_start = line_end; row += 1; } let column = offset - line_start; let kind; let message; match error_type { // Error types that report names ffi::TSQueryErrorNodeType | ffi::TSQueryErrorField | ffi::TSQueryErrorCapture => { let suffix = source.split_at(offset).1; let in_quotes = offset > 0 && source.as_bytes()[offset - 1] == b'"'; let mut backslashes = 0; let end_offset = suffix .find(|c| { if in_quotes { ``` -------------------------------- ### Parse Table Macros Source: https://docs.rs/tree-sitter/latest/tree_sitter/constant.PARSER_HEADER.html Macros for defining states, actions, shifts, reduces, and recovery actions in a parse table. ```c #define SMALL_STATE(id) ((id) - LARGE_STATE_COUNT) #define STATE(id) id #define ACTIONS(id) id #define SHIFT(state_value) \ {{ \ .shift = { \ .type = TSParseActionTypeShift, \ .state = (state_value) \ } \ }} #define SHIFT_REPEAT(state_value) \ {{ \ .shift = { \ .type = TSParseActionTypeShift, \ .state = (state_value), \ .repetition = true \ } \ }} #define SHIFT_EXTRA() \ {{ \ .shift = { \ .type = TSParseActionTypeShift, \ .extra = true \ } \ }} #define REDUCE(symbol_name, children, precedence, prod_id) \ {{ \ .reduce = { \ .type = TSParseActionTypeReduce, \ .symbol = symbol_name, \ .child_count = children, \ .dynamic_precedence = precedence, \ .production_id = prod_id \ }, \ }} #define RECOVER() \ {{ \ .type = TSParseActionTypeRecover \ }} #define ACCEPT_INPUT() \ {{ \ .type = TSParseActionTypeAccept \ }} ``` -------------------------------- ### unwrap_or example Source: https://docs.rs/tree-sitter/latest/tree_sitter/ffi/type.TSDecodeFunction.html Demonstrates the usage of `unwrap_or` for Option. ```rust assert_eq!(Some("car").unwrap_or("bike"), "car"); assert_eq!(None.unwrap_or("bike"), "bike"); ``` -------------------------------- ### Query PartialEq Implementation Source: https://docs.rs/tree-sitter/latest/src/tree_sitter/lib.rs.html Implements PartialEq for Query based on the pointer equality. ```rust impl PartialEq for Query { fn eq(&self, other: &Self) -> bool { self.ptr == other.ptr } } ```