From 2626c1a67ee2090f3acc75b993df1884addf8dab Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Sat, 20 Jul 2024 13:56:32 -0700 Subject: [PATCH] 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. (cherry picked from commit 1abf3bdd7edcd405d4ccb4ef4de38068348f4b95) --- src/treesit.c | 15 ++++++++++++--- src/treesit.h | 13 ++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/treesit.c b/src/treesit.c index a0e41add475..5ed15bca788 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -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; diff --git a/src/treesit.h b/src/treesit.h index d3c6aa4c250..3da4cc155ea 100644 --- a/src/treesit.h +++ b/src/treesit.h @@ -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; }; -- 2.39.2