Support dumping tree-sitter query (bug#69952)

Previous commit allows Emacs to dump tree-sitter queries by simply
dumping the query string and language symbol, and left the query object
and cursor object as NULL.  This commit makes sure Emacs doesn't crash
when loading the dumped query, by make sure Emacs can handle the case
where the cursor is NULL.

* src/treesit.c (make_treesit_query): Initialize query with null cursor.
(treesit_ensure_query_cursor): New function.
(treesit_initialize_query): Ensure cursor is non-null.
* src/treesit.h (Lisp_TS_Query): Update documentation.
This commit is contained in:
Yuan Fu 2024-07-20 13:56:32 -07:00
parent 1eca867e1b
commit 1abf3bdd7e
No known key found for this signature in database
GPG key ID: 56E19BC57664A442
2 changed files with 20 additions and 8 deletions

View file

@ -1201,7 +1201,6 @@ make_treesit_node (Lisp_Object parser, TSNode node)
static Lisp_Object
make_treesit_query (Lisp_Object query, Lisp_Object language)
{
TSQueryCursor *treesit_cursor = ts_query_cursor_new ();
struct Lisp_TS_Query *lisp_query;
lisp_query = ALLOCATE_PSEUDOVECTOR (struct Lisp_TS_Query,
@ -1210,7 +1209,7 @@ make_treesit_query (Lisp_Object query, Lisp_Object language)
lisp_query->language = language;
lisp_query->source = query;
lisp_query->query = NULL;
lisp_query->cursor = treesit_cursor;
lisp_query->cursor = NULL;
return make_lisp_ptr (lisp_query, Lisp_Vectorlike);
}
@ -1269,6 +1268,16 @@ treesit_compose_query_signal_data (uint32_t error_offset,
build_string ("Debug the query with `treesit-query-validate'"));
}
/* Ensure QUERY has a non-NULL cursor, and return it. */
static TSQueryCursor *
treesit_ensure_query_cursor (Lisp_Object query)
{
if (!XTS_COMPILED_QUERY (query)->cursor)
XTS_COMPILED_QUERY (query)->cursor = ts_query_cursor_new ();
return XTS_COMPILED_QUERY (query)->cursor;
}
/* Ensure the QUERY is compiled. Return the TSQuery. It could be
NULL if error occurs, in which case ERROR_OFFSET and ERROR_TYPE are
bound. If error occurs, return NULL, and assign SIGNAL_SYMBOL and
@ -2865,7 +2874,7 @@ treesit_initialize_query (Lisp_Object query, const TSLanguage *lang,
{
*ts_query = treesit_ensure_query_compiled (query, signal_symbol,
signal_data);
*cursor = XTS_COMPILED_QUERY (query)->cursor;
*cursor = treesit_ensure_query_cursor (query);
/* We don't need to free ts_query and cursor because they
are stored in a lisp object, which is tracked by gc. */
*need_free = false;

View file

@ -119,12 +119,15 @@ struct Lisp_TS_Query
Lisp_Object language;
/* Source lisp (sexp or string) query. */
Lisp_Object source;
/* Pointer to the query object. This can be NULL, meaning this
query is not initialized/compiled. We compile the query when
it is used the first time (in treesit-query-capture). */
/* Pointer to the query object. This can be NULL, meaning this query
is not initialized/compiled. We compile the query when it is used
the first time. (See treesit_ensure_query_compiled.) */
TSQuery *query;
/* Pointer to a cursor. If we are storing the query object, we
might as well store a cursor, too. */
/* Pointer to a cursor. If we are storing the query object, we might
as well store a cursor, too. This can be NULL; caller should use
treesit_ensure_query_cursor to access the cursor. We made cursor
to be NULL-able because it makes dumping and loading queries
easy. */
TSQueryCursor *cursor;
};