]> git.eshelyaron.com Git - emacs.git/commitdiff
Support dumping tree-sitter query (bug#69952)
authorYuan Fu <casouri@gmail.com>
Sat, 20 Jul 2024 20:56:32 +0000 (13:56 -0700)
committerEshel Yaron <me@eshelyaron.com>
Mon, 22 Jul 2024 10:38:14 +0000 (12:38 +0200)
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
src/treesit.h

index a0e41add4755269eadb9f6e0eb703a9c4f465671..5ed15bca78804f19ca119ec8522f6191e5f0fb94 100644 (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;
index d3c6aa4c250dad7173d64a981282d6a7dfb66964..3da4cc155ea9dc811d025a08fa11d355faba03c8 100644 (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;
 };