API extensions

This commit is contained in:
Daumantas Kavolis 2023-05-17 10:39:37 +03:00
parent 08f4e82bb2
commit c47e217e73
14 changed files with 741 additions and 29 deletions

View file

@ -1,5 +1,6 @@
/* automatically generated by rust-bindgen 0.66.1 */
pub type TSStateId = u16;
pub type TSSymbol = u16;
pub type TSFieldId = u16;
#[repr(C)]
@ -27,6 +28,11 @@ pub struct TSQuery {
pub struct TSQueryCursor {
_unused: [u8; 0],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct TSLookaheadIterator {
_unused: [u8; 0],
}
pub const TSInputEncoding_TSInputEncodingUTF8: TSInputEncoding = 0;
pub const TSInputEncoding_TSInputEncodingUTF16: TSInputEncoding = 1;
pub type TSInputEncoding = ::std::os::raw::c_uint;
@ -326,6 +332,14 @@ extern "C" {
#[doc = " Check if the node is a syntax error or contains any syntax errors."]
pub fn ts_node_has_error(arg1: TSNode) -> bool;
}
extern "C" {
#[doc = " Check if the node is a syntax error."]
pub fn ts_node_is_error(arg1: TSNode) -> bool;
}
extern "C" {
#[doc = " Get this node's parse state."]
pub fn ts_node_parse_state(arg1: TSNode) -> TSStateId;
}
extern "C" {
#[doc = " Get the node's immediate parent."]
pub fn ts_node_parent(arg1: TSNode) -> TSNode;
@ -427,6 +441,10 @@ extern "C" {
#[doc = " Re-initialize a tree cursor to start at a different node."]
pub fn ts_tree_cursor_reset(arg1: *mut TSTreeCursor, arg2: TSNode);
}
extern "C" {
#[doc = " Re-initialize a tree cursor to the same position as another cursor.\n\n Unlike `ts_tree_cursor_reset`, this will not lose parent information and\n allows reusing already created cursors."]
pub fn ts_tree_cursor_reset_to(arg1: *mut TSTreeCursor, arg2: *const TSTreeCursor);
}
extern "C" {
#[doc = " Get the tree cursor's current node."]
pub fn ts_tree_cursor_current_node(arg1: *const TSTreeCursor) -> TSNode;
@ -450,9 +468,16 @@ extern "C" {
pub fn ts_tree_cursor_goto_next_sibling(arg1: *mut TSTreeCursor) -> bool;
}
extern "C" {
#[doc = " Move the cursor to the first child of its current node.\n\n This returns `true` if the cursor successfully moved, and returns `false`\n if there were no children."]
#[doc = " Move the cursor to the previous sibling of its current node.\n\n This returns `true` if the cursor successfully moved, and returns `false` if\n there was no previous sibling node."]
pub fn ts_tree_cursor_goto_previous_sibling(arg1: *mut TSTreeCursor) -> bool;
}
extern "C" {
#[doc = " Move the cursor to the first/last child of its current node.\n\n This returns `true` if the cursor successfully moved, and returns `false`\n if there were no children."]
pub fn ts_tree_cursor_goto_first_child(arg1: *mut TSTreeCursor) -> bool;
}
extern "C" {
pub fn ts_tree_cursor_goto_last_child(arg1: *mut TSTreeCursor) -> bool;
}
extern "C" {
#[doc = " Move the cursor to the node that is the nth descendant of\n the original node that the cursor was constructed with, where\n zero represents the original node itself."]
pub fn ts_tree_cursor_goto_descendant(arg1: *mut TSTreeCursor, arg2: u32);
@ -608,6 +633,10 @@ extern "C" {
#[doc = " Get the number of distinct node types in the language."]
pub fn ts_language_symbol_count(arg1: *const TSLanguage) -> u32;
}
extern "C" {
#[doc = " Get the number of valid states in this language."]
pub fn ts_language_state_count(arg1: *const TSLanguage) -> u32;
}
extern "C" {
#[doc = " Get a node type string for the given numerical id."]
pub fn ts_language_symbol_name(
@ -651,6 +680,52 @@ extern "C" {
#[doc = " Get the ABI version number for this language. This version number is used\n to ensure that languages were generated by a compatible version of\n Tree-sitter.\n\n See also `ts_parser_set_language`."]
pub fn ts_language_version(arg1: *const TSLanguage) -> u32;
}
extern "C" {
#[doc = " Get the next parse state. Combine this with lookahead iterators to generate\n completion suggestions or valid symbols in error nodes."]
pub fn ts_language_next_state(
arg1: *const TSLanguage,
arg2: TSStateId,
arg3: TSSymbol,
) -> TSStateId;
}
extern "C" {
#[doc = " Create a new lookahead iterator for the given language and parse state.\n\n This returns `NULL` if state is invalid for the language.\n\n Repeatedly using `ts_lookahead_iterator_advance` and\n `ts_lookahead_iterator_current_symbol` will generate valid symbols in the\n given parse state. Newly created lookahead iterators will contain the `ERROR`\n symbol.\n\n Lookahead iterators can be useful to generate suggestions and improve syntax\n error diagnostics. To get symbols valid in an ERROR node, use the lookahead\n iterator on its first leaf node state. For `MISSING` nodes, a lookahead\n iterator created on the previous non-extra leaf node may be appropriate."]
pub fn ts_lookahead_iterator_new(
arg1: *const TSLanguage,
arg2: TSStateId,
) -> *mut TSLookaheadIterator;
}
extern "C" {
#[doc = " Delete a lookahead iterator freeing all the memory used."]
pub fn ts_lookahead_iterator_delete(arg1: *mut TSLookaheadIterator);
}
extern "C" {
#[doc = " Reset the lookahead iterator to another state.\n\n This returns `true` if the iterator was reset to the given state and `false`\n otherwise."]
pub fn ts_lookahead_iterator_reset_state(
arg1: *mut TSLookaheadIterator,
arg2: TSStateId,
) -> bool;
}
extern "C" {
#[doc = " Reset the lookahead iterator.\n\n This returns `true` if the language was set successfully and `false`\n otherwise."]
pub fn ts_lookahead_iterator_reset(
arg1: *mut TSLookaheadIterator,
arg2: *const TSLanguage,
arg3: TSStateId,
) -> bool;
}
extern "C" {
#[doc = " Get the current language of the lookahead iterator."]
pub fn ts_lookahead_iterator_language(arg1: *const TSLookaheadIterator) -> *const TSLanguage;
}
extern "C" {
#[doc = " Advance the lookahead iterator to the next symbol.\n\n This returns `true` if there is a new symbol and `false` otherwise."]
pub fn ts_lookahead_iterator_advance(arg1: *mut TSLookaheadIterator) -> bool;
}
extern "C" {
#[doc = " Get the current symbol of the lookahead iterator;"]
pub fn ts_lookahead_iterator_current_symbol(arg1: *const TSLookaheadIterator) -> TSSymbol;
}
extern "C" {
#[doc = " Set the allocation functions used by the library.\n\n By default, Tree-sitter uses the standard libc allocation functions,\n but aborts the process when an allocation fails. This function lets\n you supply alternative allocation functions at runtime.\n\n If you pass `NULL` for any parameter, Tree-sitter will switch back to\n its default implementation of that function.\n\n If you call this function after the library has already been used, then\n you must ensure that either:\n 1. All the existing objects have been freed.\n 2. The new allocator shares its state with the old one, so it is capable\n of freeing memory that was allocated by the old allocator."]
pub fn ts_set_allocator(

View file

@ -8,7 +8,9 @@ extern "C" {
pub(crate) fn dup(fd: std::os::raw::c_int) -> std::os::raw::c_int;
}
use crate::{Language, Node, Parser, Query, QueryCursor, QueryError, Tree, TreeCursor};
use crate::{
Language, LookaheadIterator, Node, Parser, Query, QueryCursor, QueryError, Tree, TreeCursor,
};
use std::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull, str};
impl Language {
@ -130,3 +132,19 @@ impl QueryCursor {
ManuallyDrop::new(self).ptr.as_ptr()
}
}
impl<'a> LookaheadIterator<'a> {
/// Reconstructs a [LookaheadIterator] from a raw pointer.
///
/// # Safety
///
/// `ptr` must be non-null.
pub unsafe fn from_raw(ptr: *mut TSLookaheadIterator) -> LookaheadIterator<'a> {
LookaheadIterator(NonNull::new_unchecked(ptr), PhantomData)
}
/// Consumes the [LookaheadIterator], returning a raw pointer to the underlying C structure.
pub fn into_raw(self) -> *mut TSLookaheadIterator {
ManuallyDrop::new(self).0.as_ptr()
}
}

View file

@ -87,6 +87,10 @@ pub struct Node<'a>(ffi::TSNode, PhantomData<&'a ()>);
#[doc(alias = "TSParser")]
pub struct Parser(NonNull<ffi::TSParser>);
/// A stateful object that is used to look up symbols valid in a specific parse state
#[doc(alias = "TSLookaheadIterator")]
pub struct LookaheadIterator<'a>(NonNull<ffi::TSLookaheadIterator>, PhantomData<&'a ()>);
/// A type of log message.
#[derive(Debug, PartialEq, Eq)]
pub enum LogType {
@ -269,6 +273,12 @@ impl Language {
unsafe { ffi::ts_language_symbol_count(self.0) as usize }
}
/// Get the number of valid states in this language.
#[doc(alias = "ts_language_state_count")]
pub fn parse_state_count(&self) -> usize {
unsafe { ffi::ts_language_state_count(self.0) as usize }
}
/// Get the name of the node kind for the given numerical id.
#[doc(alias = "ts_language_symbol_name")]
pub fn node_kind_for_id(&self, id: u16) -> Option<&'static str> {
@ -336,6 +346,36 @@ impl Language {
};
FieldId::new(id)
}
/// Get the next parse state. Combine this with [lookahead_iterator] to
/// generate completion suggestions or valid symbols in error nodes.
#[doc(alias = "ts_language_next_state")]
pub fn next_state(&self, state: u16, id: u16) -> u16 {
unsafe { ffi::ts_language_next_state(self.0, state, id) }
}
/// Create a new lookahead iterator for this language and parse state.
///
/// This returns `None` if state is invalid for this language.
///
/// Iterating [LookaheadIterator] will yield valid symbols in the given
/// parse state. Newly created lookahead iterators will return the `ERROR`
/// symbol from [LookaheadIterator::current_symbol].
///
/// Lookahead iterators can be useful to generate suggestions and improve
/// syntax error diagnostics. To get symbols valid in an ERROR node, use the
/// lookahead iterator on its first leaf node state. For `MISSING` nodes, a
/// lookahead iterator created on the previous non-extra leaf node may be
/// appropriate.
#[doc(alias = "ts_lookahead_iterator_new")]
pub fn lookahead_iterator<'a>(&self, state: u16) -> Option<LookaheadIterator<'a>> {
let ptr = unsafe { ffi::ts_lookahead_iterator_new(self.0, state) };
if ptr.is_null() {
None
} else {
Some(unsafe { LookaheadIterator::from_raw(ptr) })
}
}
}
impl Parser {
@ -885,6 +925,12 @@ impl<'tree> Node<'tree> {
self.kind_id() == u16::MAX
}
/// Get this node's parse state.
#[doc(alias = "ts_node_parse_state")]
pub fn parse_state(&self) -> u16 {
unsafe { ffi::ts_node_parse_state(self.0) }
}
/// Check if this node is *missing*.
///
/// Missing nodes are inserted by the parser in order to recover from certain kinds of
@ -1305,6 +1351,15 @@ impl<'a> TreeCursor<'a> {
return unsafe { ffi::ts_tree_cursor_goto_first_child(&mut self.0) };
}
/// Move this cursor to the last child of its current node.
///
/// This returns `true` if the cursor successfully moved, and returns `false`
/// if there were no children.
#[doc(alias = "ts_tree_cursor_goto_last_child")]
pub fn goto_last_child(&mut self) -> bool {
return unsafe { ffi::ts_tree_cursor_goto_last_child(&mut self.0) };
}
/// Move this cursor to the parent of its current node.
///
/// This returns `true` if the cursor successfully moved, and returns `false`
@ -1333,6 +1388,15 @@ impl<'a> TreeCursor<'a> {
};
}
/// Move this cursor to the previous sibling of its current node.
///
/// This returns `true` if the cursor successfully moved, and returns
/// `false` if there was no previous sibling node.
#[doc(alias = "ts_tree_cursor_goto_previous_sibling")]
pub fn goto_previous_sibling(&mut self) -> bool {
return unsafe { ffi::ts_tree_cursor_goto_previous_sibling(&mut self.0) };
}
/// Move this cursor to the first child of its current node that extends beyond
/// the given byte offset.
///
@ -1370,6 +1434,15 @@ impl<'a> TreeCursor<'a> {
pub fn reset(&mut self, node: Node<'a>) {
unsafe { ffi::ts_tree_cursor_reset(&mut self.0, node.0) };
}
/// Re-initialize a tree cursor to the same position as another cursor.
///
/// Unlike `reset`, this will not lose parent information and
/// allows reusing already created cursors.
#[doc(alias = "ts_tree_cursor_reset_to")]
pub fn reset_to(&mut self, cursor: TreeCursor<'a>) {
unsafe { ffi::ts_tree_cursor_reset_to(&mut self.0, &cursor.0) };
}
}
impl<'a> Clone for TreeCursor<'a> {
@ -1384,6 +1457,59 @@ impl<'a> Drop for TreeCursor<'a> {
}
}
impl<'a> LookaheadIterator<'a> {
/// Get the current language of the lookahead iterator.
#[doc(alias = "ts_lookahead_iterator_language")]
pub fn language(&self) -> Language {
Language(unsafe { ffi::ts_lookahead_iterator_language(self.0.as_ptr()) })
}
/// Get the current symbol of the lookahead iterator.
#[doc(alias = "ts_lookahead_iterator_current_symbol")]
pub fn current_symbol(&self) -> u16 {
unsafe { ffi::ts_lookahead_iterator_current_symbol(self.0.as_ptr()) }
}
/// Reset the lookahead iterator.
///
/// This returns `true` if the language was set successfully and `false`
/// otherwise.
#[doc(alias = "ts_lookahead_iterator_reset")]
pub fn reset(&self, language: &'a Language, state: u16) -> bool {
unsafe { ffi::ts_lookahead_iterator_reset(self.0.as_ptr(), language.0, state) }
}
/// Reset the lookahead iterator to another state.
///
/// This returns `true` if the iterator was reset to the given state and `false`
/// otherwise.
#[doc(alias = "ts_lookahead_iterator_reset_state")]
pub fn reset_state(&self, state: u16) -> bool {
unsafe { ffi::ts_lookahead_iterator_reset_state(self.0.as_ptr(), state) }
}
}
impl<'a> Iterator for LookaheadIterator<'a> {
type Item = u16;
#[doc(alias = "ts_lookahead_iterator_advance")]
fn next(&mut self) -> Option<Self::Item> {
// the first symbol is always `0` so we can safely skip it
if !(unsafe { ffi::ts_lookahead_iterator_advance(self.0.as_ptr()) }) {
None
} else {
Some(self.current_symbol())
}
}
}
impl<'a> Drop for LookaheadIterator<'a> {
#[doc(alias = "ts_lookahead_iterator_delete")]
fn drop(&mut self) {
unsafe { ffi::ts_lookahead_iterator_delete(self.0.as_ptr()) }
}
}
impl Query {
/// Create a new query from a string containing one or more S-expression
/// patterns.