]> git.eshelyaron.com Git - emacs.git/commitdiff
CC Mode: correct handling of properties on #include <...>
authorAlan Mackenzie <acm@muc.de>
Fri, 25 Oct 2024 20:35:32 +0000 (20:35 +0000)
committerEshel Yaron <me@eshelyaron.com>
Sat, 26 Oct 2024 16:45:47 +0000 (18:45 +0200)
In C, Pike, and IDL Modes, deleting and reinserting such a <
could create havoc with the category/syntax-table properties on
the < and >.  Also the contents of <...> should only get paren
properties when the #include is present and correct.

* lisp/progmodes/cc-fonts.el (c-cpp-matchers): Replace the
c-make-font-lock-search-function which put properties on the
<...> with a simple matcher.

* lisp/progmodes/cc-langs.el
(c-get-state-before-change-functions)
(c-before-font-lock-functions): Add respectively
c-before-change-include-<> and c-after-change-include-<> in the
C, Pike and IDL entries of these variables.

* lisp/progmodes/cc-mode.el (c-before-change-include-<>)
(c-after-change-include-<>): New functions.

(cherry picked from commit 76268160ba9262a8479589427b8e783db0242260)

lisp/progmodes/cc-fonts.el
lisp/progmodes/cc-langs.el
lisp/progmodes/cc-mode.el

index 0f086f8e8122ea7ab2f14fd3d91f7d68b196226c..3a87339e38abc9bdf03466423b1da2025a9dc747 100644 (file)
@@ -564,26 +564,18 @@ stuff.  Used on level 1 and higher."
                    ;; since `font-lock-fontify-anchored-keywords' terminated
                    ;; its loop at EOL without executing our lambda form at
                    ;; all.
-                   `((,(c-make-font-lock-search-function
-                        (concat noncontinued-line-end
-                                (c-lang-const c-opt-cpp-prefix)
-                                re
-                                (c-lang-const c-syntactic-ws)
-                                "\\(<\\([^>\n\r]*\\)>?\\)")
-                        `(,(+ ncle-depth re-depth sws-depth
-                              (if (featurep 'xemacs) 2 1)
-                              )
-                          font-lock-string-face t)
-                        `((let ((beg (match-beginning
-                                      ,(+ ncle-depth re-depth sws-depth 1)))
-                                (end (1- (match-end ,(+ ncle-depth re-depth
-                                                        sws-depth 1)))))
-                            (if (eq (char-after end) ?>)
-                                (progn
-                                  (c-mark-<-as-paren beg)
-                                  (c-mark->-as-paren end))
-                              (c-unmark-<->-as-paren beg)))
-                          nil))))))
+                   `((,(concat noncontinued-line-end
+                               "\\("   ; To make the next ^ special.
+                               (c-lang-const c-cpp-include-key)
+                               "\\)"
+                               (c-lang-const c-syntactic-ws)
+                               "\\(<\\([^>\n\r]*\\)>?\\)")
+                      ,(+ ncle-depth 1
+                          (regexp-opt-depth
+                           (c-lang-const c-cpp-include-key))
+                          sws-depth
+                          (if (featurep 'xemacs) 2 1))
+                      font-lock-string-face t))))
 
              ;; #define.
              ,@(when (c-lang-const c-opt-cpp-macro-define)
index 010b0ed6b04293a26cc8a6ecf3e48b616de77151..a256371f85090103cf6fd5e503418dab8f93a27b 100644 (file)
@@ -451,7 +451,8 @@ so that all identifiers are recognized as words.")
 (c-lang-defconst c-get-state-before-change-functions
   ;; 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-before-change-check-unbalanced-strings
+  t '(c-before-change-include-<>
+      c-before-change-check-unbalanced-strings)
   c++ '(c-extend-region-for-CPP
        c-depropertize-CPP
        c-before-change-check-ml-strings
@@ -463,6 +464,7 @@ so that all identifiers are recognized as words.")
        c-parse-quotes-before-change
        c-before-change-fix-comment-escapes)
   c '(c-extend-region-for-CPP
+      c-before-change-include-<>
       c-depropertize-CPP
       c-truncate-bs-cache
       c-before-change-check-unbalanced-strings
@@ -480,7 +482,8 @@ so that all identifiers are recognized as words.")
         c-unmark-<>-around-region
         c-before-change-check-unbalanced-strings
         c-before-change-check-<>-operators)
-  pike '(c-before-change-check-ml-strings
+  pike '(c-before-change-include-<>
+        c-before-change-check-ml-strings
         c-before-change-check-unbalanced-strings)
   awk 'c-awk-record-region-clear-NL)
 (c-lang-defvar c-get-state-before-change-functions
@@ -511,6 +514,7 @@ parameters \(point-min) and \(point-max).")
   t '(c-depropertize-new-text
       c-after-change-escape-NL-in-string
       c-after-change-mark-abnormal-strings
+      c-after-change-include-<>
       c-change-expand-fl-region)
   c '(c-depropertize-new-text
       c-after-change-fix-comment-escapes
@@ -518,6 +522,7 @@ parameters \(point-min) and \(point-max).")
       c-parse-quotes-after-change
       c-after-change-mark-abnormal-strings
       c-extend-font-lock-region-for-macros
+      c-after-change-include-<>
       c-neutralize-syntax-in-CPP
       c-change-expand-fl-region)
   objc '(c-depropertize-new-text
@@ -553,6 +558,7 @@ parameters \(point-min) and \(point-max).")
         c-after-change-escape-NL-in-string
         c-after-change-unmark-ml-strings
         c-after-change-mark-abnormal-strings
+        c-after-change-include-<>
         c-change-expand-fl-region)
   awk '(c-depropertize-new-text
        c-awk-extend-and-syntax-tablify-region))
index 137217d7bef15ef7a04987527e639876eb047176..ebe8b8e45ba34c8f19c319ce795d630d2d170b2f 100644 (file)
@@ -1996,6 +1996,70 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
 (defvar c-new-id-is-type nil)
 (make-variable-buffer-local 'c-new-id-is-type)
 
+(defun c-before-change-include-<> (beg end)
+  "Remove category/syntax-table properties from each #include <..>.
+In particular, from the < and > characters which have been marked as parens
+using these properties.  This is done on every such #include <..> with a
+portion between BEG and END.
+
+This function is used solely as a member of
+`c-get-state-before-change-functions' where it should appear early, before
+`c-depropertize-CPP'.  It should be used only together with
+`c-after-change-include-<>'."
+  (c-save-buffer-state ((search-end (progn (goto-char end)
+                                          (c-end-of-macro)
+                                          (point)))
+                       hash-pos)
+    (goto-char beg)
+    (c-beginning-of-macro)
+    (while (and (< (point) search-end)
+               (search-forward-regexp c-cpp-include-key search-end 'bound)
+               (setq hash-pos (match-beginning 0)))
+      (save-restriction
+       (narrow-to-region (point-min) (c-point 'eoll))
+       (c-forward-comments))
+      (when (and (< (point) search-end)
+                (looking-at "\\s(")
+                (looking-at "\\(<\\)[^>\n\r]*\\(>\\)?")
+                (not (cdr (c-semi-pp-to-literal hash-pos))))
+       (c-unmark-<->-as-paren (match-beginning 1))
+       (when (< hash-pos c-new-BEG)
+         (setq c-new-BEG hash-pos))
+       (when (match-beginning 2)
+         (c-unmark-<->-as-paren (match-beginning 2))
+         (when (> (match-end 2) c-new-END)
+           (setq c-new-END (match-end 2))))))))
+
+(defun c-after-change-include-<> (beg end _old-len)
+  "Apply category/syntax-table properties to each #include <..>.
+In particular, to the < and > characters to mark them as matching parens
+using these properties.  This is done on every such #include <..> with a
+portion between BEG and END.
+
+This function is used solely as a member of
+`c-before-font-lock-functions' where is should appear late, but before
+`c-neutralize-syntax-in-CPP'.  It should be used only together with
+`c-before-change-include-<>'."
+  (c-save-buffer-state ((search-end (progn (goto-char end)
+                                          (c-end-of-macro)
+                                          (point)))
+                       hash-pos)
+    (goto-char beg)
+    (c-beginning-of-macro)
+    (while (and (< (point) search-end)
+               (search-forward-regexp c-cpp-include-key search-end 'bound)
+               (setq hash-pos (match-beginning 0)))
+      (save-restriction
+       (narrow-to-region (point-min) (c-point 'eoll))
+       (c-forward-comments))
+      (when (and (< (point) search-end)
+                (looking-at "\\(<\\)[^>\n\r]*\\(>\\)")
+                (not (cdr (c-semi-pp-to-literal (match-beginning 0)))))
+       (c-mark-<-as-paren (match-beginning 1))
+       (when (< hash-pos c-new-BEG) (setq c-new-BEG hash-pos))
+       (c-mark->-as-paren (match-beginning 2))
+       (when (> (match-end 2) c-new-END) (setq c-new-END (match-end 2)))))))
+
 (defun c-before-change-fix-comment-escapes (beg end)
   "Remove punctuation syntax-table text properties from C/C++ comment markers.
 This is to handle the rare case of two or more backslashes at an