Merge pull request #2840 from tree-sitter/language-reference-count
Introduce APIs for managing the lifetimes of languages, allow WASM languages to be deleted
This commit is contained in:
commit
1d8975319c
38 changed files with 724 additions and 483 deletions
|
|
@ -664,6 +664,14 @@ extern "C" {
|
|||
#[doc = " Set the maximum start depth for a query cursor.\n\n This prevents cursors from exploring children nodes at a certain depth.\n Note if a pattern includes many children, then they will still be checked.\n\n The zero max start depth value can be used as a special behavior and\n it helps to destructure a subtree by staying on a node and using captures\n for interested parts. Note that the zero max start depth only limit a search\n depth for a pattern's root node but other nodes that are parts of the pattern\n may be searched at any depth what defined by the pattern structure.\n\n Set to `UINT32_MAX` to remove the maximum start depth."]
|
||||
pub fn ts_query_cursor_set_max_start_depth(self_: *mut TSQueryCursor, max_start_depth: u32);
|
||||
}
|
||||
extern "C" {
|
||||
#[doc = " Get another reference to the given language."]
|
||||
pub fn ts_language_copy(self_: *const TSLanguage) -> *const TSLanguage;
|
||||
}
|
||||
extern "C" {
|
||||
#[doc = " Free any dynamically-allocated resources for this language, if\n this is the last reference."]
|
||||
pub fn ts_language_delete(self_: *const TSLanguage);
|
||||
}
|
||||
extern "C" {
|
||||
#[doc = " Get the number of distinct node types in the language."]
|
||||
pub fn ts_language_symbol_count(self_: *const TSLanguage) -> u32;
|
||||
|
|
@ -811,6 +819,10 @@ extern "C" {
|
|||
error: *mut TSWasmError,
|
||||
) -> *const TSLanguage;
|
||||
}
|
||||
extern "C" {
|
||||
#[doc = " Get the number of languages instantiated in the given wasm store."]
|
||||
pub fn ts_wasm_store_language_count(arg1: *const TSWasmStore) -> usize;
|
||||
}
|
||||
extern "C" {
|
||||
#[doc = " Check if the language came from a Wasm module. If so, then in order to use\n this langauge with a Parser, that parser must have a Wasm store assigned."]
|
||||
pub fn ts_language_is_wasm(arg1: *const TSLanguage) -> bool;
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ use std::{
|
|||
ffi::CStr,
|
||||
fmt, hash, iter,
|
||||
marker::PhantomData,
|
||||
mem::MaybeUninit,
|
||||
mem::{self, MaybeUninit},
|
||||
num::NonZeroU16,
|
||||
ops,
|
||||
ops::{self, Deref},
|
||||
os::raw::{c_char, c_void},
|
||||
ptr::{self, NonNull},
|
||||
slice, str,
|
||||
|
|
@ -47,10 +47,12 @@ pub const PARSER_HEADER: &'static str = include_str!("../include/tree_sitter/par
|
|||
/// An opaque object that defines how to parse a particular language. The code for each
|
||||
/// `Language` is generated by the Tree-sitter CLI.
|
||||
#[doc(alias = "TSLanguage")]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct Language(*const ffi::TSLanguage);
|
||||
|
||||
pub struct LanguageRef<'a>(*const ffi::TSLanguage, PhantomData<&'a ()>);
|
||||
|
||||
/// A tree that represents the syntactic structure of a source code file.
|
||||
#[doc(alias = "TSTree")]
|
||||
pub struct Tree(NonNull<ffi::TSTree>);
|
||||
|
|
@ -385,6 +387,26 @@ impl Language {
|
|||
}
|
||||
}
|
||||
|
||||
impl Clone for Language {
|
||||
fn clone(&self) -> Self {
|
||||
unsafe { Self(ffi::ts_language_copy(self.0)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Language {
|
||||
fn drop(&mut self) {
|
||||
unsafe { ffi::ts_language_delete(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for LanguageRef<'a> {
|
||||
type Target = Language;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe { mem::transmute(&self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Parser {
|
||||
/// Create a new parser.
|
||||
pub fn new() -> Parser {
|
||||
|
|
@ -403,7 +425,7 @@ impl Parser {
|
|||
/// and compare it to this library's [`LANGUAGE_VERSION`](LANGUAGE_VERSION) and
|
||||
/// [`MIN_COMPATIBLE_LANGUAGE_VERSION`](MIN_COMPATIBLE_LANGUAGE_VERSION) constants.
|
||||
#[doc(alias = "ts_parser_set_language")]
|
||||
pub fn set_language(&mut self, language: Language) -> Result<(), LanguageError> {
|
||||
pub fn set_language(&mut self, language: &Language) -> Result<(), LanguageError> {
|
||||
let version = language.version();
|
||||
if version < MIN_COMPATIBLE_LANGUAGE_VERSION || version > LANGUAGE_VERSION {
|
||||
Err(LanguageError { version })
|
||||
|
|
@ -766,8 +788,11 @@ impl Tree {
|
|||
|
||||
/// Get the language that was used to parse the syntax tree.
|
||||
#[doc(alias = "ts_tree_language")]
|
||||
pub fn language(&self) -> Language {
|
||||
Language(unsafe { ffi::ts_tree_language(self.0.as_ptr()) })
|
||||
pub fn language(&self) -> LanguageRef {
|
||||
LanguageRef(
|
||||
unsafe { ffi::ts_tree_language(self.0.as_ptr()) },
|
||||
PhantomData,
|
||||
)
|
||||
}
|
||||
|
||||
/// Edit the syntax tree to keep it in sync with source code that has been
|
||||
|
|
@ -894,8 +919,8 @@ impl<'tree> Node<'tree> {
|
|||
|
||||
/// Get the [`Language`] that was used to parse this node's syntax tree.
|
||||
#[doc(alias = "ts_node_language")]
|
||||
pub fn language(&self) -> Language {
|
||||
Language(unsafe { ffi::ts_node_language(self.0) })
|
||||
pub fn language(&self) -> LanguageRef {
|
||||
LanguageRef(unsafe { ffi::ts_node_language(self.0) }, PhantomData)
|
||||
}
|
||||
|
||||
/// Check if this node is *named*.
|
||||
|
|
@ -1473,8 +1498,11 @@ impl Drop for TreeCursor<'_> {
|
|||
impl LookaheadIterator {
|
||||
/// 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()) })
|
||||
pub fn language(&self) -> LanguageRef<'_> {
|
||||
LanguageRef(
|
||||
unsafe { ffi::ts_lookahead_iterator_language(self.0.as_ptr()) },
|
||||
PhantomData,
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the current symbol of the lookahead iterator.
|
||||
|
|
@ -1553,7 +1581,7 @@ impl Query {
|
|||
/// The query is associated with a particular language, and can only be run
|
||||
/// on syntax nodes parsed with that language. References to Queries can be
|
||||
/// shared between multiple threads.
|
||||
pub fn new(language: Language, source: &str) -> Result<Self, QueryError> {
|
||||
pub fn new(language: &Language, source: &str) -> Result<Self, QueryError> {
|
||||
let mut error_offset = 0u32;
|
||||
let mut error_type: ffi::TSQueryError = 0;
|
||||
let bytes = source.as_bytes();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{ffi, Language, LanguageError, Parser};
|
||||
use crate::{ffi, Language, LanguageError, Parser, FREE_FN};
|
||||
use std::{
|
||||
error,
|
||||
ffi::CString,
|
||||
ffi::{CStr, CString},
|
||||
fmt,
|
||||
mem::{self, MaybeUninit},
|
||||
os::raw::c_char,
|
||||
|
|
@ -73,11 +73,16 @@ impl WasmStore {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn language_count(&self) -> usize {
|
||||
unsafe { ffi::ts_wasm_store_language_count(self.0) as usize }
|
||||
}
|
||||
}
|
||||
|
||||
impl WasmError {
|
||||
unsafe fn new(error: ffi::TSWasmError) -> Self {
|
||||
let message = CString::from_raw(error.message);
|
||||
let message = CStr::from_ptr(error.message).to_str().unwrap().to_string();
|
||||
(FREE_FN)(error.message as *mut _);
|
||||
Self {
|
||||
kind: match error.kind {
|
||||
ffi::TSWasmErrorKindParse => WasmErrorKind::Parse,
|
||||
|
|
@ -85,7 +90,7 @@ impl WasmError {
|
|||
ffi::TSWasmErrorKindInstantiate => WasmErrorKind::Instantiate,
|
||||
_ => WasmErrorKind::Other,
|
||||
},
|
||||
message: message.into_string().unwrap(),
|
||||
message,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue