From: Alan Mackenzie Date: Fri, 14 Oct 2022 17:40:26 +0000 (+0000) Subject: Correctly fontify C++'s operator"" _tag (...) X-Git-Tag: emacs-29.0.90~1616^2~621 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=3da935d5339dfb43cb1be2df5f83b74b4e34ccc1;p=emacs.git 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. --- diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 0ac96219a19..223b1e917fe 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -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) diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index 2e71285cb36..b4ff32b9070 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -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++ ""? (progn diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index cd23483a58f..650c8720ee4 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -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."