]> git.eshelyaron.com Git - emacs.git/commitdiff
Don't mess up syntax-ppss cache in electric-pair (Bug#29710)
authorNoam Postavsky <npostavs@gmail.com>
Fri, 15 Dec 2017 02:25:13 +0000 (21:25 -0500)
committerNoam Postavsky <npostavs@gmail.com>
Sun, 17 Dec 2017 02:02:38 +0000 (21:02 -0500)
In Emacs 25 and above, calling `scan-sexps', `parse-partial-sexp', or
similar may update the syntax-ppss cache if
`parse-sexp-lookup-properties' is non-nil.  Therefore, when calling
any of these functions with a different than normal syntax-table, the
cache must be cleaned afterwards.
* lisp/elec-pair.el (electric-pair--with-uncached-syntax): New macro.
(electric-pair--syntax-ppss, electric-pair--balance-info): Use it.

lisp/elec-pair.el

index 7f523d1df451a6f7124acbb92e22ddbfb4909122..a980f51d3c01f82dc9118002ff6af9c7ca0bdf7d 100644 (file)
@@ -24,6 +24,7 @@
 ;;; Code:
 
 (require 'electric)
+(eval-when-compile (require 'cl-lib))
 
 ;;; Electric pairing.
 
@@ -222,6 +223,22 @@ inside a comment or string."
        (electric-pair-mode nil))
     (self-insert-command 1)))
 
+(cl-defmacro electric-pair--with-uncached-syntax ((table &optional start) &rest body)
+  "Like `with-syntax-table', but flush the syntax-ppss cache afterwards.
+Use this instead of (with-syntax-table TABLE BODY) when BODY
+contains code which may update the syntax-ppss cache.  This
+includes calling `parse-partial-sexp' and any sexp-based movement
+functions when `parse-sexp-lookup-properties' is non-nil.  The
+cache is flushed from position START, defaulting to point."
+  (declare (debug ((form &optional form) body)) (indent 1))
+  (let ((start-var (make-symbol "start")))
+    `(let ((syntax-propertize-function nil)
+           (,start-var ,(or start '(point))))
+       (unwind-protect
+           (with-syntax-table ,table
+             ,@body)
+         (syntax-ppss-flush-cache ,start-var)))))
+
 (defun electric-pair--syntax-ppss (&optional pos where)
   "Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'.
 
@@ -240,7 +257,8 @@ when to fallback to `parse-partial-sexp'."
                               (skip-syntax-forward " >!")
                               (point)))))
     (if s-or-c-start
-        (with-syntax-table electric-pair-text-syntax-table
+        (electric-pair--with-uncached-syntax (electric-pair-text-syntax-table
+                                              s-or-c-start)
           (parse-partial-sexp s-or-c-start pos))
       ;; HACK! cc-mode apparently has some `syntax-ppss' bugs
       (if (memq major-mode '(c-mode c++ mode))
@@ -293,7 +311,8 @@ If point is not enclosed by any lists, return ((t) . (t))."
                         (cond ((< direction 0)
                                (condition-case nil
                                    (eq (char-after pos)
-                                       (with-syntax-table table
+                                       (electric-pair--with-uncached-syntax
+                                           (table)
                                          (matching-paren
                                           (char-before
                                            (scan-sexps (point) 1)))))
@@ -323,7 +342,7 @@ If point is not enclosed by any lists, return ((t) . (t))."
     (save-excursion
       (while (not outermost)
         (condition-case err
-            (with-syntax-table table
+            (electric-pair--with-uncached-syntax (table)
               (scan-sexps (point) (if (> direction 0)
                                       (point-max)
                                     (- (point-max))))