emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 757e66a: CC Mode. Fix fontification bug with unterminated quotes


From: Alan Mackenzie
Subject: master 757e66a: CC Mode. Fix fontification bug with unterminated quotes on adjacent lines
Date: Sat, 30 Nov 2019 16:27:04 -0500 (EST)

branch: master
commit 757e66afdc1cd4f0a261d368cafd5009e04084a4
Author: Alan Mackenzie <address@hidden>
Commit: Alan Mackenzie <address@hidden>

    CC Mode.  Fix fontification bug with unterminated quotes on adjacent lines
    
    In particular, with these unterminated quotes on each of two adjacent lines,
    the following text was spuriously fontified with string face.
    
    * lisp/progmodes/cc-defs.el
    (c-search-backward-char-property-with-value-on-char): New macro.
    
    * lisp/progmodes/cc-mode.el (c-clear-string-fences): Check whether there is 
an
    unmatched quote at a lower buffer position which should match the current
    quote, rather than wrongly assuming the latter is unmatched and marking it
    with a punctuation syntax.
    (c-font-lock-fontify-region): Ensure all pertinent parts of the buffer have
    string fence properties applied before performing any syntactic operations 
on
    it; in particular, this applies to a quote at an earlier buffer position 
which
    "matches" one inside the region about to be fontified.
---
 lisp/progmodes/cc-defs.el |  23 ++++++++++
 lisp/progmodes/cc-mode.el | 110 ++++++++++++++++++++++++++++++----------------
 2 files changed, 95 insertions(+), 38 deletions(-)

diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 6a9371e..c681881 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -1340,6 +1340,29 @@ nil; point is then left undefined."
        (search-forward-regexp "\\(\n\\|.\\)")  ; to set the match-data.
        (point))))
 
+(defmacro c-search-backward-char-property-with-value-on-char
+    (property value char &optional limit)
+  "Search backward for a text-property PROPERTY having value VALUE on a
+character with value CHAR.
+LIMIT bounds the search.  The value comparison is done with `equal'.
+PROPERTY must be a constant.
+
+Leave point just before the character, and set the match data on
+this character, and return point.  If the search fails, return
+nil; point is then left undefined."
+  `(let ((char-skip (concat "^" (char-to-string ,char)))
+        (-limit- (or ,limit (point-min)))
+        (-value- ,value))
+     (while
+        (and
+         (progn (skip-chars-backward char-skip -limit-)
+                (> (point) -limit-))
+         (not (equal (c-get-char-property (1- (point)) ,property) -value-)))
+       (backward-char))
+     (when (> (point) -limit-)
+       (search-backward-regexp "\\(\n\\|.\\)") ; to set the match-data.
+       (point))))
+
 (defmacro c-search-forward-char-property-without-value-on-char
     (property value char &optional limit)
   "Search forward for a character CHAR without text property PROPERTY having
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 73160fc..7fcc8a6 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1233,6 +1233,15 @@ Note that the style variables are always made local to 
the buffer."
       ;; Check we haven't left any unbalanced "s.
       (save-excursion
        (setq pos beg)
+       ;; Is there already an unbalanced " before BEG?
+       (setq pos (c-min-property-position pos end 'c-fl-syn-tab))
+       (when (< pos end) (goto-char pos))
+       (when (and (save-match-data
+                    (c-search-backward-char-property-with-value-on-char
+                     'c-fl-syn-tab '(15) ?\"
+                     (max (- (point) 500) (point-min))))
+                  (not (equal (c-get-char-property (point) 'syntax-table) 
'(1))))
+         (setq pos (1+ pos)))
        (while (< pos end)
          (setq pos
                (c-min-property-position pos end 'c-fl-syn-tab))
@@ -2234,44 +2243,69 @@ Note that this is a strict tail, so won't match, e.g. 
\"0x....\".")
   ;; line was fouled up by context fontification.
   (save-restriction
     (widen)
-    (let (new-beg new-end new-region case-fold-search)
-      (if (and c-in-after-change-fontification
-              (< beg c-new-END) (> end c-new-BEG))
-         ;; Region and the latest after-change fontification region overlap.
-         ;; Determine the upper and lower bounds of our adjusted region
-         ;; separately.
-         (progn
-           (if (<= beg c-new-BEG)
-               (setq c-in-after-change-fontification nil))
-           (setq new-beg
-                 (if (and (>= beg (c-point 'bol c-new-BEG))
-                          (<= beg c-new-BEG))
-                     ;; Either jit-lock has accepted `c-new-BEG', or has
-                     ;; (probably) extended the change region spuriously to
-                     ;; BOL, which position likely has a syntactically
-                     ;; different position.  To ensure correct fontification,
-                     ;; we start at `c-new-BEG', assuming any characters to the
-                     ;; left of `c-new-BEG' on the line do not require
-                     ;; fontification.
-                     c-new-BEG
-                   (setq new-region (c-before-context-fl-expand-region beg end)
-                         new-end (cdr new-region))
-                   (car new-region)))
-           (setq new-end
-                 (if (and (>= end (c-point 'bol c-new-END))
-                          (<= end c-new-END))
-                     c-new-END
-                   (or new-end
-                       (cdr (c-before-context-fl-expand-region beg end))))))
-       ;; Context (etc.) fontification.
-       (setq new-region (c-before-context-fl-expand-region beg end)
-             new-beg (car new-region)  new-end (cdr new-region)))
-      (c-save-buffer-state nil
-       (unwind-protect
-           (progn (c-restore-string-fences new-beg new-end)
-                  (funcall (default-value 'font-lock-fontify-region-function)
-                           new-beg new-end verbose))
-         (c-clear-string-fences))))))
+    (let (new-beg new-end new-region case-fold-search string-fence-beg lim)
+      ;; Check how far back we need to extend the region where we reapply the
+      ;; string fence syntax-table properties.  These must be in place for the
+      ;; coming fontification operations.
+      (save-excursion
+       (goto-char (if c-in-after-change-fontification
+                      (min beg c-new-BEG)
+                    beg))
+       (setq lim (max (- (point) 500) (point-min)))
+       (while
+           (progn
+             (skip-chars-backward "^\"" lim)
+             (or (bobp) (backward-char))
+             (save-excursion
+               (eq (logand (skip-chars-backward "\\\\") 1) 1))))
+       (setq string-fence-beg
+             (cond ((c-get-char-property (point) 'c-fl-syn-tab)
+                    (point))
+                   (c-in-after-change-fontification
+                    c-new-BEG)
+                   (t beg)))
+       (c-save-buffer-state nil
+         ;; Temporarily reapply the string fence syntax-table properties.
+         (c-with-extended-string-fences
+          string-fence-beg (if c-in-after-change-fontification
+                               (max end c-new-END)
+                             end)
+
+          (if (and c-in-after-change-fontification
+                   (< beg c-new-END) (> end c-new-BEG))
+              ;; Region and the latest after-change fontification region 
overlap.
+              ;; Determine the upper and lower bounds of our adjusted region
+              ;; separately.
+              (progn
+                (if (<= beg c-new-BEG)
+                    (setq c-in-after-change-fontification nil))
+                (setq new-beg
+                      (if (and (>= beg (c-point 'bol c-new-BEG))
+                               (<= beg c-new-BEG))
+                          ;; Either jit-lock has accepted `c-new-BEG', or has
+                          ;; (probably) extended the change region spuriously
+                          ;; to BOL, which position likely has a
+                          ;; syntactically different position.  To ensure
+                          ;; correct fontification, we start at `c-new-BEG',
+                          ;; assuming any characters to the left of
+                          ;; `c-new-BEG' on the line do not require
+                          ;; fontification.
+                          c-new-BEG
+                        (setq new-region (c-before-context-fl-expand-region 
beg end)
+                              new-end (cdr new-region))
+                        (car new-region)))
+                (setq new-end
+                      (if (and (>= end (c-point 'bol c-new-END))
+                               (<= end c-new-END))
+                          c-new-END
+                        (or new-end
+                            (cdr (c-before-context-fl-expand-region beg 
end))))))
+            ;; Context (etc.) fontification.
+            (setq new-region (c-before-context-fl-expand-region beg end)
+                  new-beg (car new-region)  new-end (cdr new-region)))
+          ;; Finally invoke font lock's functionality.
+          (funcall (default-value 'font-lock-fontify-region-function)
+                   new-beg new-end verbose)))))))
 
 (defun c-after-font-lock-init ()
   ;; Put on `font-lock-mode-hook'.  This function ensures our after-change



reply via email to

[Prev in Thread] Current Thread [Next in Thread]