Commit 29ec1e48 authored by Alan Mackenzie's avatar Alan Mackenzie

Improve C++ raw string fontification.

Integrate the handling of raw string and ordinary string fontification.

* lisp/progmodes/cc-defs.el (c-font-lock-flush)
(c-search-forward-char-property-without-value-on-char): new macros.
(c-point): In the 'eoll arm, check for eobp.
(c-search-forward-char-property-with-value-on-char): Handle the &optional
limit argument being nil.
(c-clear-char-property-with-value-on-char-function)
(c-clear-char-property-with-value-on-char): Return the position of the first
cleared property.

* lisp/progmodes/cc-engine.el (c-find-decl-prefix-search): Don't spuriously
recognize the change of face at a ) as the start of a string (a
"pseudo match").
(c-old-beg-rs c-old-end-rs): New variables.
(c-raw-string-pos): Analyze raw string delimiters more carefully.
(c-raw-string-in-end-delim): New function.
(c-depropertize-raw-string): Largely rewritten.
(c-before-change-check-raw-strings): New functionality: only remove the
syntax-table text properties from raw strings whose delimiters are about to
change.
(c-propertize-raw-string-id): New function.
(c-after-change-re-mark-raw-strings): Remove, incorporating functionality into
other functions.
(c-propertize-raw-string-opener): Largely rewritten.
(c-after-change-re-mark-raw-strings): Removed.
(c-after-change-unmark-raw-strings, c-after-change-unmark-raw-strings): New
functions.

* lisp/progmodes/cc-fonts.el (c-font-lock-raw-strings): Largely rewritten.

* lisp/progmodes/cc-langs.el (c-before-font-lock-functions): Replace
c-after-change-re-mark-unbalanced-strings by
c-after-change-mark-abnormal-strings in the t, c+objc, c++ and java sections.
Add c-after-change-unmark-raw-strings and remove
c-after-change-re-mark-raw-strings from the c++ section.

* lisp/progmodes/cc-mode.el (c-old-BEG c-old-END): Remove.
(c-old-END-literality): New variable.
(c-depropertize-CPP): Remove syntax-table properties from raw strings within
macros.
(c-before-change-check-unbalanced-strings): Call
c-truncate-semi-nonlit-pos-cache to preserve the integrity of the cache.
(c-before-change-check-unbalanced-strings): Call
c-truncate-semi-nonlit-pos-cache, largely rewritten.
(c-after-change-re-mark-unbalanced-strings): Renamed to
c-after-change-mark-abnormal-strings.  Call c-maybe-re-mark-raw-string.
parent c2670448
Pipeline #1090 failed with stage
in 49 minutes and 56 seconds
......@@ -212,6 +212,13 @@ This variant works around bugs in `eval-when-compile' in various
`(cl-delete-duplicates ,cl-seq ,@cl-keys)
`(delete-duplicates ,cl-seq ,@cl-keys))))
(defmacro c-font-lock-flush (beg end)
"Declare the region BEG...END's fontification as out-of-date.
On XEmacs and older Emacsen, this refontifies that region immediately."
(if (fboundp 'font-lock-flush)
`(font-lock-flush ,beg ,end)
`(font-lock-fontify-region ,beg ,end)))
(defmacro c-point (position &optional point)
"Return the value of certain commonly referenced POSITIONs relative to POINT.
The current point is used if POINT isn't specified. POSITION can be
......@@ -258,10 +265,12 @@ to it is returned. This function does not modify the point or the mark."
((eq position 'eoll)
`(save-excursion
,@(if point `((goto-char ,point)))
(while (progn
(end-of-line)
(prog1 (eq (logand 1 (skip-chars-backward "\\\\")) 1)))
(beginning-of-line 2))
(while (and
(not (eobp))
(progn
(end-of-line)
(prog1 (eq (logand 1 (skip-chars-backward "\\\\")) 1))))
(forward-line))
(end-of-line)
(point)))
......@@ -1214,7 +1223,7 @@ Leave point just after 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- ,limit)
(-limit- (or ,limit (point-max)))
(-value- ,value))
(while
(and
......@@ -1226,15 +1235,39 @@ nil; point is then left undefined."
(search-forward-regexp ".") ; 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
a value CHAR.
LIMIT bounds the search. The value comparison is done with `equal'.
PROPERTY must be a constant.
Leave point just after 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-max)))
(-value- ,value))
(while
(and
(progn (skip-chars-forward char-skip -limit-)
(< (point) -limit-))
(equal (c-get-char-property (point) ,property) -value-))
(forward-char))
(when (< (point) -limit-)
(search-forward-regexp ".") ; to set the match-data.
(point))))
(defun c-clear-char-property-with-value-on-char-function (from to property
value char)
"Remove all text-properties PROPERTY with value VALUE on
characters with value CHAR from the region [FROM, TO), as tested
by `equal'. These properties are assumed to be over individual
characters, having been put there by c-put-char-property. POINT
remains unchanged."
remains unchanged. Return the position of the first removed
property, or nil."
(let ((place from)
)
first)
(while ; loop round occurrences of (PROPERTY VALUE)
(progn
(while ; loop round changes in PROPERTY till we find VALUE
......@@ -1243,28 +1276,34 @@ remains unchanged."
(not (equal (get-text-property place property) value)))
(setq place (c-next-single-property-change place property nil to)))
(< place to))
(if (eq (char-after place) char)
(remove-text-properties place (1+ place) (cons property nil)))
(when (eq (char-after place) char)
(remove-text-properties place (1+ place) (cons property nil))
(or first (setq first place)))
;; Do we have to do anything with stickiness here?
(setq place (1+ place)))))
(setq place (1+ place)))
first))
(defmacro c-clear-char-property-with-value-on-char (from to property value char)
"Remove all text-properties PROPERTY with value VALUE on
characters with value CHAR from the region [FROM, TO), as tested
by `equal'. These properties are assumed to be over individual
characters, having been put there by c-put-char-property. POINT
remains unchanged."
remains unchanged. Return the position of the first removed
property, or nil."
(if c-use-extents
;; XEmacs
`(let ((-property- ,property)
(-char- ,char))
(-char- ,char)
(first (1+ (point-max))))
(map-extents (lambda (ext val)
(if (and (equal (extent-property ext -property-) val)
(eq (char-after
(extent-start-position ext))
-char-))
(delete-extent ext)))
nil ,from ,to ,value nil -property-))
(when (and (equal (extent-property ext -property-) val)
(eq (char-after
(extent-start-position ext))
-char-))
(setq first (min first (extent-start-position ext)))
(delete-extent ext)))
nil ,from ,to ,value nil -property-)
(and (<= first (point-max)) first))
;; GNU Emacs
`(c-clear-char-property-with-value-on-char-function ,from ,to ,property
,value ,char)))
......@@ -1316,6 +1355,7 @@ with value CHAR in the region [FROM to)."
;(eval-after-load "edebug" ; 2006-07-09: def-edebug-spec is now in subr.el.
; '(progn
(def-edebug-spec cc-eval-when-compile (&rest def-form))
(def-edebug-spec c-font-lock-flush t)
(def-edebug-spec c--mapcan t)
(def-edebug-spec c--set-difference (form form &rest [symbolp form]))
(def-edebug-spec c--intersection (form form &rest [symbolp form]))
......
This diff is collapsed.
......@@ -1674,25 +1674,36 @@ casts and declarations are fontified. Used on level 2 and higher."
(goto-char string-start)
(and (eq (char-before) ?R)
(looking-at "\"\\([^ ()\\\n\r\t]\\{0,16\\}\\)(")
(match-string-no-properties 1))))))
(match-string-no-properties 1)))))
(content-start (and raw-id (point))))
;; We go round the next loop twice per raw string, once for each "end".
(while (< (point) limit)
(if raw-id
;; Search for the raw string end delimiter
(progn
(if (search-forward-regexp (concat ")\\(" (regexp-quote raw-id) "\\)\"")
limit 'limit)
(c-put-font-lock-face (match-beginning 1) (point) 'default))
(when (search-forward-regexp (concat ")\\(" (regexp-quote raw-id) "\\)\"")
limit 'limit)
(c-put-font-lock-face content-start (match-beginning 1)
'font-lock-string-face)
(c-remove-font-lock-face (match-beginning 1) (point)))
(setq raw-id nil))
;; Search for the start of a raw string.
(when (search-forward-regexp
"R\\(\"\\)\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" limit 'limit)
(when
(or (and (eobp)
(eq (c-get-char-property (1- (point)) 'face)
'font-lock-warning-face))
(eq (c-get-char-property (point) 'face) 'font-lock-string-face)
(and (equal (c-get-char-property (match-end 2) 'syntax-table) '(1))
(equal (c-get-char-property (match-beginning 1) 'syntax-table)
'(1))))
;; Make sure we're not in a comment or string.
(and
(not (memq (c-get-char-property (match-beginning 0) 'face)
'(font-lock-comment-face font-lock-comment-delimiter-face
font-lock-string-face)))
(or (and (eobp)
(eq (c-get-char-property (1- (point)) 'face)
'font-lock-warning-face))
(not (eq (c-get-char-property (point) 'face) 'font-lock-comment-face))
;; (eq (c-get-char-property (point) 'face) 'font-lock-string-face)
(and (equal (c-get-char-property (match-end 2) 'syntax-table) '(1))
(equal (c-get-char-property (match-beginning 1) 'syntax-table)
'(1)))))
(let ((paren-prop (c-get-char-property (1- (point)) 'syntax-table)))
(if paren-prop
(progn
......@@ -1703,8 +1714,9 @@ casts and declarations are fontified. Used on level 2 and higher."
(equal paren-prop '(15))
(not (c-search-forward-char-property 'syntax-table '(15) limit)))
(goto-char limit)))
(c-put-font-lock-face (match-beginning 1) (match-end 2) 'default)
(setq raw-id (match-string-no-properties 2)))))))))
(c-remove-font-lock-face (match-beginning 0) (match-end 2))
(setq raw-id (match-string-no-properties 2))
(setq content-start (match-end 0)))))))))
nil)
(defun c-font-lock-c++-lambda-captures (limit)
......
......@@ -497,25 +497,25 @@ parameters \(point-min) and \(point-max).")
;; For documentation see the following c-lang-defvar of the same name.
;; The value here may be a list of functions or a single function.
t '(c-depropertize-new-text
c-after-change-re-mark-unbalanced-strings
c-after-change-mark-abnormal-strings
c-change-expand-fl-region)
(c objc) '(c-depropertize-new-text
c-parse-quotes-after-change
c-after-change-re-mark-unbalanced-strings
c-after-change-mark-abnormal-strings
c-extend-font-lock-region-for-macros
c-neutralize-syntax-in-CPP
c-change-expand-fl-region)
c++ '(c-depropertize-new-text
c-after-change-unmark-raw-strings
c-parse-quotes-after-change
c-after-change-re-mark-unbalanced-strings
c-after-change-mark-abnormal-strings
c-extend-font-lock-region-for-macros
c-after-change-re-mark-raw-strings
c-neutralize-syntax-in-CPP
c-restore-<>-properties
c-change-expand-fl-region)
java '(c-depropertize-new-text
c-parse-quotes-after-change
c-after-change-re-mark-unbalanced-strings
c-after-change-mark-abnormal-strings
c-restore-<>-properties
c-change-expand-fl-region)
awk '(c-depropertize-new-text
......
......@@ -678,14 +678,12 @@ that requires a literal mode spec at compile time."
(make-variable-buffer-local 'c-new-BEG)
(defvar c-new-END 0)
(make-variable-buffer-local 'c-new-END)
;; The following two variables record the values of `c-new-BEG' and
;; `c-new-END' just after `c-new-END' has been adjusted for the length of text
;; inserted or removed. They may be read by any after-change function (but
;; should not be altered by one).
(defvar c-old-BEG 0)
(make-variable-buffer-local 'c-old-BEG)
(defvar c-old-END 0)
(make-variable-buffer-local 'c-old-END)
;; Buffer local variable which notes the value of calling `c-in-literal' just
;; before a change. It is one of 'string, 'c, 'c++ (for the two sorts of
;; comments), or nil.
(defvar c-old-END-literality nil)
(make-variable-buffer-local 'c-old-END-literality)
(defun c-common-init (&optional mode)
"Common initialization for all CC Mode modes.
......@@ -900,7 +898,8 @@ Note that the style variables are always made local to the buffer."
(defun c-depropertize-CPP (beg end)
;; Remove the punctuation syntax-table text property from the CPP parts of
;; (c-new-BEG c-new-END).
;; (c-new-BEG c-new-END), and remove all syntax-table properties from any
;; raw strings within these CPP parts.
;;
;; This function is in the C/C++/ObjC values of
;; `c-get-state-before-change-functions' and is called exclusively as a
......@@ -912,6 +911,7 @@ Note that the style variables are always made local to the buffer."
(goto-char (match-beginning 1))
(setq m-beg (point))
(c-end-of-macro)
(save-excursion (c-depropertize-raw-strings-in-region m-beg (point)))
(c-clear-char-property-with-value m-beg (point) 'syntax-table '(1)))
(while (and (< (point) end)
......@@ -920,14 +920,16 @@ Note that the style variables are always made local to the buffer."
(goto-char (match-beginning 1))
(setq m-beg (point))
(c-end-of-macro))
(if (and ss-found (> (point) end))
(c-clear-char-property-with-value m-beg (point) 'syntax-table '(1)))
(when (and ss-found (> (point) end))
(save-excursion (c-depropertize-raw-strings-in-region m-beg (point)))
(c-clear-char-property-with-value m-beg (point) 'syntax-table '(1)))
(while (and (< (point) c-new-END)
(search-forward-regexp c-anchored-cpp-prefix c-new-END 'bound))
(goto-char (match-beginning 1))
(setq m-beg (point))
(c-end-of-macro)
(save-excursion (c-depropertize-raw-strings-in-region m-beg (point)))
(c-clear-char-property-with-value
m-beg (point) 'syntax-table '(1)))))
......@@ -1213,6 +1215,7 @@ Note that the style variables are always made local to the buffer."
"\"\\|\\s|" (point-max) t t)
(progn
(c-clear-char-property (1- (point)) 'syntax-table)
(c-truncate-semi-nonlit-pos-cache (1- (point)))
(not (eq (char-before) ?\")))))
(eq (char-before) ?\"))
(progn
......@@ -1247,27 +1250,38 @@ Note that the style variables are always made local to the buffer."
(forward-char)
(backward-sexp)
(c-clear-char-property eoll-1 'syntax-table)
(c-truncate-semi-nonlit-pos-cache eoll-1)
(c-clear-char-property (point) 'syntax-table))
;; Opening " at EOB.
(c-clear-char-property (1- (point)) 'syntax-table))
(if (c-search-backward-char-property 'syntax-table '(15) c-new-BEG)
;; Opening " on last line of text (without EOL).
(c-clear-char-property (point) 'syntax-table))))
(when (and (c-search-backward-char-property 'syntax-table '(15) c-new-BEG)
(eq (char-after) ?\")) ; Ignore an unterminated raw string's (.
;; Opening " on last line of text (without EOL).
(c-clear-char-property (point) 'syntax-table)
(c-truncate-semi-nonlit-pos-cache (point)))))
(t (goto-char end) ; point-max
(if (c-search-backward-char-property 'syntax-table '(15) c-new-BEG)
(c-clear-char-property (point) 'syntax-table))))
(when
(and
(c-search-backward-char-property 'syntax-table '(15) c-new-BEG)
(eq (char-after) ?\"))
(c-clear-char-property (point) 'syntax-table)
(c-truncate-semi-nonlit-pos-cache (point)))))
(unless (and c-multiline-string-start-char
(not (c-characterp c-multiline-string-start-char)))
(when (eq end-literal-type 'string)
(c-clear-char-property (1- (cdr end-limits)) 'syntax-table))
(when (and (eq end-literal-type 'string)
(not (eq (char-before (cdr end-limits)) ?\()))
(c-clear-char-property (1- (cdr end-limits)) 'syntax-table)
(c-truncate-semi-nonlit-pos-cache (1- (cdr end-limits))))
(when (eq beg-literal-type 'string)
(when (and (eq beg-literal-type 'string)
(eq (char-after (car beg-limits)) ?\"))
(setq c-new-BEG (min c-new-BEG (car beg-limits)))
(c-clear-char-property (car beg-limits) 'syntax-table)))))
(c-clear-char-property (car beg-limits) 'syntax-table)
(c-truncate-semi-nonlit-pos-cache (car beg-limits))))))
(defun c-after-change-re-mark-unbalanced-strings (beg end _old-len)
(defun c-after-change-mark-abnormal-strings (beg end _old-len)
;; Mark any unbalanced strings in the region (c-new-BEG c-new-END) with
;; string fence syntax-table text properties.
;;
......@@ -1318,7 +1332,8 @@ Note that the style variables are always made local to the buffer."
(min (1+ (point)) (point-max)))))
((and (null beg-literal-type)
(goto-char beg)
(eq (char-before) c-multiline-string-start-char)
(and (not (bobp))
(eq (char-before) c-multiline-string-start-char))
(memq (char-after) c-string-delims))
(cons (point)
(progn
......@@ -1343,22 +1358,24 @@ Note that the style variables are always made local to the buffer."
(while (progn
(setq s (parse-partial-sexp (point) c-new-END nil
nil s 'syntax-table))
(and (< (point) c-new-END)
(or (not (nth 3 s))
(not (memq (char-before) c-string-delims))))))
(and (< (point) c-new-END)
(or (not (nth 3 s))
(not (memq (char-before) c-string-delims))))))
;; We're at the start of a string.
(memq (char-before) c-string-delims)))
(if (c-unescaped-nls-in-string-p (1- (point)))
(looking-at "\\(\\\\\\(.\\|\n\\|\r\\)\\|[^\"]\\)*")
(looking-at (cdr (assq (char-before) c-string-innards-re-alist))))
(cond
((memq (char-after (match-end 0)) '(?\n ?\r))
(c-put-char-property (1- (point)) 'syntax-table '(15))
(c-put-char-property (match-end 0) 'syntax-table '(15)))
((or (eq (match-end 0) (point-max))
(eq (char-after (match-end 0)) ?\\)) ; \ at EOB
(c-put-char-property (1- (point)) 'syntax-table '(15))))
(goto-char (min (1+ (match-end 0)) (point-max)))
(unless (and (c-major-mode-is 'c++-mode)
(c-maybe-re-mark-raw-string))
(if (c-unescaped-nls-in-string-p (1- (point)))
(looking-at "\\(\\\\\\(.\\|\n|\\\r\\)\\|[^\"]\\)*")
(looking-at (cdr (assq (char-before) c-string-innards-re-alist))))
(cond
((memq (char-after (match-end 0)) '(?\n ?\r))
(c-put-char-property (1- (point)) 'syntax-table '(15))
(c-put-char-property (match-end 0) 'syntax-table '(15)))
((or (eq (match-end 0) (point-max))
(eq (char-after (match-end 0)) ?\\)) ; \ at EOB
(c-put-char-property (1- (point)) 'syntax-table '(15))))
(goto-char (min (1+ (match-end 0)) (point-max))))
(setq s nil)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
......@@ -1721,7 +1738,6 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; (c-new-BEG c-new-END) will be the region to fontify. It may become
;; larger than (beg end).
(setq c-new-END (- (+ c-new-END (- end beg)) old-len))
(setq c-old-BEG c-new-BEG c-old-END c-new-END)
(unless (c-called-from-text-property-change-p)
(setq c-just-done-before-change nil)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment