From: Alan Mackenzie Date: Tue, 31 Dec 2024 18:39:57 +0000 (+0000) Subject: CC Mode: Fix various minor indentation bugs X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=cbf474448090d874411f23aa9d75529bf85a1ced;p=emacs.git CC Mode: Fix various minor indentation bugs 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) --- diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi index e1dc777ebc1..5661cd55068 100644 --- a/doc/misc/cc-mode.texi +++ b/doc/misc/cc-mode.texi @@ -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 +requires + ( requires (T t) @{ ++t; @} + && Baz) @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 diff --git a/lisp/progmodes/cc-align.el b/lisp/progmodes/cc-align.el index f2edf6f5f06..c467184d938 100644 --- a/lisp/progmodes/cc-align.el +++ b/lisp/progmodes/cc-align.el @@ -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 diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 17b18f6e7e4..86f77a66735 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -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)) ;; 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 '(?\; ?:))) diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 4daca559212..3f9d6c8c28f 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -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))))) diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el index dac60c94085..f1393c999f3 100644 --- a/lisp/progmodes/cc-vars.el +++ b/lisp/progmodes/cc-vars.el @@ -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