aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2019-11-30 21:22:55 +0000
committerAlan Mackenzie2019-11-30 21:26:00 +0000
commit757e66afdc1cd4f0a261d368cafd5009e04084a4 (patch)
tree874f5b30fdca4ca6b234c543bb57d36e5017682f
parent3c278b4999632621ef9690b319798d4ed752b163 (diff)
downloademacs-757e66afdc1cd4f0a261d368cafd5009e04084a4.tar.gz
emacs-757e66afdc1cd4f0a261d368cafd5009e04084a4.zip
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.
-rw-r--r--lisp/progmodes/cc-defs.el23
-rw-r--r--lisp/progmodes/cc-mode.el110
2 files changed, 95 insertions, 38 deletions
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el
index 6a9371e6f19..c6818819e74 100644
--- a/lisp/progmodes/cc-defs.el
+++ b/lisp/progmodes/cc-defs.el
@@ -1340,6 +1340,29 @@ nil; point is then left undefined."
1340 (search-forward-regexp "\\(\n\\|.\\)") ; to set the match-data. 1340 (search-forward-regexp "\\(\n\\|.\\)") ; to set the match-data.
1341 (point)))) 1341 (point))))
1342 1342
1343(defmacro c-search-backward-char-property-with-value-on-char
1344 (property value char &optional limit)
1345 "Search backward for a text-property PROPERTY having value VALUE on a
1346character with value CHAR.
1347LIMIT bounds the search. The value comparison is done with `equal'.
1348PROPERTY must be a constant.
1349
1350Leave point just before the character, and set the match data on
1351this character, and return point. If the search fails, return
1352nil; point is then left undefined."
1353 `(let ((char-skip (concat "^" (char-to-string ,char)))
1354 (-limit- (or ,limit (point-min)))
1355 (-value- ,value))
1356 (while
1357 (and
1358 (progn (skip-chars-backward char-skip -limit-)
1359 (> (point) -limit-))
1360 (not (equal (c-get-char-property (1- (point)) ,property) -value-)))
1361 (backward-char))
1362 (when (> (point) -limit-)
1363 (search-backward-regexp "\\(\n\\|.\\)") ; to set the match-data.
1364 (point))))
1365
1343(defmacro c-search-forward-char-property-without-value-on-char 1366(defmacro c-search-forward-char-property-without-value-on-char
1344 (property value char &optional limit) 1367 (property value char &optional limit)
1345 "Search forward for a character CHAR without text property PROPERTY having 1368 "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 73160fc7a42..7fcc8a6d1c5 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."
1233 ;; Check we haven't left any unbalanced "s. 1233 ;; Check we haven't left any unbalanced "s.
1234 (save-excursion 1234 (save-excursion
1235 (setq pos beg) 1235 (setq pos beg)
1236 ;; Is there already an unbalanced " before BEG?
1237 (setq pos (c-min-property-position pos end 'c-fl-syn-tab))
1238 (when (< pos end) (goto-char pos))
1239 (when (and (save-match-data
1240 (c-search-backward-char-property-with-value-on-char
1241 'c-fl-syn-tab '(15) ?\"
1242 (max (- (point) 500) (point-min))))
1243 (not (equal (c-get-char-property (point) 'syntax-table) '(1))))
1244 (setq pos (1+ pos)))
1236 (while (< pos end) 1245 (while (< pos end)
1237 (setq pos 1246 (setq pos
1238 (c-min-property-position pos end 'c-fl-syn-tab)) 1247 (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....\".")
2234 ;; line was fouled up by context fontification. 2243 ;; line was fouled up by context fontification.
2235 (save-restriction 2244 (save-restriction
2236 (widen) 2245 (widen)
2237 (let (new-beg new-end new-region case-fold-search) 2246 (let (new-beg new-end new-region case-fold-search string-fence-beg lim)
2238 (if (and c-in-after-change-fontification 2247 ;; Check how far back we need to extend the region where we reapply the
2239 (< beg c-new-END) (> end c-new-BEG)) 2248 ;; string fence syntax-table properties. These must be in place for the
2240 ;; Region and the latest after-change fontification region overlap. 2249 ;; coming fontification operations.
2241 ;; Determine the upper and lower bounds of our adjusted region 2250 (save-excursion
2242 ;; separately. 2251 (goto-char (if c-in-after-change-fontification
2243 (progn 2252 (min beg c-new-BEG)
2244 (if (<= beg c-new-BEG) 2253 beg))
2245 (setq c-in-after-change-fontification nil)) 2254 (setq lim (max (- (point) 500) (point-min)))
2246 (setq new-beg 2255 (while
2247 (if (and (>= beg (c-point 'bol c-new-BEG)) 2256 (progn
2248 (<= beg c-new-BEG)) 2257 (skip-chars-backward "^\"" lim)
2249 ;; Either jit-lock has accepted `c-new-BEG', or has 2258 (or (bobp) (backward-char))
2250 ;; (probably) extended the change region spuriously to 2259 (save-excursion
2251 ;; BOL, which position likely has a syntactically 2260 (eq (logand (skip-chars-backward "\\\\") 1) 1))))
2252 ;; different position. To ensure correct fontification, 2261 (setq string-fence-beg
2253 ;; we start at `c-new-BEG', assuming any characters to the 2262 (cond ((c-get-char-property (point) 'c-fl-syn-tab)
2254 ;; left of `c-new-BEG' on the line do not require 2263 (point))
2255 ;; fontification. 2264 (c-in-after-change-fontification
2256 c-new-BEG 2265 c-new-BEG)
2257 (setq new-region (c-before-context-fl-expand-region beg end) 2266 (t beg)))
2258 new-end (cdr new-region)) 2267 (c-save-buffer-state nil
2259 (car new-region))) 2268 ;; Temporarily reapply the string fence syntax-table properties.
2260 (setq new-end 2269 (c-with-extended-string-fences
2261 (if (and (>= end (c-point 'bol c-new-END)) 2270 string-fence-beg (if c-in-after-change-fontification
2262 (<= end c-new-END)) 2271 (max end c-new-END)
2263 c-new-END 2272 end)
2264 (or new-end 2273
2265 (cdr (c-before-context-fl-expand-region beg end)))))) 2274 (if (and c-in-after-change-fontification
2266 ;; Context (etc.) fontification. 2275 (< beg c-new-END) (> end c-new-BEG))
2267 (setq new-region (c-before-context-fl-expand-region beg end) 2276 ;; Region and the latest after-change fontification region overlap.
2268 new-beg (car new-region) new-end (cdr new-region))) 2277 ;; Determine the upper and lower bounds of our adjusted region
2269 (c-save-buffer-state nil 2278 ;; separately.
2270 (unwind-protect 2279 (progn
2271 (progn (c-restore-string-fences new-beg new-end) 2280 (if (<= beg c-new-BEG)
2272 (funcall (default-value 'font-lock-fontify-region-function) 2281 (setq c-in-after-change-fontification nil))
2273 new-beg new-end verbose)) 2282 (setq new-beg
2274 (c-clear-string-fences)))))) 2283 (if (and (>= beg (c-point 'bol c-new-BEG))
2284 (<= beg c-new-BEG))
2285 ;; Either jit-lock has accepted `c-new-BEG', or has
2286 ;; (probably) extended the change region spuriously
2287 ;; to BOL, which position likely has a
2288 ;; syntactically different position. To ensure
2289 ;; correct fontification, we start at `c-new-BEG',
2290 ;; assuming any characters to the left of
2291 ;; `c-new-BEG' on the line do not require
2292 ;; fontification.
2293 c-new-BEG
2294 (setq new-region (c-before-context-fl-expand-region beg end)
2295 new-end (cdr new-region))
2296 (car new-region)))
2297 (setq new-end
2298 (if (and (>= end (c-point 'bol c-new-END))
2299 (<= end c-new-END))
2300 c-new-END
2301 (or new-end
2302 (cdr (c-before-context-fl-expand-region beg end))))))
2303 ;; Context (etc.) fontification.
2304 (setq new-region (c-before-context-fl-expand-region beg end)
2305 new-beg (car new-region) new-end (cdr new-region)))
2306 ;; Finally invoke font lock's functionality.
2307 (funcall (default-value 'font-lock-fontify-region-function)
2308 new-beg new-end verbose)))))))
2275 2309
2276(defun c-after-font-lock-init () 2310(defun c-after-font-lock-init ()
2277 ;; Put on `font-lock-mode-hook'. This function ensures our after-change 2311 ;; Put on `font-lock-mode-hook'. This function ensures our after-change