1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-02-06 15:41:27 -08:00

Correctly fontify C++'s operator"" _tag (...)

Give both the "" and _tag font-lock-function-name-face.  Also correct the
fontification of an inherited class name when there is an attribute between
the class name being declared and the colon introducing the inheritance.

* lisp/progmodes/cc-engine.el (c-forward-over-colon-type-list): New function.
(c-forward-keyword-clause): Use the above new function instead of a
looking-at.
(c-forward-name, c-forward-declarator): Accept both the "" and the tag as part
of the name.

* lisp/progmodes/cc-fonts.el (c-font-lock-declarators): Fontify the "" (which
already has font-lock-string-face) and the tag with
font-lock-function-name-face.

* lisp/progmodes/cc-langs.el (c-overloadable-operators): Add "" to this list.
(c-sub-colon-type-list-re): New lang-const and lang-var.
This commit is contained in:
Alan Mackenzie 2022-10-14 17:40:26 +00:00
parent 51fc195d39
commit 3da935d533
3 changed files with 68 additions and 9 deletions

View file

@ -8356,6 +8356,23 @@ multi-line strings (but not C++, for example)."
(goto-char here))))
t)
(defun c-forward-over-colon-type-list ()
;; If we're at a sequence of characters which can extend from, e.g.,
;; a class name up to a colon introducing an inheritance list,
;; move forward over them, including the colon, and return non-nil.
;; Otherwise return nil, leaving point unmoved.
(let ((here (point)) pos)
(while (and (re-search-forward c-sub-colon-type-list-re nil t)
(not (eq (char-after) ?:))
(c-major-mode-is 'c++-mode)
(setq pos (c-looking-at-c++-attribute)))
(goto-char pos))
(if (eq (char-after) ?:)
(progn (forward-char)
t)
(goto-char here)
nil)))
(defun c-forward-keyword-clause (match)
;; Submatch MATCH in the current match data is assumed to surround a
;; token. If it's a keyword, move over it and any immediately
@ -8463,12 +8480,11 @@ multi-line strings (but not C++, for example)."
(and c-record-type-identifiers
(progn
;; If a keyword matched both one of the types above and
;; this one, we match `c-colon-type-list-re' after the
;; this one, we move forward to the colon following the
;; clause matched above.
(goto-char safe-pos)
(looking-at c-colon-type-list-re))
(c-forward-over-colon-type-list))
(progn
(goto-char (match-end 0))
(c-forward-syntactic-ws)
(c-forward-keyword-prefixed-id type))
;; There's a type after the `c-colon-type-list-re' match
@ -8921,8 +8937,16 @@ multi-line strings (but not C++, for example)."
;; Got some other operator.
(setq c-last-identifier-range
(cons (point) (match-end 0)))
(if (and (eq (char-after) ?\")
(eq (char-after (1+ (point))) ?\"))
;; operator"" has an (?)optional tag after it.
(progn
(goto-char (match-end 0))
(c-forward-syntactic-ws lim+)
(when (c-on-identifier)
(c-forward-token-2 1 nil lim+)))
(goto-char (match-end 0))
(c-forward-syntactic-ws lim+)
(c-forward-syntactic-ws lim+))
(setq pos (point)
res 'operator)))
@ -9676,7 +9700,7 @@ point unchanged and return nil."
;; (e.g. "," or ";" or "}").
(let ((here (point))
id-start id-end brackets-after-id paren-depth decorated
got-init arglist)
got-init arglist double-double-quote)
(or limit (setq limit (point-max)))
(if (and
(< (point) limit)
@ -9705,6 +9729,10 @@ point unchanged and return nil."
(setq id-start (point))
(if (looking-at c-overloadable-operators-regexp)
(progn
(when (and (c-major-mode-is 'c++-mode)
(eq (char-after) ?\")
(eq (char-after (1+ (point))) ?\"))
(setq double-double-quote t))
(goto-char (match-end 0))
(c-forward-syntactic-ws limit)
(setq got-identifier t)
@ -9756,6 +9784,13 @@ point unchanged and return nil."
t)
(t nil)))
(progn
(c-forward-syntactic-ws limit)
(when (and double-double-quote ; C++'s operator"" _tag
(c-on-identifier))
(c-forward-token-2 1 nil limit))
t)
;; Skip out of the parens surrounding the identifier. If closing
;; parens are missing, this form returns nil.
(or (= paren-depth 0)

View file

@ -1141,12 +1141,28 @@ casts and declarations are fontified. Used on level 2 and higher."
(while (and (< (point) id-end)
(re-search-forward c-opt-identifier-prefix-key id-end t))
(c-forward-syntactic-ws limit))))
(when (not (get-text-property (point) 'face))
;; Only apply the face when the text doesn't have one yet.
;; Exception: The "" in C++'s operator"" will already wrongly have
;; string face.
(when (memq (get-text-property (point) 'face)
'(nil font-lock-string-face))
(c-put-font-lock-face (point) id-end
(cond
((not (memq types '(nil t))) types)
(is-function 'font-lock-function-name-face)
(t 'font-lock-variable-name-face))))))
(t 'font-lock-variable-name-face))))
;; Fontify any _tag in C++'s operator"" _tag.
(when (and
(c-major-mode-is 'c++-mode)
(equal (buffer-substring-no-properties id-start id-end)
"\"\""))
(goto-char id-end)
(c-forward-syntactic-ws limit)
(when (c-on-identifier)
(c-put-font-lock-face
(point)
(progn (c-forward-over-token) (point))
font-lock-function-name-face)))))
(and template-class
(eq init-char ?=) ; C++ "<class X = Y>"?
(progn

View file

@ -1449,8 +1449,7 @@ form\". See also `c-op-identifier-prefix'."
"??'=" "xor_eq" "&=" "and_eq" "|=" "??!=" "or_eq"
"<<" ">>" ">>=" "<<=" "==" "!=" "not_eq" "<=>" "<=" ">="
"&&" "and" "||" "??!??!" "or" "++" "--" "," "->*" "->"
"()" "[]" "<::>" "??(??)")
;; These work like identifiers in Pike.
"()" "[]" "\"\"" "<::>" "??(??)")
pike '("`+" "`-" "`&" "`|" "`^" "`<<" "`>>" "`*" "`/" "`%" "`~"
"`==" "`<" "`>" "`!" "`[]" "`[]=" "`->" "`->=" "`()" "``+"
"``-" "``&" "``|" "``^" "``<<" "``>>" "``*" "``/" "``%"
@ -2936,6 +2935,15 @@ regexp if `c-colon-type-list-kwds' isn't nil."
"[^][{}();,/#=:]*:")))
(c-lang-defvar c-colon-type-list-re (c-lang-const c-colon-type-list-re))
(c-lang-defconst c-sub-colon-type-list-re
"Regexp matching buffer content that may come between a keyword in
`c-colon-type-list-kwds' and a putative colon, or nil if there are no
such keywords. Exception: it does not match any C++ attributes."
t (if (c-lang-const c-colon-type-list-re)
(substring (c-lang-const c-colon-type-list-re) 0 -1)))
(c-lang-defvar c-sub-colon-type-list-re
(c-lang-const c-sub-colon-type-list-re))
(c-lang-defconst c-paren-nontype-kwds
"Keywords that may be followed by a parenthesis expression that doesn't
contain type identifiers."