From 245366b18a0675dc56d3236895cf0e099385d720 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Fri, 25 Nov 2022 15:06:55 -0800 Subject: [PATCH] ; Add comments in treesit.c and treesit.h * src/treesit.c * src/treesit.h: Add (and fix) comments. --- src/treesit.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---- src/treesit.h | 13 ++++++------- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/treesit.c b/src/treesit.c index 3df53f2179d..66fd884efc3 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -707,6 +707,8 @@ treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte, Lisp_Object lisp_parser = XCAR (parser_list); treesit_check_parser (lisp_parser); TSTree *tree = XTS_PARSER (lisp_parser)->tree; + /* See comment (ref:visible-beg-null) if you wonder why we don't + update visible_beg/end when tree is NULL. */ if (tree != NULL) { eassert (start_byte <= old_end_byte); @@ -742,7 +744,7 @@ treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte, XTS_PARSER (lisp_parser)->timestamp++; /* VISIBLE_BEG/END records tree-sitter's range of view in - the buffer. Ee need to adjust them when tree-sitter's + the buffer. We need to adjust them when tree-sitter's view changes. */ ptrdiff_t visi_beg_delta; if (old_end_byte > new_end_byte) @@ -765,6 +767,44 @@ treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte, } } +/* Comment (ref:visible-beg-null) So the purpose of visible_beg/end + are to keep track of "which part of the buffer does the tree-sitter + tree sees", in order to update the tree correctly. Visible_beg/end + has two purposes: "clips" buffer changes within them, and translate + position in buffer to position in the tree (buf position - visi_beg + = tree position). + + Conceptually, visible_beg/end marks the visible region of the + buffer when we last reparsed. In between two reparse, we don't + really care if the visible region of the buffer changes. + + Right before we reparse, we make tree-sitter's visible region + matches that of the buffer, and update visible_beg/end. + + That is, the whole purpose of visible_beg/end (and + treesit_record_change and treesit_ensure_position_synced) is to + update the tree (by ts_tree_edit). So if the tree is NULL, we + don't update the tree and there is no need to keep tracking of + them. Only when we already have a tree, do we need to keep track + of position changes and update it correctly, so it can be feed into + ts_parser_parse as the old tree, so that tree-sitter only parses + the changed part (aka incremental). + + In a nutshell, tree-sitter incremental parsing in Emacs looks like: + + treesit_record_change(tree) \ + treesit_record_change(tree) | user edits buffer + ... / + + treesit_ensure_position_synced(tree) \ treesit_ensure_parsed + ts_parser_parse(tree) -> tree / + + treesit_record_change(tree) \ + treesit_record_change(tree) | user edits buffer + ... / + + and so on. */ + /* Make sure PARSER's visible_beg and visible_end are in sync with BUF_BEGV_BYTE and BUG_ZV_BYTE. When calling this function you must make sure the current buffer's size is not larger than UINT32_MAX. @@ -1365,9 +1405,10 @@ treesit_check_range_argument (Lisp_Object ranges) CHECK_LIST_END (tail, ranges); } -/* Generate a list of ranges in Lisp from RANGES. This function - doesn't take ownership of RANGES. BUFFER is used to convert - between tree-sitter buffer offset and buffer position. */ +/* Generate a list of ranges in Lisp from RANGES. Assumes tree-sitter + tree and the buffer has the same visible region (w.r.t narrowing). + This function doesn't take ownership of RANGES. BUFFER is used to + convert between tree-sitter buffer offset and buffer position. */ static Lisp_Object treesit_make_ranges (const TSRange *ranges, uint32_t len, struct buffer *buffer) diff --git a/src/treesit.h b/src/treesit.h index 1473126c5bc..6f6423ff472 100644 --- a/src/treesit.h +++ b/src/treesit.h @@ -56,13 +56,12 @@ struct Lisp_TS_Parser this field to true to force tree-sitter to re-parse. */ bool need_reparse; /* These two positions record the buffer byte position (1-based) of - the "visible region" that tree-sitter sees. Unlike markers, - These two positions do not change as the user inserts and deletes - text around them. Before re-parse, we move these positions to - match BUF_BEGV_BYTE and BUF_ZV_BYTE. Note that we don't need to - synchronize these positions when retrieving them in a function - that involves a node: if the node is not outdated, these - positions are synchronized. */ + the "visible region" that tree-sitter sees. Before re-parse, we + move these positions to match BUF_BEGV_BYTE and BUF_ZV_BYTE. + Note that we don't need to synchronize these positions when + retrieving them in a function that involves a node: if the node + is not outdated, these positions are synchronized. See comment + (ref:visible-beg-null) in treesit.c for more explanation. */ ptrdiff_t visible_beg; ptrdiff_t visible_end; /* This counter is incremented every time a change is made to the -- 2.39.2