Fix treesit_sync_visible_region's range fixup code (bug#73264)
authorYuan Fu <casouri@gmail.com>
Sun, 15 Sep 2024 07:24:03 +0000 (00:24 -0700)
committerYuan Fu <casouri@gmail.com>
Sun, 15 Sep 2024 07:31:40 +0000 (00:31 -0700)
      new_ranges_head
      |
      v
( )->( )->( )->( )->( )
           ^    ^
           |    |
           |    lisp_ranges (loop head)
           |
           prev_cons -> set cdr to nil to cut of the rest

result:

     ( )->( )

* src/treesit.c (treesit_sync_visible_region): Cut off this cons and the
rest, not set the current range's end to nil.
* test/src/treesit-tests.el:
(treesit-range-fixup-after-edit): Add tests for all cases.

src/treesit.c
test/src/treesit-tests.el

index 9958d8a4c2ac910df0f904ce96159a6e6675a723..628a4dff9cce68573def69e6b61acf2a021c2069 100644 (file)
@@ -1064,6 +1064,7 @@ treesit_sync_visible_region (Lisp_Object parser)
   if (NILP (lisp_ranges)) return;
 
   Lisp_Object new_ranges_head = lisp_ranges;
+  Lisp_Object prev_cons = Qnil;
 
   FOR_EACH_TAIL_SAFE (lisp_ranges)
   {
@@ -1076,9 +1077,12 @@ treesit_sync_visible_region (Lisp_Object parser)
       new_ranges_head = XCDR (new_ranges_head);
     else if (beg >= visible_end)
       {
-       /* Even the beg is after visible_end, dicard this range and all
+       /* Even the beg is after visible_end, discard this range and all
            the ranges after it.  */
-       XSETCDR (range, Qnil);
+       if (NILP (prev_cons))
+         new_ranges_head = Qnil;
+       else
+         XSETCDR (prev_cons, Qnil);
        break;
       }
     else
@@ -1091,12 +1095,18 @@ treesit_sync_visible_region (Lisp_Object parser)
        if (end > visible_end)
          XSETCDR (range, make_fixnum (visible_end));
       }
+    prev_cons = lisp_ranges;
   }
 
   XTS_PARSER (parser)->last_set_ranges = new_ranges_head;
 
   if (NILP (new_ranges_head))
     {
+      /* We are in a weird situation here: none of the previous ranges
+         overlaps with the new visible region.  We don't have any good
+         options, so just throw the towel: just remove ranges and hope
+         lisp world will soon update with reasonable ranges or just
+         delete this parser.   */
       bool success;
       success = ts_parser_set_included_ranges (XTS_PARSER (parser)->parser,
                                               NULL, 0);
index 98aaeb62781c8a7381fc6cbb5a8cf473dd1a4f9b..68ed6ca751fd6109a8d04bb238cfc44a10083fb2 100644 (file)
@@ -709,7 +709,37 @@ visible_end.)"
                      '((1 . 7) (10 . 15))))
       (narrow-to-region 5 13)
       (should (equal (treesit-parser-included-ranges parser)
-                     '((5 . 7) (10 . 13)))))))
+                     '((5 . 7) (10 . 13))))
+
+      ;; Narrow in front.
+      (widen)
+      (treesit-parser-set-included-ranges parser '((4 . 17)))
+      ;; 11111111111111111111
+      ;;    [           ]
+      ;; {     } narrow
+      (narrow-to-region 1 8)
+      (should (equal (treesit-parser-included-ranges parser)
+                     '((4 . 8))))
+
+      ;; Narrow in back.
+      (widen)
+      (treesit-parser-set-included-ranges parser '((4 . 17)))
+      ;; 11111111111111111111
+      ;;    [           ]
+      ;;              {     } narrow
+      (narrow-to-region 15 20)
+      (should (equal (treesit-parser-included-ranges parser)
+                     '((15 . 17))))
+
+      ;; No overlap
+      (widen)
+      (treesit-parser-set-included-ranges parser '((15 . 20)))
+      ;; 11111111111111111111
+      ;;    [           ]
+      ;;              {     } narrow
+      (narrow-to-region 1 10)
+      (should (equal (treesit-parser-included-ranges parser)
+                     nil)))))
 
 ;;; Multiple language