]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix treesit--merge-ranges (bug#73324)
authorYuan Fu <casouri@gmail.com>
Sat, 21 Sep 2024 03:40:26 +0000 (20:40 -0700)
committerEshel Yaron <me@eshelyaron.com>
Mon, 23 Sep 2024 10:45:21 +0000 (12:45 +0200)
* lisp/treesit.el (treesit--merge-ranges): Make sure that old
ranges that intersects with START-END are actually discarded.
* test/src/treesit-tests.el (treesit-range-merge): New test.

(cherry picked from commit 0834106a6209833ab5f5c032cce857f39889d3d6)

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

index 77a2d01adf670385a0094e06a577b1ee8fa02519..473152c109e32e76ff1e80dc11972c3026dc1727 100644 (file)
@@ -623,20 +623,39 @@ Return the merged list of ranges."
          ;; New range and old range don't intersect, new comes
          ;; before, push new.
          ((<= new-end old-beg)
-          (push (car new-ranges) result)
+          (unless (eq new-beg new-end)
+            (push (car new-ranges) result))
           (setq new-ranges (cdr new-ranges)))
          ;; New range and old range don't intersect, old comes
          ;; before, push old.
          ((<= old-end new-beg)
-          (push (car old-ranges) result)
+          (unless (eq old-beg old-end)
+            (push (car old-ranges) result))
           (setq old-ranges (cdr old-ranges)))
          (t ;; New and old range intersect, discard old.
           (setq old-ranges (cdr old-ranges))))))
-    (let ((left-over (or new-ranges old-ranges)))
-      (dolist (range left-over)
-        (push range result)))
+    ;; At this point, either old-ranges has left-over or new-ranges has
+    ;; left-over, but not both.
+    (while old-ranges
+      ;; For each left-over old range, push to result unless it
+      ;; intersects with START-END.
+      (let ((old-beg (caar old-ranges))
+            (old-end (cdar old-ranges)))
+        (unless (or (and (< start old-end)
+                         (< old-beg end))
+                    (eq old-beg old-end))
+          (push (car old-ranges) result)))
+      (setq old-ranges (cdr old-ranges)))
+    ;; Unconditionally push left-over new ranges to result.
+    (while new-ranges
+      (unless (eq (caar new-ranges) (cdar new-ranges))
+        (push (car new-ranges) result))
+      (setq new-ranges (cdr new-ranges)))
     (nreverse result)))
 
+;; TODO: truncate ranges that exceeds START and END instead of
+;; discarding them.  Merge into treesit--merge-ranges so we don't loop
+;; over the ranges twice (might be premature optimization tho).
 (defun treesit--clip-ranges (ranges start end)
   "Clip RANGES in between START and END.
 RANGES is a list of ranges of the form (BEG . END).  Ranges
@@ -861,6 +880,7 @@ SETTING should be a setting in `treesit-font-lock-settings'."
     (setf (nth 1 new-setting) t)
     new-setting))
 
+;; FIXME: Rewrite this in more readable fashion.
 (defun treesit--font-lock-level-setter (sym val)
   "Custom setter for `treesit-font-lock-level'.
 Set the default value of SYM to VAL, recompute fontification
index 7eecbdcfa94a02e491b5c67de7e3931e34d5a5cb..ca595c41244d0fb0fa5606b78db1cdb4f15c873a 100644 (file)
@@ -686,6 +686,11 @@ visible_end.)"
       (should (equal '((16 . 28)) (treesit-query-range
                                    'javascript query nil nil '(1 . -1)))))))
 
+(ert-deftest treesit-range-merge ()
+  "Test merging ranges."
+  (should (equal (treesit--merge-ranges '((1 . 1) (3 . 483)) nil 1 488)
+                 nil)))
+
 (ert-deftest treesit-range-fixup-after-edit ()
   "Tests if Emacs can fix OOB ranges after deleting text or narrowing."
   (skip-unless (treesit-language-available-p 'json))