emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 3da935d533: Correctly fontify C++'s operator"" _tag (...)


From: Alan Mackenzie
Subject: master 3da935d533: Correctly fontify C++'s operator"" _tag (...)
Date: Fri, 14 Oct 2022 13:43:14 -0400 (EDT)

branch: master
commit 3da935d5339dfb43cb1be2df5f83b74b4e34ccc1
Author: Alan Mackenzie <acm@muc.de>
Commit: Alan Mackenzie <acm@muc.de>

    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.
---
 lisp/progmodes/cc-engine.el | 45 ++++++++++++++++++++++++++++++++++++++++-----
 lisp/progmodes/cc-fonts.el  | 20 ++++++++++++++++++--
 lisp/progmodes/cc-langs.el  | 12 ++++++++++--
 3 files changed, 68 insertions(+), 9 deletions(-)

diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 0ac96219a1..223b1e917f 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 2e71285cb3..b4ff32b907 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++ "<class X = Y>"?
            (progn
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index cd23483a58..650c8720ee 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."



reply via email to

[Prev in Thread] Current Thread [Next in Thread]