]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix tree-sitter parser notifier recursion
authorYuan Fu <casouri@gmail.com>
Wed, 28 Dec 2022 23:19:34 +0000 (15:19 -0800)
committerYuan Fu <casouri@gmail.com>
Wed, 28 Dec 2022 23:19:34 +0000 (15:19 -0800)
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.

src/treesit.c

index 813d4222f98a482718532344017631dc03bc0825..e226df263c18c826689a2b937e9e18718351cdec 100644 (file)
@@ -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