diff options
| author | Yuan Fu <casouri@gmail.com> | 2022-12-28 15:19:34 -0800 |
|---|---|---|
| committer | Yuan Fu <casouri@gmail.com> | 2022-12-28 15:19:34 -0800 |
| commit | ec6feeaa19117deb0d60e97ad814b87ecbb7fa99 (patch) | |
| tree | f4663ffde848f6e1f8d64128aa5a86eb92af5400 /src | |
| parent | db96b1282f90ee40560f81e8b715fe785badbb6e (diff) | |
Fix tree-sitter parser notifier recursion
See the comment for detail.
* src/treesit.c (treesit_ensure_parsed): Move the need_reparse short
circuit to the very beginning. Move the call to
treesit_call_after_change_functions to the very end.
Diffstat (limited to 'src')
| -rw-r--r-- | src/treesit.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/src/treesit.c b/src/treesit.c index 813d4222f98..e226df263c1 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -955,6 +955,11 @@ treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree, static void treesit_ensure_parsed (Lisp_Object parser) { + /* Make sure this comes before everything else, see comment + (ref:notifier-inside-ensure-parsed) for more detail. */ + if (!XTS_PARSER (parser)->need_reparse) + return; + struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer); /* Before we parse, catch up with the narrowing situation. */ @@ -963,8 +968,6 @@ treesit_ensure_parsed (Lisp_Object parser) because it might set the flag to true. */ treesit_sync_visible_region (parser); - if (!XTS_PARSER (parser)->need_reparse) - return; TSParser *treesit_parser = XTS_PARSER (parser)->parser; TSTree *tree = XTS_PARSER (parser)->tree; TSInput input = XTS_PARSER (parser)->input; @@ -984,14 +987,20 @@ treesit_ensure_parsed (Lisp_Object parser) xsignal1 (Qtreesit_parse_error, buf); } + XTS_PARSER (parser)->tree = new_tree; + XTS_PARSER (parser)->need_reparse = false; + + /* After-change functions should run at the very end, most crucially + after need_reparse is set to false, this way if the function + calls some tree-sitter function which invokes + treesit_ensure_parsed again, it returns early and do not + recursively call the after change functions again. + (ref:notifier-inside-ensure-parsed) */ if (tree != NULL) { treesit_call_after_change_functions (tree, new_tree, parser); ts_tree_delete (tree); } - - XTS_PARSER (parser)->tree = new_tree; - XTS_PARSER (parser)->need_reparse = false; } /* This is the read function provided to tree-sitter to read from a |
