1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-30 04:10:54 -08:00

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.
This commit is contained in:
Alan Mackenzie 2019-11-30 21:22:55 +00:00
parent 3c278b4999
commit 757e66afdc
2 changed files with 95 additions and 38 deletions

View file

@ -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

View file

@ -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