1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-28 10:56:36 +00:00

Allow C++ nested brace-list-entries to be better indented.

This fixes bug #24431.  The key change of this bug fix is correctly analyzing
nested brace lists when the opening element stands on the same line as both
its introductory brace and an enclosing parameter list parenthesis.

* list/progmodes/cc-align.el (c-lineup-under-anchor): New line-up function.

* list/progmodes/cc-engine.el (c-looking-at-or-maybe-in-bracelist): Accept the
presence of exactly an identifier between an open parenthesis and an open
brace as evidence of the brace starting a brace list.
(c-looking-at-statement-block): New function, extracted from
c-looking-at-inexpr-block.  Enhance it to analyze inner blocks recursively
when needed.
(c-looking-at-inexpr-block): Extract new function (see above) and call it.
(c-add-stmt-syntax): Enhance, with new &optional parameter, to supply the
prime syntactic symbol with a fixed anchor point.  When this is used, restrict
all added syntactic symbols to those having an anchor point on the same line.
Add, in addition to the current additional symbols, c-brace-list-entry when
needed; use c-looking-at-statement-block to determine the latter.
(c-guess-basic-syntax, CASE 9D): Use c-add-stmt-syntax rather than just
c-add-syntax, to assemble the syntactic context of a 'brace-list-entry, thus
getting, possibly, several accompanying syntactic entries.

* lisp/progmodes/cc-styles.el (c-style-alist, "gnu" style): New entry for
'brace-list-intro, namely c-lineup-arglist-intro-after-paren.

* lisp/progmodes/cc-vars.el (c-offsets-alist): Change the factory default
offset for 'brace-list-entry from 0 to c-lineup-under-anchor.

* doc/misc/cc-mode.texi (Syntactic Symbols): Amend the definition of
brace-list-intro.
(Brace List Symbols): Amend the example to show the new analysis of brace
lists when the first element comes on the same line as the opening brace.
(Misc Line-Up): Document the new line-up function c-lineup-under-anchor.
This commit is contained in:
Alan Mackenzie 2017-02-01 20:20:09 +00:00
parent 5d61ef0de9
commit 94ad13b93c
5 changed files with 111 additions and 36 deletions

View File

@ -4141,7 +4141,8 @@ Open brace of an enum or static array list. @ref{Brace List Symbols}.
@item brace-list-close
Close brace of an enum or static array list. @ref{Brace List Symbols}.
@item brace-list-intro
First line in an enum or static array list. @ref{Brace List Symbols}.
First line after the opening @samp{@{} in an enum or static array
list. @ref{Brace List Symbols}.
@item brace-list-entry
Subsequent lines in an enum or static array list. @ref{Brace List
Symbols}.
@ -4635,11 +4636,18 @@ example:
Here, you've already seen the analysis of lines 1, 2, 3, and 11. On
line 4, things get interesting; this line is assigned
@code{brace-entry-open} syntactic symbol because it's a bracelist entry
line that starts with an open brace. Lines 5 and 6 (and line 9) are
pretty standard, and line 7 is a @code{brace-list-close} as you'd
expect. Once again, line 8 is assigned as @code{brace-entry-open} as is
line 10.
@code{brace-entry-open} syntactic symbol because it's a bracelist
entry line that starts with an open brace. Lines 5 and 6 are pretty
standard, and line 7 is a @code{brace-list-close} as you'd expect.
Once again, line 8 is assigned as @code{brace-entry-open} as is line
10. Line 9 is assigned two syntactic elements, @code{brace-list-intro}
with anchor point at the @samp{@{} of line 8@footnote{This extra
syntactic element was introduced in @ccmode{} 5.33.1 to allow extra
flexibility in indenting the second line of such a construct. You can
preserve the behaviour resulting from the former syntactic analysis by
giving @code{brace-list-entry} an offset of
@code{c-lineup-under-anchor} (@pxref{Misc Line-Up}).}, and
@code{brace-list-entry} anchored on the @samp{1} of line 8.
@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@node External Scope Symbols, Paren List Symbols, Brace List Symbols, Syntactic Symbols
@ -6288,6 +6296,17 @@ already has; think of it as an identity function for lineups.
@comment ------------------------------------------------------------
@defun c-lineup-under-anchor
Line up a line directly underneath its anchor point. This is like
@samp{0}, except any previously calculated offset contributions are
disregarded.
@workswith Any syntactic symbol which has an anchor point.
@end defun
@comment ------------------------------------------------------------
@defun c-lineup-cpp-define
@findex lineup-cpp-define (c-)
Line up macro continuation lines according to the indentation of the

View File

@ -1221,6 +1221,18 @@ Works with: arglist-cont, arglist-cont-nonempty."
(vector (progn (goto-char alignto) (current-column)))))))
(defun c-lineup-under-anchor (langelem)
"Line up the current line directly under the anchor position in LANGELEM.
This is like 0, except it supersedes any indentation already calculated for
previous syntactic elements in the syntactic context.
Works with: Any syntactic symbol which has an anchor position."
(save-excursion
(goto-char (c-langelem-pos langelem))
(vector (current-column))))
(defun c-lineup-dont-change (langelem)
"Do not change the indentation of the current line.

View File

@ -10260,13 +10260,22 @@ comment at the start of cc-engine.el for more info."
(t nil)))))
(setq pos (point))
(if (and after-type-id-pos
(goto-char after-type-id-pos)
(setq res (c-back-over-member-initializers))
(goto-char res)
(eq (car (c-beginning-of-decl-1 lim)) 'same))
(cons (point) nil) ; Return value.
(cond
((and after-type-id-pos
(goto-char after-type-id-pos)
(setq res (c-back-over-member-initializers))
(goto-char res)
(eq (car (c-beginning-of-decl-1 lim)) 'same))
(cons (point) nil)) ; Return value.
((and after-type-id-pos
(progn
(c-backward-syntactic-ws)
(eq (char-before) ?\()))
;; Single identifier between '(' and '{'. We have a bracelist.
(cons after-type-id-pos nil))
(t
(goto-char pos)
;; Checks to do on all sexps before the brace, up to the
;; beginning of the statement.
@ -10368,7 +10377,7 @@ comment at the start of cc-engine.el for more info."
; languages where
; `c-opt-inexpr-brace-list-key' is
; non-nil and we have macros.
(t t))) ;; The caller can go up one level.
(t t)))) ;; The caller can go up one level.
)))
(defun c-inside-bracelist-p (containing-sexp paren-state)
@ -10493,6 +10502,30 @@ comment at the start of cc-engine.el for more info."
(c-at-statement-start-p))
(make-obsolete 'c-looking-at-bos 'c-at-statement-start-p "22.1")
(defun c-looking-at-statement-block ()
;; Point is at an opening brace. If this is a statement block (i.e. the
;; elements in it are terminated by semicolons) return t. Otherwise, return
;; nil.
(let ((here (point)))
(prog1
(if (c-go-list-forward)
(let ((there (point)))
(backward-char)
(c-syntactic-skip-backward
"^;," here t)
(cond
((eq (char-before) ?\;) t)
((eq (char-before) ?,) nil)
(t (goto-char here)
(forward-char)
(and (c-syntactic-re-search-forward "{" there t t)
(progn (backward-char)
(c-looking-at-statement-block))))))
(forward-char)
(and (c-syntactic-re-search-forward "[;,]" nil t t)
(eq (char-before) ?\;)))
(goto-char here))))
(defun c-looking-at-inexpr-block (lim containing-sexp &optional check-at-end)
;; Return non-nil if we're looking at the beginning of a block
;; inside an expression. The value returned is actually a cons of
@ -10648,15 +10681,7 @@ comment at the start of cc-engine.el for more info."
(and (c-major-mode-is 'c++-mode)
(save-excursion
(goto-char block-follows)
(if (c-go-list-forward)
(progn
(backward-char)
(c-syntactic-skip-backward
"^;," block-follows t)
(not (eq (char-before) ?\;)))
(or (not (c-syntactic-re-search-forward
"[;,]" nil t t))
(not (eq (char-before) ?\;)))))))
(not (c-looking-at-statement-block)))))
nil
(cons 'inexpr-statement (point)))))
@ -10792,17 +10817,20 @@ comment at the start of cc-engine.el for more info."
syntax-extra-args
stop-at-boi-only
containing-sexp
paren-state)
paren-state
&optional fixed-anchor)
;; Add the indicated SYNTAX-SYMBOL to `c-syntactic-context', extending it as
;; needed with further syntax elements of the types `substatement',
;; `inexpr-statement', `arglist-cont-nonempty', `statement-block-intro', and
;; `defun-block-intro'.
;; `inexpr-statement', `arglist-cont-nonempty', `statement-block-intro',
;; `defun-block-intro', and `brace-list-intro'.
;;
;; Do the generic processing to anchor the given syntax symbol on
;; the preceding statement: Skip over any labels and containing
;; statements on the same line, and then search backward until we
;; find a statement or block start that begins at boi without a
;; label or comment.
;; Do the generic processing to anchor the given syntax symbol on the
;; preceding statement: First skip over any labels and containing statements
;; on the same line. If FIXED-ANCHOR is non-nil, use this as the
;; anchor-point for the given syntactic symbol, and don't make syntactic
;; entries for constructs beginning on lines before that containing
;; ANCHOR-POINT. Otherwise search backward until we find a statement or
;; block start that begins at boi without a label or comment.
;;
;; Point is assumed to be at the prospective anchor point for the
;; given SYNTAX-SYMBOL. More syntax entries are added if we need to
@ -10831,6 +10859,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))
;; 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.
@ -10908,7 +10937,9 @@ comment at the start of cc-engine.el for more info."
(c-add-syntax 'substatement nil))))
)))
containing-sexp)
containing-sexp
(or (null fixed-anchor)
(> containing-sexp anchor-boi)))
;; Now we have to go out of this block.
(goto-char containing-sexp)
@ -10982,6 +11013,14 @@ comment at the start of cc-engine.el for more info."
(cdr (assoc (match-string 1)
c-other-decl-block-key-in-symbols-alist))
(max (c-point 'boi paren-pos) (point))))
((save-excursion
(goto-char paren-pos)
(c-looking-at-or-maybe-in-bracelist containing-sexp))
(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)))
(t (c-add-syntax 'defun-block-intro nil))))
(c-add-syntax 'statement-block-intro nil)))
@ -11001,7 +11040,10 @@ comment at the start of cc-engine.el for more info."
(setq q (cdr (car p))) ; e.g. (nil 28) [from (arglist-cont-nonempty nil 28)]
(while q
(unless (car q)
(setcar q (point)))
(setcar q (if (or (cdr p)
(null fixed-anchor))
(point)
fixed-anchor)))
(setq q (cdr q)))
(setq p (cdr p))))
)))
@ -12354,7 +12396,8 @@ comment at the start of cc-engine.el for more info."
(c-forward-syntactic-ws (c-point 'eol))
(c-looking-at-special-brace-list (point)))))
(c-add-syntax 'brace-entry-open (point))
(c-add-syntax 'brace-list-entry (point))
(c-add-stmt-syntax 'brace-list-entry nil t containing-sexp
paren-state (point))
))
))))
@ -12848,7 +12891,7 @@ Cannot combine absolute offsets %S and %S in `add' method"
;;
;; Note that topmost-intro always has an anchor position at bol, for
;; historical reasons. It's often used together with other symbols
;; that has more sane positions. Since we always use the first
;; that have more sane positions. Since we always use the first
;; found anchor position, we rely on that these other symbols always
;; precede topmost-intro in the LANGELEMS list.
;;

View File

@ -67,6 +67,7 @@
(arglist-close . c-lineup-arglist)
(inline-open . 0)
(brace-list-open . +)
(brace-list-intro . c-lineup-arglist-intro-after-paren)
(topmost-intro-cont
. (first c-lineup-topmost-intro-cont
c-lineup-gnu-DEFUN-intro-cont))))

View File

@ -1115,7 +1115,7 @@ can always override the use of `c-default-style' by making calls to
;; Anchor pos: At the brace list decl start(*).
(brace-list-intro . +)
;; Anchor pos: At the brace list decl start(*).
(brace-list-entry . 0)
(brace-list-entry . c-lineup-under-anchor)
;; 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
;; token.