NOTES ON TREESIT_RECORD_CHANGE It is vital that Emacs informs tree-sitter of every change made to the buffer, lest tree-sitter's parse tree would be corrupted/out of sync. All buffer changes in Emacs are made through functions in insdel.c (and casefiddle.c), I augmented functions in those files with calls to treesit_record_change. Below is a manifest of all the relevant functions in insdel.c as of Emacs 29: Function Calls ---------------------------------------------------------------------- copy_text (*1) insert insert_1_both insert_and_inherit insert_1_both insert_char insert insert_string insert insert_before_markers insert_1_both insert_before_markers_and_inherit insert_1_both insert_1_both treesit_record_change insert_from_string insert_from_string_1 insert_from_string_before_markers insert_from_string_1 insert_from_string_1 treesit_record_change insert_from_gap_1 treesit_record_change insert_from_gap insert_from_gap_1 insert_from_buffer treesit_record_change insert_from_buffer_1 (used by insert_from_buffer) (*2) replace_range treesit_record_change replace_range_2 (caller needs to call treesit_r_c) del_range del_range_1 del_range_1 del_range_2 del_range_byte del_range_2 del_range_both del_range_2 del_range_2 treesit_record_change (*1) This functions is used only to copy from string to string when used outside of insdel.c, and when used inside insdel.c, the caller calls treesit_record_change. (*2) This function is a static function, and insert_from_buffer is its only caller. So it should be fine to call treesit_record_change in insert_from_buffer but not insert_from_buffer_1. I also left a reminder comment. As for casefiddle.c, do_casify_unibyte_region and do_casify_multibyte_region modifies buffer, but they are static functions and are called by casify_region, which calls treesit_record_change. Other higher-level functions calls casify_region to do the work.