feat(lib): add ts_query_cursor_exec_with_options

Currently, this allows users to pass in a callback that should be
invoked to check whether or not to halt query execution
This commit is contained in:
Amaan Qureshi 2024-10-27 23:57:08 -04:00
parent 26b89da9bb
commit 8d68980aa8
3 changed files with 73 additions and 1 deletions

View file

@ -162,6 +162,19 @@ pub const TSQueryErrorCapture: TSQueryError = 4;
pub const TSQueryErrorStructure: TSQueryError = 5;
pub const TSQueryErrorLanguage: TSQueryError = 6;
pub type TSQueryError = ::core::ffi::c_uint;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct TSQueryCursorState {
pub payload: *mut ::core::ffi::c_void,
pub current_byte_offset: u32,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct TSQueryCursorOptions {
pub payload: *mut ::core::ffi::c_void,
pub progress_callback:
::core::option::Option<unsafe extern "C" fn(state: *mut TSQueryCursorState) -> bool>,
}
extern "C" {
#[doc = " Create a new parser."]
pub fn ts_parser_new() -> *mut TSParser;
@ -662,6 +675,15 @@ extern "C" {
#[doc = " Start running a given query on a given node."]
pub fn ts_query_cursor_exec(self_: *mut TSQueryCursor, query: *const TSQuery, node: TSNode);
}
extern "C" {
#[doc = " Start running a gievn query on a given node, with some options."]
pub fn ts_query_cursor_exec_with_options(
self_: *mut TSQueryCursor,
query: *const TSQuery,
node: TSNode,
options: *const TSQueryCursorOptions,
);
}
extern "C" {
#[doc = " Manage the maximum number of in-progress matches allowed by this query\n cursor.\n\n Query cursors have an optional maximum capacity for storing lists of\n in-progress captures. If this capacity is exceeded, then the\n earliest-starting match will silently be dropped to make room for further\n matches. This maximum capacity is optional — by default, query cursors allow\n any number of pending matches, dynamically allocating new space for them as\n needed as the query is executed."]
pub fn ts_query_cursor_did_exceed_match_limit(self_: *const TSQueryCursor) -> bool;

View file

@ -161,6 +161,16 @@ typedef enum TSQueryError {
TSQueryErrorLanguage,
} TSQueryError;
typedef struct TSQueryCursorState {
void *payload;
uint32_t current_byte_offset;
} TSQueryCursorState;
typedef struct TSQueryCursorOptions {
void *payload;
bool (*progress_callback)(TSQueryCursorState *state);
} TSQueryCursorOptions;
/********************/
/* Section - Parser */
/********************/
@ -1020,6 +1030,16 @@ void ts_query_cursor_delete(TSQueryCursor *self);
*/
void ts_query_cursor_exec(TSQueryCursor *self, const TSQuery *query, TSNode node);
/**
* Start running a gievn query on a given node, with some options.
*/
void ts_query_cursor_exec_with_options(
TSQueryCursor *self,
const TSQuery *query,
TSNode node,
const TSQueryCursorOptions *query_options
);
/**
* Manage the maximum number of in-progress matches allowed by this query
* cursor.
@ -1036,6 +1056,8 @@ uint32_t ts_query_cursor_match_limit(const TSQueryCursor *self);
void ts_query_cursor_set_match_limit(TSQueryCursor *self, uint32_t limit);
/**
* @deprecated use [`ts_query_cursor_exec_with_options`] and pass in a callback instead, this will be removed in 0.26.
*
* Set the maximum duration in microseconds that query execution should be allowed to
* take before halting.
*
@ -1045,6 +1067,8 @@ void ts_query_cursor_set_match_limit(TSQueryCursor *self, uint32_t limit);
void ts_query_cursor_set_timeout_micros(TSQueryCursor *self, uint64_t timeout_micros);
/**
* @deprecated use [`ts_query_cursor_exec_with_options`] and pass in a callback instead, this will be removed in 0.26.
*
* Get the duration in microseconds that query execution is allowed to take.
*
* This is set via [`ts_query_cursor_set_timeout_micros`].

View file

@ -315,6 +315,8 @@ struct TSQueryCursor {
uint32_t next_state_id;
TSClock end_clock;
TSDuration timeout_duration;
const TSQueryCursorOptions *query_options;
TSQueryCursorState query_state;
unsigned operation_count;
bool on_visible_node;
bool ascending;
@ -3082,6 +3084,23 @@ void ts_query_cursor_exec(
} else {
self->end_clock = clock_null();
}
self->query_options = NULL;
self->query_state = (TSQueryCursorState) {0};
}
void ts_query_cursor_exec_with_options(
TSQueryCursor *self,
const TSQuery *query,
TSNode node,
const TSQueryCursorOptions *query_options
) {
ts_query_cursor_exec(self, query, node);
if (query_options) {
self->query_options = query_options;
self->query_state = (TSQueryCursorState) {
.payload = query_options->payload
};
}
}
void ts_query_cursor_set_byte_range(
@ -3481,12 +3500,19 @@ static inline bool ts_query_cursor__advance(
if (++self->operation_count == OP_COUNT_PER_QUERY_TIMEOUT_CHECK) {
self->operation_count = 0;
}
if (self->query_options && self->query_options->progress_callback) {
self->query_state.current_byte_offset = ts_node_start_byte(ts_tree_cursor_current_node(&self->cursor));
}
if (
did_match ||
self->halted ||
(
self->operation_count == 0 &&
!clock_is_null(self->end_clock) && clock_is_gt(clock_now(), self->end_clock)
(
(!clock_is_null(self->end_clock) && clock_is_gt(clock_now(), self->end_clock)) ||
(self->query_options && self->query_options->progress_callback && self->query_options->progress_callback(&self->query_state))
)
)
) {
return did_match;