diff --git a/lisp/treesit.el b/lisp/treesit.el index 67be1e7d583..bedcc260750 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -634,20 +634,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 @@ -872,6 +891,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 diff --git a/test/src/treesit-tests.el b/test/src/treesit-tests.el index 24cd755fcf0..700b0505d71 100644 --- a/test/src/treesit-tests.el +++ b/test/src/treesit-tests.el @@ -684,6 +684,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))