diff options
author | Yuan Fu <casouri@gmail.com> | 2024-06-01 10:20:48 -0700 |
---|---|---|
committer | Yuan Fu <casouri@gmail.com> | 2024-06-01 10:29:55 -0700 |
commit | 20af58d3a13ddb5c2ca376da8cdd3fde4833ca2d (patch) | |
tree | 34911232c2aa99244baef21db031ee6a8b326e30 | |
parent | bf50aa38f9d2a3a5af8d32ce139c7533c912c476 (diff) | |
download | emacs-20af58d3a13ddb5c2ca376da8cdd3fde4833ca2d.tar.gz emacs-20af58d3a13ddb5c2ca376da8cdd3fde4833ca2d.tar.bz2 emacs-20af58d3a13ddb5c2ca376da8cdd3fde4833ca2d.zip |
Check for buffer liveness when accessing tree-sitter node (bug#71012)
* src/treesit.h (treesit_node_buffer_live_p): Declare function.
* src/print.c (print_vectorlike): Print node without position if
buffer is killed.
* src/treesit.c (treesit_node_buffer_live_p): New function.
(treesit_check_node): Add buffer liveness check.
(syms_of_treesit): New error treesit-node-buffer-killed.
-rw-r--r-- | src/print.c | 5 | ||||
-rw-r--r-- | src/treesit.c | 20 | ||||
-rw-r--r-- | src/treesit.h | 1 |
3 files changed, 26 insertions, 0 deletions
diff --git a/src/print.c b/src/print.c index d52d98ad371..8ee5a3616eb 100644 --- a/src/print.c +++ b/src/print.c @@ -2029,6 +2029,11 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, print_c_string ("-outdated>", printcharfun); break; } + if (!treesit_node_buffer_live_p (obj)) + { + print_c_string ("-in-killed-buffer>", printcharfun); + break; + } printchar (' ', printcharfun); /* Now the node must be up-to-date, and calling functions like Ftreesit_node_start will not signal. */ diff --git a/src/treesit.c b/src/treesit.c index 21c61a35e70..45efa429f9a 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -1786,6 +1786,13 @@ treesit_check_node (Lisp_Object obj) CHECK_TS_NODE (obj); if (!treesit_node_uptodate_p (obj)) xsignal1 (Qtreesit_node_outdated, obj); + + /* Technically a lot of node functions can work without the + associated buffer being alive, but I doubt there're any real + use-cases for that; OTOH putting the buffer-liveness check here is + simple, clean, and safe. */ + if (!treesit_node_buffer_live_p (obj)) + xsignal1 (Qtreesit_node_buffer_killed, obj); } /* Checks that OBJ is a positive integer and it is within the visible @@ -1806,6 +1813,14 @@ treesit_node_uptodate_p (Lisp_Object obj) return XTS_NODE (obj)->timestamp == XTS_PARSER (lisp_parser)->timestamp; } +bool +treesit_node_buffer_live_p (Lisp_Object obj) +{ + struct buffer *buffer + = XBUFFER (XTS_PARSER (XTS_NODE (obj)->parser)->buffer); + return BUFFER_LIVE_P (buffer); +} + DEFUN ("treesit-node-type", Ftreesit_node_type, Streesit_node_type, 1, 1, 0, doc: /* Return the NODE's type as a string. @@ -3549,6 +3564,8 @@ syms_of_treesit (void) "treesit-load-language-error"); DEFSYM (Qtreesit_node_outdated, "treesit-node-outdated"); + DEFSYM (Qtreesit_node_buffer_killed, + "treesit-node-buffer-killed"); DEFSYM (Quser_emacs_directory, "user-emacs-directory"); DEFSYM (Qtreesit_parser_deleted, "treesit-parser-deleted"); @@ -3577,6 +3594,9 @@ syms_of_treesit (void) define_error (Qtreesit_node_outdated, "This node is outdated, please retrieve a new one", Qtreesit_error); + define_error (Qtreesit_node_buffer_killed, + "The buffer associated with this node is killed", + Qtreesit_error); define_error (Qtreesit_parser_deleted, "This parser is deleted and cannot be used", Qtreesit_error); diff --git a/src/treesit.h b/src/treesit.h index f5c8c67395d..dcb19648a37 100644 --- a/src/treesit.h +++ b/src/treesit.h @@ -189,6 +189,7 @@ extern Lisp_Object make_treesit_parser (Lisp_Object, TSParser *, TSTree *, extern Lisp_Object make_treesit_node (Lisp_Object, TSNode); extern bool treesit_node_uptodate_p (Lisp_Object); +extern bool treesit_node_buffer_live_p (Lisp_Object); extern void treesit_delete_parser (struct Lisp_TS_Parser *); extern void treesit_delete_query (struct Lisp_TS_Query *); |