diff options
| author | Yuan Fu | 2024-06-01 10:20:48 -0700 |
|---|---|---|
| committer | Yuan Fu | 2024-06-01 10:29:55 -0700 |
| commit | 20af58d3a13ddb5c2ca376da8cdd3fde4833ca2d (patch) | |
| tree | 34911232c2aa99244baef21db031ee6a8b326e30 | |
| parent | bf50aa38f9d2a3a5af8d32ce139c7533c912c476 (diff) | |
| download | emacs-20af58d3a13ddb5c2ca376da8cdd3fde4833ca2d.tar.gz 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, | |||
| 2029 | print_c_string ("-outdated>", printcharfun); | 2029 | print_c_string ("-outdated>", printcharfun); |
| 2030 | break; | 2030 | break; |
| 2031 | } | 2031 | } |
| 2032 | if (!treesit_node_buffer_live_p (obj)) | ||
| 2033 | { | ||
| 2034 | print_c_string ("-in-killed-buffer>", printcharfun); | ||
| 2035 | break; | ||
| 2036 | } | ||
| 2032 | printchar (' ', printcharfun); | 2037 | printchar (' ', printcharfun); |
| 2033 | /* Now the node must be up-to-date, and calling functions like | 2038 | /* Now the node must be up-to-date, and calling functions like |
| 2034 | Ftreesit_node_start will not signal. */ | 2039 | 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) | |||
| 1786 | CHECK_TS_NODE (obj); | 1786 | CHECK_TS_NODE (obj); |
| 1787 | if (!treesit_node_uptodate_p (obj)) | 1787 | if (!treesit_node_uptodate_p (obj)) |
| 1788 | xsignal1 (Qtreesit_node_outdated, obj); | 1788 | xsignal1 (Qtreesit_node_outdated, obj); |
| 1789 | |||
| 1790 | /* Technically a lot of node functions can work without the | ||
| 1791 | associated buffer being alive, but I doubt there're any real | ||
| 1792 | use-cases for that; OTOH putting the buffer-liveness check here is | ||
| 1793 | simple, clean, and safe. */ | ||
| 1794 | if (!treesit_node_buffer_live_p (obj)) | ||
| 1795 | xsignal1 (Qtreesit_node_buffer_killed, obj); | ||
| 1789 | } | 1796 | } |
| 1790 | 1797 | ||
| 1791 | /* Checks that OBJ is a positive integer and it is within the visible | 1798 | /* Checks that OBJ is a positive integer and it is within the visible |
| @@ -1806,6 +1813,14 @@ treesit_node_uptodate_p (Lisp_Object obj) | |||
| 1806 | return XTS_NODE (obj)->timestamp == XTS_PARSER (lisp_parser)->timestamp; | 1813 | return XTS_NODE (obj)->timestamp == XTS_PARSER (lisp_parser)->timestamp; |
| 1807 | } | 1814 | } |
| 1808 | 1815 | ||
| 1816 | bool | ||
| 1817 | treesit_node_buffer_live_p (Lisp_Object obj) | ||
| 1818 | { | ||
| 1819 | struct buffer *buffer | ||
| 1820 | = XBUFFER (XTS_PARSER (XTS_NODE (obj)->parser)->buffer); | ||
| 1821 | return BUFFER_LIVE_P (buffer); | ||
| 1822 | } | ||
| 1823 | |||
| 1809 | DEFUN ("treesit-node-type", | 1824 | DEFUN ("treesit-node-type", |
| 1810 | Ftreesit_node_type, Streesit_node_type, 1, 1, 0, | 1825 | Ftreesit_node_type, Streesit_node_type, 1, 1, 0, |
| 1811 | doc: /* Return the NODE's type as a string. | 1826 | doc: /* Return the NODE's type as a string. |
| @@ -3549,6 +3564,8 @@ syms_of_treesit (void) | |||
| 3549 | "treesit-load-language-error"); | 3564 | "treesit-load-language-error"); |
| 3550 | DEFSYM (Qtreesit_node_outdated, | 3565 | DEFSYM (Qtreesit_node_outdated, |
| 3551 | "treesit-node-outdated"); | 3566 | "treesit-node-outdated"); |
| 3567 | DEFSYM (Qtreesit_node_buffer_killed, | ||
| 3568 | "treesit-node-buffer-killed"); | ||
| 3552 | DEFSYM (Quser_emacs_directory, | 3569 | DEFSYM (Quser_emacs_directory, |
| 3553 | "user-emacs-directory"); | 3570 | "user-emacs-directory"); |
| 3554 | DEFSYM (Qtreesit_parser_deleted, "treesit-parser-deleted"); | 3571 | DEFSYM (Qtreesit_parser_deleted, "treesit-parser-deleted"); |
| @@ -3577,6 +3594,9 @@ syms_of_treesit (void) | |||
| 3577 | define_error (Qtreesit_node_outdated, | 3594 | define_error (Qtreesit_node_outdated, |
| 3578 | "This node is outdated, please retrieve a new one", | 3595 | "This node is outdated, please retrieve a new one", |
| 3579 | Qtreesit_error); | 3596 | Qtreesit_error); |
| 3597 | define_error (Qtreesit_node_buffer_killed, | ||
| 3598 | "The buffer associated with this node is killed", | ||
| 3599 | Qtreesit_error); | ||
| 3580 | define_error (Qtreesit_parser_deleted, | 3600 | define_error (Qtreesit_parser_deleted, |
| 3581 | "This parser is deleted and cannot be used", | 3601 | "This parser is deleted and cannot be used", |
| 3582 | Qtreesit_error); | 3602 | 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 *, | |||
| 189 | extern Lisp_Object make_treesit_node (Lisp_Object, TSNode); | 189 | extern Lisp_Object make_treesit_node (Lisp_Object, TSNode); |
| 190 | 190 | ||
| 191 | extern bool treesit_node_uptodate_p (Lisp_Object); | 191 | extern bool treesit_node_uptodate_p (Lisp_Object); |
| 192 | extern bool treesit_node_buffer_live_p (Lisp_Object); | ||
| 192 | 193 | ||
| 193 | extern void treesit_delete_parser (struct Lisp_TS_Parser *); | 194 | extern void treesit_delete_parser (struct Lisp_TS_Parser *); |
| 194 | extern void treesit_delete_query (struct Lisp_TS_Query *); | 195 | extern void treesit_delete_query (struct Lisp_TS_Query *); |