diff options
| author | Yuan Fu | 2024-07-20 13:56:32 -0700 |
|---|---|---|
| committer | Yuan Fu | 2024-07-20 14:00:47 -0700 |
| commit | 1abf3bdd7edcd405d4ccb4ef4de38068348f4b95 (patch) | |
| tree | 2fdcc8436a77598caa4560f500fd87167fe0c9bc /src | |
| parent | 1eca867e1b60acef7f4343bc5c70340de58f1079 (diff) | |
| download | emacs-1abf3bdd7edcd405d4ccb4ef4de38068348f4b95.tar.gz emacs-1abf3bdd7edcd405d4ccb4ef4de38068348f4b95.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/treesit.c | 15 | ||||
| -rw-r--r-- | 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) | |||
| 1201 | static Lisp_Object | 1201 | static Lisp_Object |
| 1202 | make_treesit_query (Lisp_Object query, Lisp_Object language) | 1202 | make_treesit_query (Lisp_Object query, Lisp_Object language) |
| 1203 | { | 1203 | { |
| 1204 | TSQueryCursor *treesit_cursor = ts_query_cursor_new (); | ||
| 1205 | struct Lisp_TS_Query *lisp_query; | 1204 | struct Lisp_TS_Query *lisp_query; |
| 1206 | 1205 | ||
| 1207 | lisp_query = ALLOCATE_PSEUDOVECTOR (struct Lisp_TS_Query, | 1206 | lisp_query = ALLOCATE_PSEUDOVECTOR (struct Lisp_TS_Query, |
| @@ -1210,7 +1209,7 @@ make_treesit_query (Lisp_Object query, Lisp_Object language) | |||
| 1210 | lisp_query->language = language; | 1209 | lisp_query->language = language; |
| 1211 | lisp_query->source = query; | 1210 | lisp_query->source = query; |
| 1212 | lisp_query->query = NULL; | 1211 | lisp_query->query = NULL; |
| 1213 | lisp_query->cursor = treesit_cursor; | 1212 | lisp_query->cursor = NULL; |
| 1214 | return make_lisp_ptr (lisp_query, Lisp_Vectorlike); | 1213 | return make_lisp_ptr (lisp_query, Lisp_Vectorlike); |
| 1215 | } | 1214 | } |
| 1216 | 1215 | ||
| @@ -1269,6 +1268,16 @@ treesit_compose_query_signal_data (uint32_t error_offset, | |||
| 1269 | build_string ("Debug the query with `treesit-query-validate'")); | 1268 | build_string ("Debug the query with `treesit-query-validate'")); |
| 1270 | } | 1269 | } |
| 1271 | 1270 | ||
| 1271 | /* Ensure QUERY has a non-NULL cursor, and return it. */ | ||
| 1272 | static TSQueryCursor * | ||
| 1273 | treesit_ensure_query_cursor (Lisp_Object query) | ||
| 1274 | { | ||
| 1275 | if (!XTS_COMPILED_QUERY (query)->cursor) | ||
| 1276 | XTS_COMPILED_QUERY (query)->cursor = ts_query_cursor_new (); | ||
| 1277 | |||
| 1278 | return XTS_COMPILED_QUERY (query)->cursor; | ||
| 1279 | } | ||
| 1280 | |||
| 1272 | /* Ensure the QUERY is compiled. Return the TSQuery. It could be | 1281 | /* Ensure the QUERY is compiled. Return the TSQuery. It could be |
| 1273 | NULL if error occurs, in which case ERROR_OFFSET and ERROR_TYPE are | 1282 | NULL if error occurs, in which case ERROR_OFFSET and ERROR_TYPE are |
| 1274 | bound. If error occurs, return NULL, and assign SIGNAL_SYMBOL and | 1283 | bound. If error occurs, return NULL, and assign SIGNAL_SYMBOL and |
| @@ -2865,7 +2874,7 @@ treesit_initialize_query (Lisp_Object query, const TSLanguage *lang, | |||
| 2865 | { | 2874 | { |
| 2866 | *ts_query = treesit_ensure_query_compiled (query, signal_symbol, | 2875 | *ts_query = treesit_ensure_query_compiled (query, signal_symbol, |
| 2867 | signal_data); | 2876 | signal_data); |
| 2868 | *cursor = XTS_COMPILED_QUERY (query)->cursor; | 2877 | *cursor = treesit_ensure_query_cursor (query); |
| 2869 | /* We don't need to free ts_query and cursor because they | 2878 | /* We don't need to free ts_query and cursor because they |
| 2870 | are stored in a lisp object, which is tracked by gc. */ | 2879 | are stored in a lisp object, which is tracked by gc. */ |
| 2871 | *need_free = false; | 2880 | *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 | |||
| 119 | Lisp_Object language; | 119 | Lisp_Object language; |
| 120 | /* Source lisp (sexp or string) query. */ | 120 | /* Source lisp (sexp or string) query. */ |
| 121 | Lisp_Object source; | 121 | Lisp_Object source; |
| 122 | /* Pointer to the query object. This can be NULL, meaning this | 122 | /* Pointer to the query object. This can be NULL, meaning this query |
| 123 | query is not initialized/compiled. We compile the query when | 123 | is not initialized/compiled. We compile the query when it is used |
| 124 | it is used the first time (in treesit-query-capture). */ | 124 | the first time. (See treesit_ensure_query_compiled.) */ |
| 125 | TSQuery *query; | 125 | TSQuery *query; |
| 126 | /* Pointer to a cursor. If we are storing the query object, we | 126 | /* Pointer to a cursor. If we are storing the query object, we might |
| 127 | might as well store a cursor, too. */ | 127 | as well store a cursor, too. This can be NULL; caller should use |
| 128 | treesit_ensure_query_cursor to access the cursor. We made cursor | ||
| 129 | to be NULL-able because it makes dumping and loading queries | ||
| 130 | easy. */ | ||
| 128 | TSQueryCursor *cursor; | 131 | TSQueryCursor *cursor; |
| 129 | }; | 132 | }; |
| 130 | 133 | ||