]> git.eshelyaron.com Git - emacs.git/commitdiff
CC Mode: Fix various minor indentation bugs
authorAlan Mackenzie <acm@muc.de>
Tue, 31 Dec 2024 18:39:57 +0000 (18:39 +0000)
committerEshel Yaron <me@eshelyaron.com>
Sat, 4 Jan 2025 20:26:20 +0000 (21:26 +0100)
As part of this, introduce a second anchor point to the
syntactic symbols brace-list-intro and enum-intro, the position
of the opening brace.

* lisp/progmodes/cc-align.el
(c-lineup-item-after-paren-at-boi): New function.

* /lisp/progmodes/cc-engine.el
(c-foreign-truncate-lit-pos-cache)
(c-foreign-init-lit-pos-cache): Use
c-truncate-lit-pos/state-cache in place of an older function.
(c-no-bracelist-cache): Update its definition to exclude
conses.
(c-strip-conses): New function.
(c-inside-bracelist-p): Use c-strip-conses.
(c-add-stmt-syntax): In the "go out a block" loop, go out of a
brace at BOI when there's non-whitespace text after it.
Refactor an `if' form containing a cond form into a cond form.
Add the new second second anchor point into syntactic contexts
with brace-list-intro and enum-intro.  Anchor brace-list-close
and enum-close elements on the individual declarations in
struct, etc., variable declarations.
(c-guess-basic-syntax, CASE 20): Use the new constraint-cont
syntactic symbol.
(c-guess-basic-syntax, CASE 9B): Anchor brace-list-close and
enum-close elements on the individual declarations in struct,
etc., variable declarations.
(c-guess-basic-syntax, CASEs 9C, 9D): Add the new second anchor
point into brace-list-intro and enum-intro syntactic contexts.

* lisp/progmodes/cc-mode.el (c-locate-first-punctuation-prop):
New function.
(c-depropertize-CPP): Use c-locate-first-punctuation-prop.

* lisp/progmodes/cc-vars.el (c-offsets-alist): Amend the
entries for constraint-cont, brace-list-intro, and enum-intro,
using c-lineup-item-after-paren-at-boi.

* doc/misc/cc-mode.texi (List Line-Up): Add a description of
c-lineup-item-after-paren-at-boi.

(cherry picked from commit 643e32340d1342cee8af3f1f604ea1c1ad12837a)

doc/misc/cc-mode.texi
lisp/progmodes/cc-align.el
lisp/progmodes/cc-engine.el
lisp/progmodes/cc-mode.el
lisp/progmodes/cc-vars.el

index e1dc777ebc13732827baf777264870bd48684c88..5661cd55068e00f6d343336eec2b09eedf67b53a 100644 (file)
@@ -6192,6 +6192,33 @@ to perform indentation.
 
 @comment ------------------------------------------------------------
 
+@defun c-lineup-item-after-paren-at-boi
+@findex lineup-item-after-paren-at-boi (c-)
+Line up under the first entry on the same line as an open parenthesis
+when that parenthesis is the lefmost non-space character in its line.
+For example:
+
+@example
+@group
+template <typename T>
+requires
+    ( requires (T t) @{ ++t; @}
+      && Baz<T>)      @hereFn{constraint-cont}
+int foo();
+@end group
+@end example
+
+
+This function is intended for use in a list.  If the construct being
+analyzed doesn't conform to the above description, the function
+returns nil.  Otherwise it returns a vector containing the indentation.
+
+@workswith{} @code{brace-list-intro}, @code{enum-intro},
+@code{constraint-cont}.
+@end defun
+
+@comment ------------------------------------------------------------
+
 @defun c-lineup-class-decl-init-+
 @findex lineup-class-decl-init-+ (c-)
 Line up the second entry of a class (etc.) initializer
index f2edf6f5f06c5c70eed471cc07d02649fc396949..c467184d938faf1116e50fa3a4600b459abcab71 100644 (file)
@@ -314,6 +314,30 @@ statement-block-intro, statement-case-intro, arglist-intro."
     (if (eolp) (skip-chars-backward " \t"))
     (vector (current-column))))
 
+(defun c-lineup-item-after-paren-at-boi (_langelem)
+  "Line up a *-cont line to just after the surrounding open paren at boi.
+\"paren\" here can also mean \"brace\", etc.  We line up under the first
+non-whitespace text after the paren.  If there is no such paren, or no
+such text, return nil, allowing another function to handle the
+construct.
+
+Works with: brace-list-intro, enum-intro, constraint-cont."
+  (save-excursion
+    (beginning-of-line)
+    (and
+     (if (c-langelem-2nd-pos c-syntactic-element)
+        ;; brace-list-intro, enum-intro.
+        (progn (goto-char (c-langelem-2nd-pos c-syntactic-element))
+               t)
+       ;; constraint-cont.
+       (c-go-up-list-backward nil (c-langelem-pos c-syntactic-element)))
+     (eq (point) (c-point 'boi))
+     (looking-at "\\s(")
+     (progn (forward-char)
+           (c-forward-syntactic-ws (c-point 'eol))
+           (unless (eolp)
+             (vector (current-column)))))))
+
 (defun c-lineup-arglist-close-under-paren (langelem)
   "Line up a line under the enclosing open paren.
 Normally used to line up a closing paren in the same column as its
index 17b18f6e7e415934cbd91e0dd0cb1b8ce0da7768..86f77a667350963069fec98dffc4a060d883a1a1 100644 (file)
@@ -3233,7 +3233,7 @@ This function should be added to the `before-change-functions'
 hook by major modes that use CC Mode's filling functionality
 without initializing CC Mode.  Currently (2020-06) these are
 `js-mode' and `mhtml-mode'."
-  (c-truncate-lit-pos-cache beg))
+  (c-truncate-lit-pos/state-cache beg))
 
 (defun c-foreign-init-lit-pos-cache ()
   "Initialize CC Mode's literal cache.
@@ -3242,7 +3242,7 @@ This function should be called from the mode functions of major
 modes which use CC Mode's filling functionality without
 initializing CC Mode.  Currently (2020-06) these are `js-mode' and
 `mhtml-mode'."
-  (c-truncate-lit-pos-cache 1))
+  (c-truncate-lit-pos/state-cache 1))
 
 \f
 ;; A system for finding noteworthy parens before the point.
@@ -13354,12 +13354,21 @@ comment at the start of cc-engine.el for more info."
           (t t))))                     ;; The caller can go up one level.
        ))))
 
-;; A list of the form returned by `c-parse-state'.  Each opening brace in it
-;; is not the brace of a brace list.  Any cons items in it are ignored, and
-;; are also unreliable.
+;; A list of the form returned by `c-parse-state', but without conses.  Each
+;; opening brace in it is not the brace of a brace list.
 (defvar c-no-bracelist-cache nil)
 (make-variable-buffer-local 'c-no-bracelist-cache)
 
+(defun c-strip-conses (liszt)
+  ;; Make a copy of the list LISZT, removing conses from the copy.  Return the
+  ;; result.
+  (let ((ptr liszt) new)
+    (while ptr
+      (if (atom (car ptr))
+         (push (car ptr) new))
+      (setq ptr (cdr ptr)))
+    (nreverse new)))
+
 (defun c-inside-bracelist-p (containing-sexp paren-state accept-in-paren)
   ;; Return the buffer position of the beginning of the brace list statement
   ;; if CONTAINING-SEXP is inside a brace list, otherwise return nil.
@@ -13422,13 +13431,13 @@ comment at the start of cc-engine.el for more info."
                    (not (memq next-containing c-no-bracelist-cache)))
          (setq next-containing (c-pull-open-brace paren-state)))
        (setq c-no-bracelist-cache
-             (nconc whole-paren-state
+             (nconc (c-strip-conses whole-paren-state)
                     (and next-containing (list next-containing))
                     paren-state))
        nil)
        ((not (memq containing-sexp c-no-bracelist-cache))
        ;; Update `c-no-bracelist-cache'
-       (setq c-no-bracelist-cache (copy-tree whole-paren-state))
+       (setq c-no-bracelist-cache (c-strip-conses whole-paren-state))
        nil)))))
 
 (defun c-looking-at-special-brace-list ()
@@ -14056,6 +14065,7 @@ comment at the start of cc-engine.el for more info."
     (let ((syntax-last c-syntactic-context)
          (boi (c-point 'boi))
          (anchor-boi (c-point 'boi))
+         (anchor-point-2 containing-sexp)
          ;; Set when we're on a label, so that we don't stop there.
          ;; FIXME: To be complete we should check if we're on a label
          ;; now at the start.
@@ -14067,17 +14077,24 @@ comment at the start of cc-engine.el for more info."
                 (point) nil)
             syntax-extra-args)
 
-      ;; Loop while we have to back out of containing blocks.
+      ;; Each time round the following loop, back out of the containing block.
+      ;; Do this unless `fixed-anchor' is non-nil and `containing-sexp' is at
+      ;; or before the BOI of the anchor position.  Carry on until the inner
+      ;; `while' loop fails to back up to `containing-sexp', or we reach the
+      ;; top level, or `containing-sexp' is before the initial anchor point.
       (while
          (and
           (catch 'back-up-block
 
-            ;; Loop while we have to back up statements.
+            ;; Each time round the following loop, back up a single
+            ;; statement until we reach a BOS at BOI, or `containing-sexp',
+            ;; or any previous statement when `stop-at-boi-only' is nil.
+            ;; More or less.  Read the source for full details.  ;-(
             (while (or (/= (point) boi)
                        on-label
                        (looking-at c-comment-start-regexp))
 
-              ;; Skip past any comments that stands between the
+              ;; Skip past any comments that stand between the
               ;; statement start and boi.
               (let ((savepos (point)))
                 (while (and (/= savepos boi)
@@ -14135,7 +14152,11 @@ comment at the start of cc-engine.el for more info."
 
           containing-sexp
           (or (null fixed-anchor)
-              (> containing-sexp anchor-boi)))
+              (> containing-sexp anchor-boi)
+              (save-excursion
+                (goto-char (1+ containing-sexp))
+                (c-forward-syntactic-ws (c-point 'eol))
+                (< (point) (c-point 'eol)))))
 
        ;; Now we have to go out of this block.
        (goto-char containing-sexp)
@@ -14157,7 +14178,7 @@ comment at the start of cc-engine.el for more info."
        ;; from and add the right syntactic element for it.
        (let ((paren-pos (point))
              (paren-char (char-after))
-             step-type)
+             step-type anchor-point)
 
          (if (eq paren-char ?\()
              ;; Stepped out of a parenthesis block, so we're in an
@@ -14188,45 +14209,62 @@ comment at the start of cc-engine.el for more info."
                      on-label nil))
 
            ;; Stepped out of a brace block.
+           (save-excursion
+             (if (and (zerop (c-backward-token-2))
+                      (looking-at "=\\([^=]\\|$\\)")
+                      (zerop (c-backward-token-2))
+                      (looking-at c-symbol-key)
+                      (not (looking-at c-keywords-regexp)))
+                 (setq anchor-point (point))))
+           (if anchor-point
+               (progn (goto-char anchor-point)
+                      (setq step-type 'same
+                            on-label nil))
+
            (setq step-type (c-beginning-of-statement-1 containing-sexp)
-                 on-label (eq step-type 'label))
+                 on-label (eq step-type 'label)))
 
-           (if (and (eq step-type 'same)
-                    (/= paren-pos (point)))
-               (let (inexpr bspec)
-                 (cond
-                  ((save-excursion
-                     (goto-char paren-pos)
-                     (setq inexpr (c-looking-at-inexpr-block
-                                   (c-safe-position containing-sexp paren-state)
-                                   containing-sexp)))
-                   (c-add-syntax (if (eq (car inexpr) 'inlambda)
-                                     'defun-block-intro
-                                   'statement-block-intro)
-                                 nil))
-                  ((looking-at c-other-decl-block-key)
-                   (c-add-syntax
-                    (cdr (assoc (match-string 1)
-                                c-other-decl-block-key-in-symbols-alist))
-                    (max (c-point 'boi paren-pos) (point))))
-                  ((c-at-enum-brace paren-pos)
-                   (c-add-syntax 'enum-intro nil))
-                  ((c-inside-bracelist-p paren-pos paren-state nil)
-                   (if (save-excursion
-                         (goto-char paren-pos)
-                         (c-looking-at-statement-block))
-                       (c-add-syntax 'defun-block-intro nil)
-                     (c-add-syntax 'brace-list-intro nil)))
-                  ((save-excursion
+           (let (inexpr bspec)
+             (cond
+              ((or (not (eq step-type 'same))
+                   (eq paren-pos (point)))
+               (if (and (eq paren-pos (point))
+                        (c-inside-bracelist-p paren-pos paren-state nil))
+                   (c-add-syntax 'brace-list-intro nil anchor-point-2)
+                 (c-add-syntax 'statement-block-intro nil)))
+              ((save-excursion
+                 (goto-char paren-pos)
+                 (setq inexpr (c-looking-at-inexpr-block
+                               (c-safe-position containing-sexp paren-state)
+                               containing-sexp)))
+               (c-add-syntax (if (eq (car inexpr) 'inlambda)
+                                 'defun-block-intro
+                               'statement-block-intro)
+                             nil))
+              ((looking-at c-other-decl-block-key)
+               (c-add-syntax
+                (cdr (assoc (match-string 1)
+                            c-other-decl-block-key-in-symbols-alist))
+                (max (c-point 'boi paren-pos) (point))))
+              ((c-at-enum-brace paren-pos)
+               (c-add-syntax 'enum-intro nil anchor-point-2))
+              ((c-inside-bracelist-p paren-pos paren-state nil)
+               (if (save-excursion
                      (goto-char paren-pos)
-                     (setq bspec (c-looking-at-or-maybe-in-bracelist
-                                  containing-sexp containing-sexp))
-                     (and (consp bspec)
-                          (eq (cdr bspec) 'in-paren)))
-                   (c-add-syntax 'brace-list-intro (car bspec)))
-                  (t (c-add-syntax 'defun-block-intro nil))))
+                     (c-looking-at-statement-block))
+                   (c-add-syntax 'defun-block-intro nil)
+                 (c-add-syntax 'brace-list-intro nil anchor-point-2)))
+              ((save-excursion
+                 (goto-char paren-pos)
+                 (setq bspec (c-looking-at-or-maybe-in-bracelist
+                              containing-sexp containing-sexp))
+                 (and (consp bspec)
+                      (eq (cdr bspec) 'in-paren)))
+               (c-add-syntax 'brace-list-intro (car bspec)
+                             anchor-point-2))
+              (t (c-add-syntax 'defun-block-intro nil))))
 
-             (c-add-syntax 'statement-block-intro nil)))
+           (setq anchor-point-2 containing-sexp))
 
          (if (= paren-pos boi)
              ;; Always done if the open brace was at boi.  The
@@ -15478,9 +15516,13 @@ comment at the start of cc-engine.el for more info."
             (not (eq (cdr tmp) 'expression))
             (setq placeholder (car tmp)))
        (c-add-syntax
-        (if (eq char-after-ip ?{)
-            'substatement-open
-          'substatement)
+        (cond
+         ((and (eq (char-after containing-sexp) ?\()
+               (> containing-sexp placeholder))
+          'constraint-cont)
+         ((eq char-after-ip ?{)
+          'substatement-open)
+         (t 'substatement))
         (c-point 'boi placeholder)))
 
        ;; ((Old) CASE 6 has been removed.)
@@ -15750,7 +15792,17 @@ comment at the start of cc-engine.el for more info."
                              (c-determine-limit 1000))
                             (point)))
                          (c-most-enclosing-brace state-cache (point))))
-           (c-beginning-of-statement-1 lim nil nil t)
+           (save-excursion
+             (setq placeholder
+                   (and (zerop (c-backward-token-2))
+                        (looking-at "=\\([^=]\\|$\\)")
+                        (zerop (c-backward-token-2))
+                        (looking-at c-symbol-key)
+                        (not (looking-at c-keywords-regexp))
+                        (point))))
+           (if placeholder
+               (goto-char placeholder)
+             (c-beginning-of-statement-1 lim nil nil t))
            (c-add-stmt-syntax (if enum-pos 'enum-close 'brace-list-close)
                               nil t lim paren-state)))
 
@@ -15779,7 +15831,7 @@ comment at the start of cc-engine.el for more info."
              (goto-char containing-sexp))
            (if (eq (point) (c-point 'boi))
                (c-add-syntax (if enum-pos 'enum-intro 'brace-list-intro)
-                             (point))
+                             (point) containing-sexp)
              (setq lim (or (save-excursion
                              (and
                               (c-back-over-member-initializers
@@ -15788,20 +15840,25 @@ comment at the start of cc-engine.el for more info."
                            (c-most-enclosing-brace state-cache (point))))
              (c-beginning-of-statement-1 lim nil nil t)
              (c-add-stmt-syntax (if enum-pos 'enum-intro 'brace-list-intro)
-                                nil t lim paren-state)))
+                                (list containing-sexp)
+                                t lim paren-state)))
 
           ;; CASE 9D: this is just a later brace-list-entry/enum-entry or
           ;; brace-entry-open
-          (t (if (or (eq char-after-ip ?{)
-                     (and c-special-brace-lists
-                          (save-excursion
-                            (goto-char indent-point)
-                            (c-forward-syntactic-ws (c-point 'eol))
-                            (c-looking-at-special-brace-list))))
-                 (c-add-syntax 'brace-entry-open (point))
+          (t (cond
+              ((or (eq char-after-ip ?{)
+                   (and c-special-brace-lists
+                        (save-excursion
+                          (goto-char indent-point)
+                          (c-forward-syntactic-ws (c-point 'eol))
+                          (c-looking-at-special-brace-list))))
+               (c-add-syntax 'brace-entry-open (point)))
+              ((eq (c-point 'eol) (1- indent-point))
                (c-add-stmt-syntax (if enum-pos 'enum-entry 'brace-list-entry)
                                   nil t containing-sexp
-                                  paren-state (point))))))))
+                                  paren-state (point)))
+              (t (c-add-syntax (if enum-pos 'enum-entry 'brace-list-entry)
+                               (point)))))))))
 
        ;; CASE 10: A continued statement or top level construct.
        ((and (not (memq char-before-ip '(?\; ?:)))
index 4daca559212f4c68440e67be6900650fcf8f406a..3f9d6c8c28f3f5826b2eda5c23036eaab21c6857 100644 (file)
@@ -995,6 +995,15 @@ Note that the style variables are always made local to the buffer."
        '(put-text-property remove-text-properties
                            remove-list-of-text-properties)))
 
+(defun c-locate-first-punctuation-prop (beg)
+  ;; Scan the region (BEG (point)) for `syntax-table' punctuation text properties,
+  ;; returning the position of the first found, or nil.  Point is unchanged.
+  (let ((end (point)))
+    (goto-char beg)
+    (prog1 (if (c-search-forward-char-property 'syntax-table '(1) end)
+              (match-beginning 0))
+      (goto-char end))))
+
 (defun c-depropertize-CPP (beg end)
   ;; Remove the punctuation syntax-table text property from the CPP parts of
   ;; (c-new-BEG c-new-END), and remove all syntax-table properties from any
@@ -1019,7 +1028,10 @@ Note that the style variables are always made local to the buffer."
                      (search-forward-regexp c-anchored-cpp-prefix end 'bound)))
       (goto-char (match-beginning 1))
       (setq m-beg (point))
-      (c-end-of-macro))
+      (c-end-of-macro)
+      (c-truncate-lit-pos/state-cache
+       (or (c-locate-first-punctuation-prop m-beg) (point-max))))
+
     (when (and ss-found (> (point) end))
       (when c-ml-string-opener-re
        (save-excursion (c-depropertize-ml-strings-in-region m-beg (point))))
@@ -1031,6 +1043,8 @@ 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)
+      (c-truncate-lit-pos/state-cache
+       (or (c-locate-first-punctuation-prop m-beg) (point-max)))
       (when c-ml-string-opener-re
        (save-excursion (c-depropertize-ml-strings-in-region m-beg (point))))
       (c-clear-syntax-table-with-value-trim-caches m-beg (point) '(1)))))
index dac60c9408536efd44db3cb68cdefe5507033e55..f1393c999f3f7212daa43093fb330e0eb04d7547 100644 (file)
@@ -1291,7 +1291,7 @@ can always override the use of `c-default-style' by making calls to
        ;; Anchor pos: Bol at the last line of previous construct.
        (topmost-intro-cont    . c-lineup-topmost-intro-cont)
        ;;Anchor pos: Bol at the topmost annotation line
-       (constraint-cont  . +)
+       (constraint-cont       . (c-lineup-item-after-paren-at-boi +))
        ;; Anchor pos: Boi of the starting requires/concept line
        (annotation-top-cont   .   0)
        ;;Anchor pos: Bol at the topmost annotation line
@@ -1322,8 +1322,9 @@ can always override the use of `c-default-style' by making calls to
        ;; "typedef" token is ignored.
        (brace-list-close      . 0)
        ;; Anchor pos: At the brace list decl start(*).
-       (brace-list-intro      . +)
+       (brace-list-intro      . (c-lineup-item-after-paren-at-boi +))
        ;; Anchor pos: At the brace list decl start(*).
+       ;; 2nd pos: At the open brace.
        (brace-list-entry      . 0)
        ;; Anchor pos: At the first non-ws char after the open paren if
        ;; the first token is on the same line, otherwise boi at that
@@ -1335,9 +1336,10 @@ can always override the use of `c-default-style' by making calls to
        ;; enum construct.
        (enum-close            . 0)
        ;; Anchor pos: At the enum block open.
-       (enum-intro            . +)
+       (enum-intro            . (c-lineup-item-after-paren-at-boi +))
        ;; Anchor pos: The opening brace position when at boi, or boi
        ;; at the enum decl start(*).
+       ;; 2nd pos: At the open brace.
        (enum-entry            . 0)
        ;; Anchor pos: Normally, boi of the line containing the
        ;; previous token, but if that line also contains the opening