]> git.eshelyaron.com Git - emacs.git/commitdiff
(Freplace_match): Fix bug#65451
authorStefan Monnier <monnier@iro.umontreal.ca>
Sun, 7 Apr 2024 18:16:38 +0000 (14:16 -0400)
committerEshel Yaron <me@eshelyaron.com>
Wed, 10 Apr 2024 20:27:42 +0000 (22:27 +0200)
* src/search.c (Freplace_match): For ordering of *-change-functions.

* test/src/editfns-tests.el
(editfns-tests--before/after-change-functions): New test.
(sanity-check--message, sanity-check-change-functions-error)
(sanity-check-change-functions-check-size)
(sanity-check-change-functions-before)
(sanity-check-change-functions-after): New functions.
(sanity-check--verbose, sanity-check-change-functions-beg)
(sanity-check-change-functions-end)
(sanity-check-change-functions-buffer-size)
(sanity-check-change-functions-errors): New vars.

(cherry picked from commit 63588775fcb64e4fd88a97e0882aae38c9f5fb1c)

src/search.c
test/src/editfns-tests.el

index f2d1f1f544945c880ef705ea876acee44bbc6979..b092d5b7fef438b44310d8304c5db27862b22789 100644 (file)
@@ -2759,6 +2759,7 @@ since only regular expressions have distinguished subexpressions.  */)
 
   /* Replace the old text with the new in the cleanest possible way.  */
   replace_range (sub_start, sub_end, newtext, 1, 0, 1, true, true);
+  signal_after_change (sub_start, sub_end - sub_start, SCHARS (newtext));
 
   if (case_action == all_caps)
     Fupcase_region (make_fixnum (search_regs.start[sub]),
@@ -2783,7 +2784,6 @@ since only regular expressions have distinguished subexpressions.  */)
   /* Now move point "officially" to the end of the inserted replacement.  */
   move_if_not_intangible (newpoint);
 
-  signal_after_change (sub_start, sub_end - sub_start, SCHARS (newtext));
   update_compositions (sub_start, newpoint, CHECK_BORDER);
 
   return Qnil;
index b3b7da65ad327ad649c2e60c3689ad3b255ee919..a14a5f90b65c0eeccee524b6e7d12553bab0a8bd 100644 (file)
     (should (= (field-beginning) 7))
     (should (= (field-end) (point-max)))))
 
+;;; Try and catch `*-changes-functions' bugs!
+
+(defvar sanity-check--verbose nil)
+(defun sanity-check--message (&rest args)
+  (if sanity-check--verbose (apply #'message args)))
+
+(defvar-local sanity-check-change-functions-beg 0)
+(defvar-local sanity-check-change-functions-end 0)
+(defvar-local sanity-check-change-functions-buffer-size nil)
+(defvar sanity-check-change-functions-errors nil)
+
+(defun sanity-check-change-functions-error (description &rest args)
+  (push (apply #'format description args)
+        sanity-check-change-functions-errors))
+
+(defun sanity-check-change-functions-check-size ()
+  (sanity-check--message "Size  : %S == %S"
+                         sanity-check-change-functions-buffer-size
+                         (buffer-size))
+  (cond
+   ((null sanity-check-change-functions-buffer-size)
+    (setq sanity-check-change-functions-buffer-size (buffer-size)))
+   ((equal sanity-check-change-functions-buffer-size (buffer-size)) nil)
+   (t
+    (sanity-check-change-functions-error
+     "buffer-size %S == %S"
+     (buffer-size) sanity-check-change-functions-buffer-size)
+    (setq sanity-check-change-functions-buffer-size (buffer-size)))))
+
+(defun sanity-check-change-functions-before (beg end)
+  (sanity-check--message "Before: %S %S" beg end)
+  (unless (<= (point-min) beg end (point-max))
+    (sanity-check-change-functions-error
+     "Position bounds: %S <= %S <= %S <= %S"
+     (point-min) beg end (point-max)))
+  (sanity-check-change-functions-check-size)
+  (setq sanity-check-change-functions-beg beg)
+  (setq sanity-check-change-functions-end end))
+
+(defun sanity-check-change-functions-after (beg end len)
+  (sanity-check--message "After : %S %S (%S)" beg end len)
+  (unless (<= (point-min) beg end (point-max))
+    (sanity-check-change-functions-error
+     "Position bounds: %S <= %S <= %S <= %S"
+     (point-min) beg end (point-max)))
+  (unless (>= len 0)
+    (sanity-check-change-functions-error "len: %S >= 0" len))
+  (let ((bend (+ beg len)))
+    (unless (<= sanity-check-change-functions-beg
+                beg bend
+                sanity-check-change-functions-end)
+      (sanity-check-change-functions-error
+       "After covered by before: %S <= %S <= %S <= %S"
+       sanity-check-change-functions-beg beg bend
+       sanity-check-change-functions-end)))
+  (let ((offset (- end beg len)))
+    (setq sanity-check-change-functions-end
+          (+ sanity-check-change-functions-end offset))
+    (setq sanity-check-change-functions-buffer-size
+          (+ sanity-check-change-functions-buffer-size offset)))
+  (sanity-check-change-functions-check-size))
+
+(ert-deftest editfns-tests--before/after-change-functions ()
+  (with-temp-buffer
+    (add-hook 'before-change-functions
+              #'sanity-check-change-functions-before nil t)
+    (add-hook 'after-change-functions
+              #'sanity-check-change-functions-after nil t)
+
+    ;; Bug#65451
+    (insert "utf-8-unix\n\nUTF")
+    (call-interactively 'dabbrev-expand)
+    (should (null sanity-check-change-functions-errors))))
+
 ;;; editfns-tests.el ends here