aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYuan Fu2024-04-16 23:46:39 -0700
committerYuan Fu2024-04-19 19:04:44 -0700
commit996b9576713f9d63ea7ff7e9630a15cb0a0214eb (patch)
tree9e64d1677b26df5b52ee0baeb8d23fae643dfb19 /src
parent8166d9d1747648d1f457195090ad36dd333bbc52 (diff)
downloademacs-996b9576713f9d63ea7ff7e9630a15cb0a0214eb.tar.gz
emacs-996b9576713f9d63ea7ff7e9630a15cb0a0214eb.zip
New function treesit-parser-changed-ranges
- Add a new field last_changed_ranges to tree-sitter parser object. - Add a new function treesit-parser-changed-ranges * doc/lispref/parsing.texi (Using Parser): Add the function in tree-sitter manual. * src/treesit.c (treesit_get_changed_ranges): New function, refactored out of treesit_call_after_change_functions. (treesit_call_after_change_functions): Pull out treesit_get_changed_ranges. (treesit_ensure_parsed): Save the changed ranges to the parser object. (make_treesit_parser): Initialize the new parser field last_changed_ranges. (Ftreesit_parser_changed_ranges): New function. (Qtreesit_unparsed_edits): New error. * src/treesit.h (Lisp_TS_Parser): New field.
Diffstat (limited to 'src')
-rw-r--r--src/treesit.c49
-rw-r--r--src/treesit.h3
2 files changed, 48 insertions, 4 deletions
diff --git a/src/treesit.c b/src/treesit.c
index d86ab501187..76354361284 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -1017,9 +1017,8 @@ treesit_check_buffer_size (struct buffer *buffer)
1017 1017
1018static Lisp_Object treesit_make_ranges (const TSRange *, uint32_t, struct buffer *); 1018static Lisp_Object treesit_make_ranges (const TSRange *, uint32_t, struct buffer *);
1019 1019
1020static void 1020static Lisp_Object
1021treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree, 1021treesit_get_changed_ranges (TSTree *old_tree, TSTree *new_tree, Lisp_Object parser)
1022 Lisp_Object parser)
1023{ 1022{
1024 /* If the old_tree is NULL, meaning this is the first parse, the 1023 /* If the old_tree is NULL, meaning this is the first parse, the
1025 changed range is the whole buffer. */ 1024 changed range is the whole buffer. */
@@ -1039,7 +1038,13 @@ treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree,
1039 lisp_ranges = Fcons (Fcons (Fpoint_min (), Fpoint_max ()), Qnil); 1038 lisp_ranges = Fcons (Fcons (Fpoint_min (), Fpoint_max ()), Qnil);
1040 set_buffer_internal (oldbuf); 1039 set_buffer_internal (oldbuf);
1041 } 1040 }
1041 return lisp_ranges;
1042}
1042 1043
1044static void
1045treesit_call_after_change_functions (Lisp_Object lisp_ranges,
1046 Lisp_Object parser)
1047{
1043 specpdl_ref count = SPECPDL_INDEX (); 1048 specpdl_ref count = SPECPDL_INDEX ();
1044 1049
1045 /* let's trust the after change functions and not clone a new ranges 1050 /* let's trust the after change functions and not clone a new ranges
@@ -1091,13 +1096,17 @@ treesit_ensure_parsed (Lisp_Object parser)
1091 XTS_PARSER (parser)->tree = new_tree; 1096 XTS_PARSER (parser)->tree = new_tree;
1092 XTS_PARSER (parser)->need_reparse = false; 1097 XTS_PARSER (parser)->need_reparse = false;
1093 1098
1099 Lisp_Object changed_ranges;
1100 changed_ranges = treesit_get_changed_ranges (tree, new_tree, parser);
1101 XTS_PARSER (parser)->last_changed_ranges = changed_ranges;
1102
1094 /* After-change functions should run at the very end, most crucially 1103 /* After-change functions should run at the very end, most crucially
1095 after need_reparse is set to false, this way if the function 1104 after need_reparse is set to false, this way if the function
1096 calls some tree-sitter function which invokes 1105 calls some tree-sitter function which invokes
1097 treesit_ensure_parsed again, it returns early and do not 1106 treesit_ensure_parsed again, it returns early and do not
1098 recursively call the after change functions again. 1107 recursively call the after change functions again.
1099 (ref:notifier-inside-ensure-parsed) */ 1108 (ref:notifier-inside-ensure-parsed) */
1100 treesit_call_after_change_functions (tree, new_tree, parser); 1109 treesit_call_after_change_functions (changed_ranges, parser);
1101 ts_tree_delete (tree); 1110 ts_tree_delete (tree);
1102} 1111}
1103 1112
@@ -1171,6 +1180,7 @@ make_treesit_parser (Lisp_Object buffer, TSParser *parser,
1171 lisp_parser->after_change_functions = Qnil; 1180 lisp_parser->after_change_functions = Qnil;
1172 lisp_parser->tag = tag; 1181 lisp_parser->tag = tag;
1173 lisp_parser->last_set_ranges = Qnil; 1182 lisp_parser->last_set_ranges = Qnil;
1183 lisp_parser->last_changed_ranges = Qnil;
1174 lisp_parser->buffer = buffer; 1184 lisp_parser->buffer = buffer;
1175 lisp_parser->parser = parser; 1185 lisp_parser->parser = parser;
1176 lisp_parser->tree = tree; 1186 lisp_parser->tree = tree;
@@ -1818,6 +1828,32 @@ positions. PARSER is the parser issuing the notification. */)
1818 return Qnil; 1828 return Qnil;
1819} 1829}
1820 1830
1831DEFUN ("treesit-parser-changed-ranges", Ftreesit_parser_changed_ranges,
1832 Streesit_parser_changed_ranges,
1833 1, 2, 0,
1834 doc: /* Return the buffer regions affected by the last reparse of PARSER.
1835
1836Returns a list of cons (BEG . END), where each cons represents a region
1837in which the buffer content was affected by the last reparse.
1838
1839This function should almost always be called immediately after
1840reparsing. If it's called when there are new buffer edits that hasn't
1841been reparsed, Emacs signals `treesit-unparsed-edits', unless QUIET is
1842non-nil.
1843
1844Calling this function multiple times consecutively doesn't change its
1845return value; it always returns the ranges affected by the last
1846reparse. */)
1847 (Lisp_Object parser, Lisp_Object quiet)
1848{
1849 treesit_check_parser (parser);
1850
1851 if (XTS_PARSER (parser)->need_reparse && NILP (quiet))
1852 xsignal1 (Qtreesit_unparsed_edits, parser);
1853
1854 return XTS_PARSER (parser)->last_changed_ranges;
1855}
1856
1821 1857
1822/*** Node API */ 1858/*** Node API */
1823 1859
@@ -4010,6 +4046,7 @@ syms_of_treesit (void)
4010 DEFSYM (Qtreesit_query_error, "treesit-query-error"); 4046 DEFSYM (Qtreesit_query_error, "treesit-query-error");
4011 DEFSYM (Qtreesit_parse_error, "treesit-parse-error"); 4047 DEFSYM (Qtreesit_parse_error, "treesit-parse-error");
4012 DEFSYM (Qtreesit_range_invalid, "treesit-range-invalid"); 4048 DEFSYM (Qtreesit_range_invalid, "treesit-range-invalid");
4049 DEFSYM (Qtreesit_unparsed_edits, "treesit-unparsed_edits");
4013 DEFSYM (Qtreesit_buffer_too_large, 4050 DEFSYM (Qtreesit_buffer_too_large,
4014 "treesit-buffer-too-large"); 4051 "treesit-buffer-too-large");
4015 DEFSYM (Qtreesit_load_language_error, 4052 DEFSYM (Qtreesit_load_language_error,
@@ -4038,6 +4075,8 @@ syms_of_treesit (void)
4038 define_error (Qtreesit_range_invalid, 4075 define_error (Qtreesit_range_invalid,
4039 "RANGES are invalid: they have to be ordered and should not overlap", 4076 "RANGES are invalid: they have to be ordered and should not overlap",
4040 Qtreesit_error); 4077 Qtreesit_error);
4078 define_error (Qtreesit_unparsed_edits, "There are unparsed edits in the buffer",
4079 Qtreesit_error);
4041 define_error (Qtreesit_buffer_too_large, "Buffer too large (> 4GiB)", 4080 define_error (Qtreesit_buffer_too_large, "Buffer too large (> 4GiB)",
4042 Qtreesit_error); 4081 Qtreesit_error);
4043 define_error (Qtreesit_load_language_error, 4082 define_error (Qtreesit_load_language_error,
@@ -4178,6 +4217,8 @@ the symbol of that THING. For example, (or sexp sentence). */);
4178 defsubr (&Streesit_parser_add_notifier); 4217 defsubr (&Streesit_parser_add_notifier);
4179 defsubr (&Streesit_parser_remove_notifier); 4218 defsubr (&Streesit_parser_remove_notifier);
4180 4219
4220 defsubr (&Streesit_parser_changed_ranges);
4221
4181 defsubr (&Streesit_node_type); 4222 defsubr (&Streesit_node_type);
4182 defsubr (&Streesit_node_start); 4223 defsubr (&Streesit_node_start);
4183 defsubr (&Streesit_node_end); 4224 defsubr (&Streesit_node_end);
diff --git a/src/treesit.h b/src/treesit.h
index bb81bf0e2b3..aa71933fe8d 100644
--- a/src/treesit.h
+++ b/src/treesit.h
@@ -49,6 +49,9 @@ struct Lisp_TS_Parser
49 ranges the users wants to set, and avoid reparse if the new 49 ranges the users wants to set, and avoid reparse if the new
50 ranges is the same as the last set one. */ 50 ranges is the same as the last set one. */
51 Lisp_Object last_set_ranges; 51 Lisp_Object last_set_ranges;
52 /* The range of buffer content that was affected by the last
53 re-parse. */
54 Lisp_Object last_changed_ranges;
52 /* The buffer associated with this parser. */ 55 /* The buffer associated with this parser. */
53 Lisp_Object buffer; 56 Lisp_Object buffer;
54 /* The pointer to the tree-sitter parser. Never NULL. */ 57 /* The pointer to the tree-sitter parser. Never NULL. */