1 //===--- WhitespaceManager.cpp - Format C++ code --------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file implements WhitespaceManager class.
12 //===----------------------------------------------------------------------===//
14 #include "WhitespaceManager.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/SmallVector.h"
22 bool WhitespaceManager::Change::IsBeforeInFile::operator()(
23 const Change
&C1
, const Change
&C2
) const {
24 return SourceMgr
.isBeforeInTranslationUnit(
25 C1
.OriginalWhitespaceRange
.getBegin(),
26 C2
.OriginalWhitespaceRange
.getBegin()) ||
27 (C1
.OriginalWhitespaceRange
.getBegin() ==
28 C2
.OriginalWhitespaceRange
.getBegin() &&
29 SourceMgr
.isBeforeInTranslationUnit(
30 C1
.OriginalWhitespaceRange
.getEnd(),
31 C2
.OriginalWhitespaceRange
.getEnd()));
34 WhitespaceManager::Change::Change(const FormatToken
&Tok
,
35 bool CreateReplacement
,
36 SourceRange OriginalWhitespaceRange
,
37 int Spaces
, unsigned StartOfTokenColumn
,
38 unsigned NewlinesBefore
,
39 StringRef PreviousLinePostfix
,
40 StringRef CurrentLinePrefix
, bool IsAligned
,
41 bool ContinuesPPDirective
, bool IsInsideToken
)
42 : Tok(&Tok
), CreateReplacement(CreateReplacement
),
43 OriginalWhitespaceRange(OriginalWhitespaceRange
),
44 StartOfTokenColumn(StartOfTokenColumn
), NewlinesBefore(NewlinesBefore
),
45 PreviousLinePostfix(PreviousLinePostfix
),
46 CurrentLinePrefix(CurrentLinePrefix
), IsAligned(IsAligned
),
47 ContinuesPPDirective(ContinuesPPDirective
), Spaces(Spaces
),
48 IsInsideToken(IsInsideToken
), IsTrailingComment(false), TokenLength(0),
49 PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
50 StartOfBlockComment(nullptr), IndentationOffset(0), ConditionalsLevel(0) {
53 void WhitespaceManager::replaceWhitespace(FormatToken
&Tok
, unsigned Newlines
,
55 unsigned StartOfTokenColumn
,
56 bool IsAligned
, bool InPPDirective
) {
57 if (Tok
.Finalized
|| (Tok
.MacroCtx
&& Tok
.MacroCtx
->Role
== MR_ExpandedArg
))
59 Tok
.setDecision((Newlines
> 0) ? FD_Break
: FD_Continue
);
60 Changes
.push_back(Change(Tok
, /*CreateReplacement=*/true, Tok
.WhitespaceRange
,
61 Spaces
, StartOfTokenColumn
, Newlines
, "", "",
62 IsAligned
, InPPDirective
&& !Tok
.IsFirst
,
63 /*IsInsideToken=*/false));
66 void WhitespaceManager::addUntouchableToken(const FormatToken
&Tok
,
68 if (Tok
.Finalized
|| (Tok
.MacroCtx
&& Tok
.MacroCtx
->Role
== MR_ExpandedArg
))
70 Changes
.push_back(Change(Tok
, /*CreateReplacement=*/false,
71 Tok
.WhitespaceRange
, /*Spaces=*/0,
72 Tok
.OriginalColumn
, Tok
.NewlinesBefore
, "", "",
73 /*IsAligned=*/false, InPPDirective
&& !Tok
.IsFirst
,
74 /*IsInsideToken=*/false));
78 WhitespaceManager::addReplacement(const tooling::Replacement
&Replacement
) {
79 return Replaces
.add(Replacement
);
82 bool WhitespaceManager::inputUsesCRLF(StringRef Text
, bool DefaultToCRLF
) {
83 size_t LF
= Text
.count('\n');
84 size_t CR
= Text
.count('\r') * 2;
85 return LF
== CR
? DefaultToCRLF
: CR
> LF
;
88 void WhitespaceManager::replaceWhitespaceInToken(
89 const FormatToken
&Tok
, unsigned Offset
, unsigned ReplaceChars
,
90 StringRef PreviousPostfix
, StringRef CurrentPrefix
, bool InPPDirective
,
91 unsigned Newlines
, int Spaces
) {
92 if (Tok
.Finalized
|| (Tok
.MacroCtx
&& Tok
.MacroCtx
->Role
== MR_ExpandedArg
))
94 SourceLocation Start
= Tok
.getStartOfNonWhitespace().getLocWithOffset(Offset
);
96 Change(Tok
, /*CreateReplacement=*/true,
97 SourceRange(Start
, Start
.getLocWithOffset(ReplaceChars
)), Spaces
,
98 std::max(0, Spaces
), Newlines
, PreviousPostfix
, CurrentPrefix
,
99 /*IsAligned=*/true, InPPDirective
&& !Tok
.IsFirst
,
100 /*IsInsideToken=*/true));
103 const tooling::Replacements
&WhitespaceManager::generateReplacements() {
107 llvm::sort(Changes
, Change::IsBeforeInFile(SourceMgr
));
108 calculateLineBreakInformation();
109 alignConsecutiveMacros();
110 alignConsecutiveShortCaseStatements();
111 alignConsecutiveDeclarations();
112 alignConsecutiveBitFields();
113 alignConsecutiveAssignments();
114 alignChainedConditionals();
115 alignTrailingComments();
116 alignEscapedNewlines();
117 alignArrayInitializers();
123 void WhitespaceManager::calculateLineBreakInformation() {
124 Changes
[0].PreviousEndOfTokenColumn
= 0;
125 Change
*LastOutsideTokenChange
= &Changes
[0];
126 for (unsigned i
= 1, e
= Changes
.size(); i
!= e
; ++i
) {
127 SourceLocation OriginalWhitespaceStart
=
128 Changes
[i
].OriginalWhitespaceRange
.getBegin();
129 SourceLocation PreviousOriginalWhitespaceEnd
=
130 Changes
[i
- 1].OriginalWhitespaceRange
.getEnd();
131 unsigned OriginalWhitespaceStartOffset
=
132 SourceMgr
.getFileOffset(OriginalWhitespaceStart
);
133 unsigned PreviousOriginalWhitespaceEndOffset
=
134 SourceMgr
.getFileOffset(PreviousOriginalWhitespaceEnd
);
135 assert(PreviousOriginalWhitespaceEndOffset
<=
136 OriginalWhitespaceStartOffset
);
137 const char *const PreviousOriginalWhitespaceEndData
=
138 SourceMgr
.getCharacterData(PreviousOriginalWhitespaceEnd
);
139 StringRef
Text(PreviousOriginalWhitespaceEndData
,
140 SourceMgr
.getCharacterData(OriginalWhitespaceStart
) -
141 PreviousOriginalWhitespaceEndData
);
142 // Usually consecutive changes would occur in consecutive tokens. This is
143 // not the case however when analyzing some preprocessor runs of the
144 // annotated lines. For example, in this code:
152 // one of the runs will produce the sequence of lines marked with line 1, 2
153 // and 3. So the two consecutive whitespace changes just before '// line 2'
154 // and before '#endif // line 3' span multiple lines and tokens:
156 // #else B{change X}[// line 2
158 // ]{change Y}#endif // line 3
160 // For this reason, if the text between consecutive changes spans multiple
161 // newlines, the token length must be adjusted to the end of the original
162 // line of the token.
163 auto NewlinePos
= Text
.find_first_of('\n');
164 if (NewlinePos
== StringRef::npos
) {
165 Changes
[i
- 1].TokenLength
= OriginalWhitespaceStartOffset
-
166 PreviousOriginalWhitespaceEndOffset
+
167 Changes
[i
].PreviousLinePostfix
.size() +
168 Changes
[i
- 1].CurrentLinePrefix
.size();
170 Changes
[i
- 1].TokenLength
=
171 NewlinePos
+ Changes
[i
- 1].CurrentLinePrefix
.size();
174 // If there are multiple changes in this token, sum up all the changes until
175 // the end of the line.
176 if (Changes
[i
- 1].IsInsideToken
&& Changes
[i
- 1].NewlinesBefore
== 0) {
177 LastOutsideTokenChange
->TokenLength
+=
178 Changes
[i
- 1].TokenLength
+ Changes
[i
- 1].Spaces
;
180 LastOutsideTokenChange
= &Changes
[i
- 1];
183 Changes
[i
].PreviousEndOfTokenColumn
=
184 Changes
[i
- 1].StartOfTokenColumn
+ Changes
[i
- 1].TokenLength
;
186 Changes
[i
- 1].IsTrailingComment
=
187 (Changes
[i
].NewlinesBefore
> 0 || Changes
[i
].Tok
->is(tok::eof
) ||
188 (Changes
[i
].IsInsideToken
&& Changes
[i
].Tok
->is(tok::comment
))) &&
189 Changes
[i
- 1].Tok
->is(tok::comment
) &&
190 // FIXME: This is a dirty hack. The problem is that
191 // BreakableLineCommentSection does comment reflow changes and here is
192 // the aligning of trailing comments. Consider the case where we reflow
193 // the second line up in this example:
198 // That amounts to 2 changes by BreakableLineCommentSection:
199 // - the first, delimited by (), for the whitespace between the tokens,
200 // - and second, delimited by [], for the whitespace at the beginning
201 // of the second token:
206 // So in the end we have two changes like this:
208 // // line1()[ ]line 2
210 // Note that the OriginalWhitespaceStart of the second change is the
211 // same as the PreviousOriginalWhitespaceEnd of the first change.
212 // In this case, the below check ensures that the second change doesn't
213 // get treated as a trailing comment change here, since this might
214 // trigger additional whitespace to be wrongly inserted before "line 2"
215 // by the comment aligner here.
217 // For a proper solution we need a mechanism to say to WhitespaceManager
218 // that a particular change breaks the current sequence of trailing
220 OriginalWhitespaceStart
!= PreviousOriginalWhitespaceEnd
;
222 // FIXME: The last token is currently not always an eof token; in those
223 // cases, setting TokenLength of the last token to 0 is wrong.
224 Changes
.back().TokenLength
= 0;
225 Changes
.back().IsTrailingComment
= Changes
.back().Tok
->is(tok::comment
);
227 const WhitespaceManager::Change
*LastBlockComment
= nullptr;
228 for (auto &Change
: Changes
) {
229 // Reset the IsTrailingComment flag for changes inside of trailing comments
230 // so they don't get realigned later. Comment line breaks however still need
232 if (Change
.IsInsideToken
&& Change
.NewlinesBefore
== 0)
233 Change
.IsTrailingComment
= false;
234 Change
.StartOfBlockComment
= nullptr;
235 Change
.IndentationOffset
= 0;
236 if (Change
.Tok
->is(tok::comment
)) {
237 if (Change
.Tok
->is(TT_LineComment
) || !Change
.IsInsideToken
) {
238 LastBlockComment
= &Change
;
239 } else if ((Change
.StartOfBlockComment
= LastBlockComment
)) {
240 Change
.IndentationOffset
=
241 Change
.StartOfTokenColumn
-
242 Change
.StartOfBlockComment
->StartOfTokenColumn
;
245 LastBlockComment
= nullptr;
249 // Compute conditional nesting level
250 // Level is increased for each conditional, unless this conditional continues
251 // a chain of conditional, i.e. starts immediately after the colon of another
253 SmallVector
<bool, 16> ScopeStack
;
254 int ConditionalsLevel
= 0;
255 for (auto &Change
: Changes
) {
256 for (unsigned i
= 0, e
= Change
.Tok
->FakeLParens
.size(); i
!= e
; ++i
) {
257 bool isNestedConditional
=
258 Change
.Tok
->FakeLParens
[e
- 1 - i
] == prec::Conditional
&&
259 !(i
== 0 && Change
.Tok
->Previous
&&
260 Change
.Tok
->Previous
->is(TT_ConditionalExpr
) &&
261 Change
.Tok
->Previous
->is(tok::colon
));
262 if (isNestedConditional
)
264 ScopeStack
.push_back(isNestedConditional
);
267 Change
.ConditionalsLevel
= ConditionalsLevel
;
269 for (unsigned i
= Change
.Tok
->FakeRParens
; i
> 0 && ScopeStack
.size(); --i
)
270 if (ScopeStack
.pop_back_val())
275 // Align a single sequence of tokens, see AlignTokens below.
276 // Column - The token for which Matches returns true is moved to this column.
277 // RightJustify - Whether it is the token's right end or left end that gets
278 // moved to that column.
279 template <typename F
>
281 AlignTokenSequence(const FormatStyle
&Style
, unsigned Start
, unsigned End
,
282 unsigned Column
, bool RightJustify
, F
&&Matches
,
283 SmallVector
<WhitespaceManager::Change
, 16> &Changes
) {
284 bool FoundMatchOnLine
= false;
287 // ScopeStack keeps track of the current scope depth. It contains indices of
288 // the first token on each scope.
289 // We only run the "Matches" function on tokens from the outer-most scope.
290 // However, we do need to pay special attention to one class of tokens
291 // that are not in the outer-most scope, and that is function parameters
292 // which are split across multiple lines, as illustrated by this example:
296 // In the above example, we need to take special care to ensure that
297 // 'double z' is indented along with it's owning function 'b'.
298 // The same holds for calling a function:
299 // double a = foo(x);
300 // int b = bar(foo(y),
302 // Similar for broken string literals:
306 // Special handling is required for 'nested' ternary operators.
307 SmallVector
<unsigned, 16> ScopeStack
;
309 for (unsigned i
= Start
; i
!= End
; ++i
) {
310 auto &CurrentChange
= Changes
[i
];
311 if (ScopeStack
.size() != 0 &&
312 CurrentChange
.indentAndNestingLevel() <
313 Changes
[ScopeStack
.back()].indentAndNestingLevel()) {
314 ScopeStack
.pop_back();
317 // Compare current token to previous non-comment token to ensure whether
318 // it is in a deeper scope or not.
319 unsigned PreviousNonComment
= i
- 1;
320 while (PreviousNonComment
> Start
&&
321 Changes
[PreviousNonComment
].Tok
->is(tok::comment
)) {
322 --PreviousNonComment
;
324 if (i
!= Start
&& CurrentChange
.indentAndNestingLevel() >
325 Changes
[PreviousNonComment
].indentAndNestingLevel()) {
326 ScopeStack
.push_back(i
);
329 bool InsideNestedScope
= ScopeStack
.size() != 0;
330 bool ContinuedStringLiteral
= i
> Start
&&
331 CurrentChange
.Tok
->is(tok::string_literal
) &&
332 Changes
[i
- 1].Tok
->is(tok::string_literal
);
333 bool SkipMatchCheck
= InsideNestedScope
|| ContinuedStringLiteral
;
335 if (CurrentChange
.NewlinesBefore
> 0 && !SkipMatchCheck
) {
337 FoundMatchOnLine
= false;
340 // If this is the first matching token to be aligned, remember by how many
341 // spaces it has to be shifted, so the rest of the changes on the line are
342 // shifted by the same amount
343 if (!FoundMatchOnLine
&& !SkipMatchCheck
&& Matches(CurrentChange
)) {
344 FoundMatchOnLine
= true;
345 Shift
= Column
- (RightJustify
? CurrentChange
.TokenLength
: 0) -
346 CurrentChange
.StartOfTokenColumn
;
347 CurrentChange
.Spaces
+= Shift
;
348 // FIXME: This is a workaround that should be removed when we fix
349 // http://llvm.org/PR53699. An assertion later below verifies this.
350 if (CurrentChange
.NewlinesBefore
== 0) {
351 CurrentChange
.Spaces
=
352 std::max(CurrentChange
.Spaces
,
353 static_cast<int>(CurrentChange
.Tok
->SpacesRequiredBefore
));
360 // This is for function parameters that are split across multiple lines,
361 // as mentioned in the ScopeStack comment.
362 if (InsideNestedScope
&& CurrentChange
.NewlinesBefore
> 0) {
363 unsigned ScopeStart
= ScopeStack
.back();
364 auto ShouldShiftBeAdded
= [&] {
365 // Function declaration
366 if (Changes
[ScopeStart
- 1].Tok
->is(TT_FunctionDeclarationName
))
370 if (Changes
[ScopeStart
- 1].Tok
->is(TT_LambdaLBrace
))
373 // Continued function declaration
374 if (ScopeStart
> Start
+ 1 &&
375 Changes
[ScopeStart
- 2].Tok
->is(TT_FunctionDeclarationName
)) {
379 // Continued (template) function call.
380 if (ScopeStart
> Start
+ 1 &&
381 Changes
[ScopeStart
- 2].Tok
->isOneOf(tok::identifier
,
382 TT_TemplateCloser
) &&
383 Changes
[ScopeStart
- 1].Tok
->is(tok::l_paren
) &&
384 Changes
[ScopeStart
].Tok
->isNot(TT_LambdaLSquare
)) {
385 if (CurrentChange
.Tok
->MatchingParen
&&
386 CurrentChange
.Tok
->MatchingParen
->is(TT_LambdaLBrace
)) {
389 if (Changes
[ScopeStart
].NewlinesBefore
> 0)
391 if (CurrentChange
.Tok
->is(tok::l_brace
) &&
392 CurrentChange
.Tok
->is(BK_BracedInit
)) {
395 return Style
.BinPackArguments
;
399 if (CurrentChange
.Tok
->is(TT_ConditionalExpr
))
402 // Period Initializer .XXX = 1.
403 if (CurrentChange
.Tok
->is(TT_DesignatedInitializerPeriod
))
406 // Continued ternary operator
407 if (CurrentChange
.Tok
->Previous
&&
408 CurrentChange
.Tok
->Previous
->is(TT_ConditionalExpr
)) {
412 // Continued direct-list-initialization using braced list.
413 if (ScopeStart
> Start
+ 1 &&
414 Changes
[ScopeStart
- 2].Tok
->is(tok::identifier
) &&
415 Changes
[ScopeStart
- 1].Tok
->is(tok::l_brace
) &&
416 CurrentChange
.Tok
->is(tok::l_brace
) &&
417 CurrentChange
.Tok
->is(BK_BracedInit
)) {
421 // Continued braced list.
422 if (ScopeStart
> Start
+ 1 &&
423 Changes
[ScopeStart
- 2].Tok
->isNot(tok::identifier
) &&
424 Changes
[ScopeStart
- 1].Tok
->is(tok::l_brace
) &&
425 CurrentChange
.Tok
->isNot(tok::r_brace
)) {
426 for (unsigned OuterScopeStart
: llvm::reverse(ScopeStack
)) {
428 if (OuterScopeStart
> Start
&&
429 Changes
[OuterScopeStart
- 1].Tok
->is(TT_LambdaLBrace
)) {
433 if (Changes
[ScopeStart
].NewlinesBefore
> 0)
438 // Continued template parameter.
439 if (Changes
[ScopeStart
- 1].Tok
->is(TT_TemplateOpener
))
445 if (ShouldShiftBeAdded())
446 CurrentChange
.Spaces
+= Shift
;
449 if (ContinuedStringLiteral
)
450 CurrentChange
.Spaces
+= Shift
;
452 // We should not remove required spaces unless we break the line before.
453 assert(Shift
> 0 || Changes
[i
].NewlinesBefore
> 0 ||
454 CurrentChange
.Spaces
>=
455 static_cast<int>(Changes
[i
].Tok
->SpacesRequiredBefore
) ||
456 CurrentChange
.Tok
->is(tok::eof
));
458 CurrentChange
.StartOfTokenColumn
+= Shift
;
459 if (i
+ 1 != Changes
.size())
460 Changes
[i
+ 1].PreviousEndOfTokenColumn
+= Shift
;
462 // If PointerAlignment is PAS_Right, keep *s or &s next to the token
463 if ((Style
.PointerAlignment
== FormatStyle::PAS_Right
||
464 Style
.ReferenceAlignment
== FormatStyle::RAS_Right
) &&
465 CurrentChange
.Spaces
!= 0) {
466 const bool ReferenceNotRightAligned
=
467 Style
.ReferenceAlignment
!= FormatStyle::RAS_Right
&&
468 Style
.ReferenceAlignment
!= FormatStyle::RAS_Pointer
;
469 for (int Previous
= i
- 1;
471 Changes
[Previous
].Tok
->getType() == TT_PointerOrReference
;
473 assert(Changes
[Previous
].Tok
->isPointerOrReference());
474 if (Changes
[Previous
].Tok
->isNot(tok::star
)) {
475 if (ReferenceNotRightAligned
)
477 } else if (Style
.PointerAlignment
!= FormatStyle::PAS_Right
) {
480 Changes
[Previous
+ 1].Spaces
-= Shift
;
481 Changes
[Previous
].Spaces
+= Shift
;
482 Changes
[Previous
].StartOfTokenColumn
+= Shift
;
488 // Walk through a subset of the changes, starting at StartAt, and find
489 // sequences of matching tokens to align. To do so, keep track of the lines and
490 // whether or not a matching token was found on a line. If a matching token is
491 // found, extend the current sequence. If the current line cannot be part of a
492 // sequence, e.g. because there is an empty line before it or it contains only
493 // non-matching tokens, finalize the previous sequence.
494 // The value returned is the token on which we stopped, either because we
495 // exhausted all items inside Changes, or because we hit a scope level higher
496 // than our initial scope.
497 // This function is recursive. Each invocation processes only the scope level
498 // equal to the initial level, which is the level of Changes[StartAt].
499 // If we encounter a scope level greater than the initial level, then we call
500 // ourselves recursively, thereby avoiding the pollution of the current state
501 // with the alignment requirements of the nested sub-level. This recursive
502 // behavior is necessary for aligning function prototypes that have one or more
504 // If this function encounters a scope level less than the initial level,
505 // it returns the current position.
506 // There is a non-obvious subtlety in the recursive behavior: Even though we
507 // defer processing of nested levels to recursive invocations of this
508 // function, when it comes time to align a sequence of tokens, we run the
509 // alignment on the entire sequence, including the nested levels.
510 // When doing so, most of the nested tokens are skipped, because their
511 // alignment was already handled by the recursive invocations of this function.
512 // However, the special exception is that we do NOT skip function parameters
513 // that are split across multiple lines. See the test case in FormatTest.cpp
514 // that mentions "split function parameter alignment" for an example of this.
515 // When the parameter RightJustify is true, the operator will be
516 // right-justified. It is used to align compound assignments like `+=` and `=`.
517 // When RightJustify and ACS.PadOperators are true, operators in each block to
518 // be aligned will be padded on the left to the same length before aligning.
519 template <typename F
>
520 static unsigned AlignTokens(const FormatStyle
&Style
, F
&&Matches
,
521 SmallVector
<WhitespaceManager::Change
, 16> &Changes
,
523 const FormatStyle::AlignConsecutiveStyle
&ACS
= {},
524 bool RightJustify
= false) {
525 // We arrange each line in 3 parts. The operator to be aligned (the anchor),
526 // and text to its left and right. In the aligned text the width of each part
527 // will be the maximum of that over the block that has been aligned. Maximum
528 // widths of each part so far. When RightJustify is true and ACS.PadOperators
529 // is false, the part from start of line to the right end of the anchor.
530 // Otherwise, only the part to the left of the anchor. Including the space
531 // that exists on its left from the start. Not including the padding added on
532 // the left to right-justify the anchor.
533 unsigned WidthLeft
= 0;
534 // The operator to be aligned when RightJustify is true and ACS.PadOperators
535 // is false. 0 otherwise.
536 unsigned WidthAnchor
= 0;
537 // Width to the right of the anchor. Plus width of the anchor when
538 // RightJustify is false.
539 unsigned WidthRight
= 0;
541 // Line number of the start and the end of the current token sequence.
542 unsigned StartOfSequence
= 0;
543 unsigned EndOfSequence
= 0;
545 // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
546 // abort when we hit any token in a higher scope than the starting one.
547 auto IndentAndNestingLevel
= StartAt
< Changes
.size()
548 ? Changes
[StartAt
].indentAndNestingLevel()
549 : std::tuple
<unsigned, unsigned, unsigned>();
551 // Keep track of the number of commas before the matching tokens, we will only
552 // align a sequence of matching tokens if they are preceded by the same number
554 unsigned CommasBeforeLastMatch
= 0;
555 unsigned CommasBeforeMatch
= 0;
557 // Whether a matching token has been found on the current line.
558 bool FoundMatchOnLine
= false;
560 // Whether the current line consists purely of comments.
561 bool LineIsComment
= true;
563 // Aligns a sequence of matching tokens, on the MinColumn column.
565 // Sequences start from the first matching token to align, and end at the
566 // first token of the first line that doesn't need to be aligned.
568 // We need to adjust the StartOfTokenColumn of each Change that is on a line
569 // containing any matching token to be aligned and located after such token.
570 auto AlignCurrentSequence
= [&] {
571 if (StartOfSequence
> 0 && StartOfSequence
< EndOfSequence
) {
572 AlignTokenSequence(Style
, StartOfSequence
, EndOfSequence
,
573 WidthLeft
+ WidthAnchor
, RightJustify
, Matches
,
583 unsigned i
= StartAt
;
584 for (unsigned e
= Changes
.size(); i
!= e
; ++i
) {
585 auto &CurrentChange
= Changes
[i
];
586 if (CurrentChange
.indentAndNestingLevel() < IndentAndNestingLevel
)
589 if (CurrentChange
.NewlinesBefore
!= 0) {
590 CommasBeforeMatch
= 0;
593 // Whether to break the alignment sequence because of an empty line.
594 bool EmptyLineBreak
=
595 (CurrentChange
.NewlinesBefore
> 1) && !ACS
.AcrossEmptyLines
;
597 // Whether to break the alignment sequence because of a line without a
600 !FoundMatchOnLine
&& !(LineIsComment
&& ACS
.AcrossComments
);
602 if (EmptyLineBreak
|| NoMatchBreak
)
603 AlignCurrentSequence();
605 // A new line starts, re-initialize line status tracking bools.
606 // Keep the match state if a string literal is continued on this line.
607 if (i
== 0 || CurrentChange
.Tok
->isNot(tok::string_literal
) ||
608 Changes
[i
- 1].Tok
->isNot(tok::string_literal
)) {
609 FoundMatchOnLine
= false;
611 LineIsComment
= true;
614 if (CurrentChange
.Tok
->isNot(tok::comment
))
615 LineIsComment
= false;
617 if (CurrentChange
.Tok
->is(tok::comma
)) {
619 } else if (CurrentChange
.indentAndNestingLevel() > IndentAndNestingLevel
) {
620 // Call AlignTokens recursively, skipping over this scope block.
622 AlignTokens(Style
, Matches
, Changes
, i
, ACS
, RightJustify
);
627 if (!Matches(CurrentChange
))
630 // If there is more than one matching token per line, or if the number of
631 // preceding commas, do not match anymore, end the sequence.
632 if (FoundMatchOnLine
|| CommasBeforeMatch
!= CommasBeforeLastMatch
)
633 AlignCurrentSequence();
635 CommasBeforeLastMatch
= CommasBeforeMatch
;
636 FoundMatchOnLine
= true;
638 if (StartOfSequence
== 0)
641 unsigned ChangeWidthLeft
= CurrentChange
.StartOfTokenColumn
;
642 unsigned ChangeWidthAnchor
= 0;
643 unsigned ChangeWidthRight
= 0;
645 if (ACS
.PadOperators
)
646 ChangeWidthAnchor
= CurrentChange
.TokenLength
;
648 ChangeWidthLeft
+= CurrentChange
.TokenLength
;
650 ChangeWidthRight
= CurrentChange
.TokenLength
;
651 for (unsigned j
= i
+ 1; j
!= e
&& Changes
[j
].NewlinesBefore
== 0; ++j
) {
652 ChangeWidthRight
+= Changes
[j
].Spaces
;
653 // Changes are generally 1:1 with the tokens, but a change could also be
654 // inside of a token, in which case it's counted more than once: once for
655 // the whitespace surrounding the token (!IsInsideToken) and once for
656 // each whitespace change within it (IsInsideToken).
657 // Therefore, changes inside of a token should only count the space.
658 if (!Changes
[j
].IsInsideToken
)
659 ChangeWidthRight
+= Changes
[j
].TokenLength
;
662 // If we are restricted by the maximum column width, end the sequence.
663 unsigned NewLeft
= std::max(ChangeWidthLeft
, WidthLeft
);
664 unsigned NewAnchor
= std::max(ChangeWidthAnchor
, WidthAnchor
);
665 unsigned NewRight
= std::max(ChangeWidthRight
, WidthRight
);
666 // `ColumnLimit == 0` means there is no column limit.
667 if (Style
.ColumnLimit
!= 0 &&
668 Style
.ColumnLimit
< NewLeft
+ NewAnchor
+ NewRight
) {
669 AlignCurrentSequence();
671 WidthLeft
= ChangeWidthLeft
;
672 WidthAnchor
= ChangeWidthAnchor
;
673 WidthRight
= ChangeWidthRight
;
676 WidthAnchor
= NewAnchor
;
677 WidthRight
= NewRight
;
682 AlignCurrentSequence();
686 // Aligns a sequence of matching tokens, on the MinColumn column.
688 // Sequences start from the first matching token to align, and end at the
689 // first token of the first line that doesn't need to be aligned.
691 // We need to adjust the StartOfTokenColumn of each Change that is on a line
692 // containing any matching token to be aligned and located after such token.
693 static void AlignMatchingTokenSequence(
694 unsigned &StartOfSequence
, unsigned &EndOfSequence
, unsigned &MinColumn
,
695 std::function
<bool(const WhitespaceManager::Change
&C
)> Matches
,
696 SmallVector
<WhitespaceManager::Change
, 16> &Changes
) {
697 if (StartOfSequence
> 0 && StartOfSequence
< EndOfSequence
) {
698 bool FoundMatchOnLine
= false;
701 for (unsigned I
= StartOfSequence
; I
!= EndOfSequence
; ++I
) {
702 if (Changes
[I
].NewlinesBefore
> 0) {
704 FoundMatchOnLine
= false;
707 // If this is the first matching token to be aligned, remember by how many
708 // spaces it has to be shifted, so the rest of the changes on the line are
709 // shifted by the same amount.
710 if (!FoundMatchOnLine
&& Matches(Changes
[I
])) {
711 FoundMatchOnLine
= true;
712 Shift
= MinColumn
- Changes
[I
].StartOfTokenColumn
;
713 Changes
[I
].Spaces
+= Shift
;
717 Changes
[I
].StartOfTokenColumn
+= Shift
;
718 if (I
+ 1 != Changes
.size())
719 Changes
[I
+ 1].PreviousEndOfTokenColumn
+= Shift
;
728 void WhitespaceManager::alignConsecutiveMacros() {
729 if (!Style
.AlignConsecutiveMacros
.Enabled
)
732 auto AlignMacrosMatches
= [](const Change
&C
) {
733 const FormatToken
*Current
= C
.Tok
;
734 unsigned SpacesRequiredBefore
= 1;
736 if (Current
->SpacesRequiredBefore
== 0 || !Current
->Previous
)
739 Current
= Current
->Previous
;
741 // If token is a ")", skip over the parameter list, to the
742 // token that precedes the "("
743 if (Current
->is(tok::r_paren
) && Current
->MatchingParen
) {
744 Current
= Current
->MatchingParen
->Previous
;
745 SpacesRequiredBefore
= 0;
748 if (!Current
|| Current
->isNot(tok::identifier
))
751 if (!Current
->Previous
|| Current
->Previous
->isNot(tok::pp_define
))
754 // For a macro function, 0 spaces are required between the
755 // identifier and the lparen that opens the parameter list.
756 // For a simple macro, 1 space is required between the
757 // identifier and the first token of the defined value.
758 return Current
->Next
->SpacesRequiredBefore
== SpacesRequiredBefore
;
761 unsigned MinColumn
= 0;
763 // Start and end of the token sequence we're processing.
764 unsigned StartOfSequence
= 0;
765 unsigned EndOfSequence
= 0;
767 // Whether a matching token has been found on the current line.
768 bool FoundMatchOnLine
= false;
770 // Whether the current line consists only of comments
771 bool LineIsComment
= true;
774 for (unsigned E
= Changes
.size(); I
!= E
; ++I
) {
775 if (Changes
[I
].NewlinesBefore
!= 0) {
778 // Whether to break the alignment sequence because of an empty line.
779 bool EmptyLineBreak
= (Changes
[I
].NewlinesBefore
> 1) &&
780 !Style
.AlignConsecutiveMacros
.AcrossEmptyLines
;
782 // Whether to break the alignment sequence because of a line without a
786 !(LineIsComment
&& Style
.AlignConsecutiveMacros
.AcrossComments
);
788 if (EmptyLineBreak
|| NoMatchBreak
) {
789 AlignMatchingTokenSequence(StartOfSequence
, EndOfSequence
, MinColumn
,
790 AlignMacrosMatches
, Changes
);
793 // A new line starts, re-initialize line status tracking bools.
794 FoundMatchOnLine
= false;
795 LineIsComment
= true;
798 if (Changes
[I
].Tok
->isNot(tok::comment
))
799 LineIsComment
= false;
801 if (!AlignMacrosMatches(Changes
[I
]))
804 FoundMatchOnLine
= true;
806 if (StartOfSequence
== 0)
809 unsigned ChangeMinColumn
= Changes
[I
].StartOfTokenColumn
;
810 MinColumn
= std::max(MinColumn
, ChangeMinColumn
);
814 AlignMatchingTokenSequence(StartOfSequence
, EndOfSequence
, MinColumn
,
815 AlignMacrosMatches
, Changes
);
818 void WhitespaceManager::alignConsecutiveAssignments() {
819 if (!Style
.AlignConsecutiveAssignments
.Enabled
)
824 [&](const Change
&C
) {
825 // Do not align on equal signs that are first on a line.
826 if (C
.NewlinesBefore
> 0)
829 // Do not align on equal signs that are last on a line.
830 if (&C
!= &Changes
.back() && (&C
+ 1)->NewlinesBefore
> 0)
833 // Do not align operator= overloads.
834 FormatToken
*Previous
= C
.Tok
->getPreviousNonComment();
835 if (Previous
&& Previous
->is(tok::kw_operator
))
838 return Style
.AlignConsecutiveAssignments
.AlignCompound
839 ? C
.Tok
->getPrecedence() == prec::Assignment
840 : (C
.Tok
->is(tok::equal
) ||
841 // In Verilog the '<=' is not a compound assignment, thus
842 // it is aligned even when the AlignCompound option is not
844 (Style
.isVerilog() && C
.Tok
->is(tok::lessequal
) &&
845 C
.Tok
->getPrecedence() == prec::Assignment
));
847 Changes
, /*StartAt=*/0, Style
.AlignConsecutiveAssignments
,
848 /*RightJustify=*/true);
851 void WhitespaceManager::alignConsecutiveBitFields() {
852 if (!Style
.AlignConsecutiveBitFields
.Enabled
)
857 [&](Change
const &C
) {
858 // Do not align on ':' that is first on a line.
859 if (C
.NewlinesBefore
> 0)
862 // Do not align on ':' that is last on a line.
863 if (&C
!= &Changes
.back() && (&C
+ 1)->NewlinesBefore
> 0)
866 return C
.Tok
->is(TT_BitFieldColon
);
868 Changes
, /*StartAt=*/0, Style
.AlignConsecutiveBitFields
);
871 void WhitespaceManager::alignConsecutiveShortCaseStatements() {
872 if (!Style
.AlignConsecutiveShortCaseStatements
.Enabled
||
873 !Style
.AllowShortCaseLabelsOnASingleLine
) {
877 auto Matches
= [&](const Change
&C
) {
878 if (Style
.AlignConsecutiveShortCaseStatements
.AlignCaseColons
)
879 return C
.Tok
->is(TT_CaseLabelColon
);
881 // Ignore 'IsInsideToken' to allow matching trailing comments which
882 // need to be reflowed as that causes the token to appear in two
883 // different changes, which will cause incorrect alignment as we'll
884 // reflow early due to detecting multiple aligning tokens per line.
885 return !C
.IsInsideToken
&& C
.Tok
->Previous
&&
886 C
.Tok
->Previous
->is(TT_CaseLabelColon
);
889 unsigned MinColumn
= 0;
891 // Empty case statements don't break the alignment, but don't necessarily
892 // match our predicate, so we need to track their column so they can push out
894 unsigned MinEmptyCaseColumn
= 0;
896 // Start and end of the token sequence we're processing.
897 unsigned StartOfSequence
= 0;
898 unsigned EndOfSequence
= 0;
900 // Whether a matching token has been found on the current line.
901 bool FoundMatchOnLine
= false;
903 bool LineIsComment
= true;
904 bool LineIsEmptyCase
= false;
907 for (unsigned E
= Changes
.size(); I
!= E
; ++I
) {
908 if (Changes
[I
].NewlinesBefore
!= 0) {
909 // Whether to break the alignment sequence because of an empty line.
910 bool EmptyLineBreak
=
911 (Changes
[I
].NewlinesBefore
> 1) &&
912 !Style
.AlignConsecutiveShortCaseStatements
.AcrossEmptyLines
;
914 // Whether to break the alignment sequence because of a line without a
919 Style
.AlignConsecutiveShortCaseStatements
.AcrossComments
) &&
922 if (EmptyLineBreak
|| NoMatchBreak
) {
923 AlignMatchingTokenSequence(StartOfSequence
, EndOfSequence
, MinColumn
,
925 MinEmptyCaseColumn
= 0;
928 // A new line starts, re-initialize line status tracking bools.
929 FoundMatchOnLine
= false;
930 LineIsComment
= true;
931 LineIsEmptyCase
= false;
934 if (Changes
[I
].Tok
->isNot(tok::comment
))
935 LineIsComment
= false;
937 if (Changes
[I
].Tok
->is(TT_CaseLabelColon
)) {
939 !Changes
[I
].Tok
->Next
|| Changes
[I
].Tok
->Next
->isTrailingComment();
941 if (LineIsEmptyCase
) {
942 if (Style
.AlignConsecutiveShortCaseStatements
.AlignCaseColons
) {
944 std::max(MinEmptyCaseColumn
, Changes
[I
].StartOfTokenColumn
);
947 std::max(MinEmptyCaseColumn
, Changes
[I
].StartOfTokenColumn
+ 2);
952 if (!Matches(Changes
[I
]))
958 FoundMatchOnLine
= true;
960 if (StartOfSequence
== 0)
963 EndOfSequence
= I
+ 1;
965 MinColumn
= std::max(MinColumn
, Changes
[I
].StartOfTokenColumn
);
967 // Allow empty case statements to push out our alignment.
968 MinColumn
= std::max(MinColumn
, MinEmptyCaseColumn
);
971 AlignMatchingTokenSequence(StartOfSequence
, EndOfSequence
, MinColumn
, Matches
,
975 void WhitespaceManager::alignConsecutiveDeclarations() {
976 if (!Style
.AlignConsecutiveDeclarations
.Enabled
)
981 [](Change
const &C
) {
982 if (C
.Tok
->is(TT_FunctionDeclarationName
))
984 if (C
.Tok
->isNot(TT_StartOfName
))
986 if (C
.Tok
->Previous
&&
987 C
.Tok
->Previous
->is(TT_StatementAttributeLikeMacro
))
989 // Check if there is a subsequent name that starts the same declaration.
990 for (FormatToken
*Next
= C
.Tok
->Next
; Next
; Next
= Next
->Next
) {
991 if (Next
->is(tok::comment
))
993 if (Next
->is(TT_PointerOrReference
))
995 if (!Next
->Tok
.getIdentifierInfo())
997 if (Next
->isOneOf(TT_StartOfName
, TT_FunctionDeclarationName
,
1004 Changes
, /*StartAt=*/0, Style
.AlignConsecutiveDeclarations
);
1007 void WhitespaceManager::alignChainedConditionals() {
1008 if (Style
.BreakBeforeTernaryOperators
) {
1011 [](Change
const &C
) {
1012 // Align question operators and last colon
1013 return C
.Tok
->is(TT_ConditionalExpr
) &&
1014 ((C
.Tok
->is(tok::question
) && !C
.NewlinesBefore
) ||
1015 (C
.Tok
->is(tok::colon
) && C
.Tok
->Next
&&
1016 (C
.Tok
->Next
->FakeLParens
.size() == 0 ||
1017 C
.Tok
->Next
->FakeLParens
.back() != prec::Conditional
)));
1019 Changes
, /*StartAt=*/0);
1021 static auto AlignWrappedOperand
= [](Change
const &C
) {
1022 FormatToken
*Previous
= C
.Tok
->getPreviousNonComment();
1023 return C
.NewlinesBefore
&& Previous
&& Previous
->is(TT_ConditionalExpr
) &&
1024 (Previous
->is(tok::colon
) &&
1025 (C
.Tok
->FakeLParens
.size() == 0 ||
1026 C
.Tok
->FakeLParens
.back() != prec::Conditional
));
1028 // Ensure we keep alignment of wrapped operands with non-wrapped operands
1029 // Since we actually align the operators, the wrapped operands need the
1030 // extra offset to be properly aligned.
1031 for (Change
&C
: Changes
)
1032 if (AlignWrappedOperand(C
))
1033 C
.StartOfTokenColumn
-= 2;
1036 [this](Change
const &C
) {
1037 // Align question operators if next operand is not wrapped, as
1038 // well as wrapped operands after question operator or last
1039 // colon in conditional sequence
1040 return (C
.Tok
->is(TT_ConditionalExpr
) && C
.Tok
->is(tok::question
) &&
1041 &C
!= &Changes
.back() && (&C
+ 1)->NewlinesBefore
== 0 &&
1042 !(&C
+ 1)->IsTrailingComment
) ||
1043 AlignWrappedOperand(C
);
1045 Changes
, /*StartAt=*/0);
1049 void WhitespaceManager::alignTrailingComments() {
1050 if (Style
.AlignTrailingComments
.Kind
== FormatStyle::TCAS_Never
)
1053 const int Size
= Changes
.size();
1055 int StartOfSequence
= 0;
1056 bool BreakBeforeNext
= false;
1057 int NewLineThreshold
= 1;
1058 if (Style
.AlignTrailingComments
.Kind
== FormatStyle::TCAS_Always
)
1059 NewLineThreshold
= Style
.AlignTrailingComments
.OverEmptyLines
+ 1;
1061 for (int I
= 0, MaxColumn
= INT_MAX
, Newlines
= 0; I
< Size
; ++I
) {
1062 auto &C
= Changes
[I
];
1063 if (C
.StartOfBlockComment
)
1065 Newlines
+= C
.NewlinesBefore
;
1066 if (!C
.IsTrailingComment
)
1069 if (Style
.AlignTrailingComments
.Kind
== FormatStyle::TCAS_Leave
) {
1070 const int OriginalSpaces
=
1071 C
.OriginalWhitespaceRange
.getEnd().getRawEncoding() -
1072 C
.OriginalWhitespaceRange
.getBegin().getRawEncoding() -
1073 C
.Tok
->LastNewlineOffset
;
1074 assert(OriginalSpaces
>= 0);
1075 const auto RestoredLineLength
=
1076 C
.StartOfTokenColumn
+ C
.TokenLength
+ OriginalSpaces
;
1077 // If leaving comments makes the line exceed the column limit, give up to
1078 // leave the comments.
1079 if (RestoredLineLength
>= Style
.ColumnLimit
&& Style
.ColumnLimit
> 0)
1081 C
.Spaces
= OriginalSpaces
;
1085 const int ChangeMinColumn
= C
.StartOfTokenColumn
;
1086 int ChangeMaxColumn
;
1088 // If we don't create a replacement for this change, we have to consider
1089 // it to be immovable.
1090 if (!C
.CreateReplacement
)
1091 ChangeMaxColumn
= ChangeMinColumn
;
1092 else if (Style
.ColumnLimit
== 0)
1093 ChangeMaxColumn
= INT_MAX
;
1094 else if (Style
.ColumnLimit
>= C
.TokenLength
)
1095 ChangeMaxColumn
= Style
.ColumnLimit
- C
.TokenLength
;
1097 ChangeMaxColumn
= ChangeMinColumn
;
1099 if (I
+ 1 < Size
&& Changes
[I
+ 1].ContinuesPPDirective
&&
1100 ChangeMaxColumn
>= 2) {
1101 ChangeMaxColumn
-= 2;
1104 bool WasAlignedWithStartOfNextLine
= false;
1105 if (C
.NewlinesBefore
>= 1) { // A comment on its own line.
1106 const auto CommentColumn
=
1107 SourceMgr
.getSpellingColumnNumber(C
.OriginalWhitespaceRange
.getEnd());
1108 for (int J
= I
+ 1; J
< Size
; ++J
) {
1109 if (Changes
[J
].Tok
->is(tok::comment
))
1112 const auto NextColumn
= SourceMgr
.getSpellingColumnNumber(
1113 Changes
[J
].OriginalWhitespaceRange
.getEnd());
1114 // The start of the next token was previously aligned with the
1115 // start of this comment.
1116 WasAlignedWithStartOfNextLine
=
1117 CommentColumn
== NextColumn
||
1118 CommentColumn
== NextColumn
+ Style
.IndentWidth
;
1123 // We don't want to align comments which end a scope, which are here
1124 // identified by most closing braces.
1125 auto DontAlignThisComment
= [](const auto *Tok
) {
1126 if (Tok
->is(tok::semi
)) {
1127 Tok
= Tok
->getPreviousNonComment();
1131 if (Tok
->is(tok::r_paren
)) {
1132 // Back up past the parentheses and a `TT_DoWhile` that may precede.
1133 Tok
= Tok
->MatchingParen
;
1136 Tok
= Tok
->getPreviousNonComment();
1139 if (Tok
->is(TT_DoWhile
)) {
1140 const auto *Prev
= Tok
->getPreviousNonComment();
1142 // A do-while-loop without braces.
1149 if (Tok
->isNot(tok::r_brace
))
1152 while (Tok
->Previous
&& Tok
->Previous
->is(tok::r_brace
))
1153 Tok
= Tok
->Previous
;
1154 return Tok
->NewlinesBefore
> 0;
1157 if (I
> 0 && C
.NewlinesBefore
== 0 &&
1158 DontAlignThisComment(Changes
[I
- 1].Tok
)) {
1159 alignTrailingComments(StartOfSequence
, I
, MinColumn
);
1160 // Reset to initial values, but skip this change for the next alignment
1163 MaxColumn
= INT_MAX
;
1164 StartOfSequence
= I
+ 1;
1165 } else if (BreakBeforeNext
|| Newlines
> NewLineThreshold
||
1166 (ChangeMinColumn
> MaxColumn
|| ChangeMaxColumn
< MinColumn
) ||
1167 // Break the comment sequence if the previous line did not end
1168 // in a trailing comment.
1169 (C
.NewlinesBefore
== 1 && I
> 0 &&
1170 !Changes
[I
- 1].IsTrailingComment
) ||
1171 WasAlignedWithStartOfNextLine
) {
1172 alignTrailingComments(StartOfSequence
, I
, MinColumn
);
1173 MinColumn
= ChangeMinColumn
;
1174 MaxColumn
= ChangeMaxColumn
;
1175 StartOfSequence
= I
;
1177 MinColumn
= std::max(MinColumn
, ChangeMinColumn
);
1178 MaxColumn
= std::min(MaxColumn
, ChangeMaxColumn
);
1180 BreakBeforeNext
= (I
== 0) || (C
.NewlinesBefore
> 1) ||
1181 // Never start a sequence with a comment at the beginning
1183 (C
.NewlinesBefore
== 1 && StartOfSequence
== I
);
1186 alignTrailingComments(StartOfSequence
, Size
, MinColumn
);
1189 void WhitespaceManager::alignTrailingComments(unsigned Start
, unsigned End
,
1191 for (unsigned i
= Start
; i
!= End
; ++i
) {
1193 if (Changes
[i
].IsTrailingComment
)
1194 Shift
= Column
- Changes
[i
].StartOfTokenColumn
;
1195 if (Changes
[i
].StartOfBlockComment
) {
1196 Shift
= Changes
[i
].IndentationOffset
+
1197 Changes
[i
].StartOfBlockComment
->StartOfTokenColumn
-
1198 Changes
[i
].StartOfTokenColumn
;
1202 Changes
[i
].Spaces
+= Shift
;
1203 if (i
+ 1 != Changes
.size())
1204 Changes
[i
+ 1].PreviousEndOfTokenColumn
+= Shift
;
1205 Changes
[i
].StartOfTokenColumn
+= Shift
;
1209 void WhitespaceManager::alignEscapedNewlines() {
1210 if (Style
.AlignEscapedNewlines
== FormatStyle::ENAS_DontAlign
)
1213 bool AlignLeft
= Style
.AlignEscapedNewlines
== FormatStyle::ENAS_Left
;
1214 unsigned MaxEndOfLine
= AlignLeft
? 0 : Style
.ColumnLimit
;
1215 unsigned StartOfMacro
= 0;
1216 for (unsigned i
= 1, e
= Changes
.size(); i
< e
; ++i
) {
1217 Change
&C
= Changes
[i
];
1218 if (C
.NewlinesBefore
> 0) {
1219 if (C
.ContinuesPPDirective
) {
1220 MaxEndOfLine
= std::max(C
.PreviousEndOfTokenColumn
+ 2, MaxEndOfLine
);
1222 alignEscapedNewlines(StartOfMacro
+ 1, i
, MaxEndOfLine
);
1223 MaxEndOfLine
= AlignLeft
? 0 : Style
.ColumnLimit
;
1228 alignEscapedNewlines(StartOfMacro
+ 1, Changes
.size(), MaxEndOfLine
);
1231 void WhitespaceManager::alignEscapedNewlines(unsigned Start
, unsigned End
,
1233 for (unsigned i
= Start
; i
< End
; ++i
) {
1234 Change
&C
= Changes
[i
];
1235 if (C
.NewlinesBefore
> 0) {
1236 assert(C
.ContinuesPPDirective
);
1237 if (C
.PreviousEndOfTokenColumn
+ 1 > Column
)
1238 C
.EscapedNewlineColumn
= 0;
1240 C
.EscapedNewlineColumn
= Column
;
1245 void WhitespaceManager::alignArrayInitializers() {
1246 if (Style
.AlignArrayOfStructures
== FormatStyle::AIAS_None
)
1249 for (unsigned ChangeIndex
= 1U, ChangeEnd
= Changes
.size();
1250 ChangeIndex
< ChangeEnd
; ++ChangeIndex
) {
1251 auto &C
= Changes
[ChangeIndex
];
1252 if (C
.Tok
->IsArrayInitializer
) {
1253 bool FoundComplete
= false;
1254 for (unsigned InsideIndex
= ChangeIndex
+ 1; InsideIndex
< ChangeEnd
;
1256 if (Changes
[InsideIndex
].Tok
== C
.Tok
->MatchingParen
) {
1257 alignArrayInitializers(ChangeIndex
, InsideIndex
+ 1);
1258 ChangeIndex
= InsideIndex
+ 1;
1259 FoundComplete
= true;
1264 ChangeIndex
= ChangeEnd
;
1269 void WhitespaceManager::alignArrayInitializers(unsigned Start
, unsigned End
) {
1271 if (Style
.AlignArrayOfStructures
== FormatStyle::AIAS_Right
)
1272 alignArrayInitializersRightJustified(getCells(Start
, End
));
1273 else if (Style
.AlignArrayOfStructures
== FormatStyle::AIAS_Left
)
1274 alignArrayInitializersLeftJustified(getCells(Start
, End
));
1277 void WhitespaceManager::alignArrayInitializersRightJustified(
1278 CellDescriptions
&&CellDescs
) {
1279 if (!CellDescs
.isRectangular())
1282 const int BracePadding
= Style
.Cpp11BracedListStyle
? 0 : 1;
1283 auto &Cells
= CellDescs
.Cells
;
1284 // Now go through and fixup the spaces.
1285 auto *CellIter
= Cells
.begin();
1286 for (auto i
= 0U; i
< CellDescs
.CellCounts
[0]; ++i
, ++CellIter
) {
1287 unsigned NetWidth
= 0U;
1288 if (isSplitCell(*CellIter
))
1289 NetWidth
= getNetWidth(Cells
.begin(), CellIter
, CellDescs
.InitialSpaces
);
1290 auto CellWidth
= getMaximumCellWidth(CellIter
, NetWidth
);
1292 if (Changes
[CellIter
->Index
].Tok
->is(tok::r_brace
)) {
1293 // So in here we want to see if there is a brace that falls
1294 // on a line that was split. If so on that line we make sure that
1295 // the spaces in front of the brace are enough.
1296 const auto *Next
= CellIter
;
1298 const FormatToken
*Previous
= Changes
[Next
->Index
].Tok
->Previous
;
1299 if (Previous
&& Previous
->isNot(TT_LineComment
)) {
1300 Changes
[Next
->Index
].Spaces
= BracePadding
;
1301 Changes
[Next
->Index
].NewlinesBefore
= 0;
1303 Next
= Next
->NextColumnElement
;
1305 // Unless the array is empty, we need the position of all the
1306 // immediately adjacent cells
1307 if (CellIter
!= Cells
.begin()) {
1309 getNetWidth(Cells
.begin(), CellIter
, CellDescs
.InitialSpaces
);
1310 auto MaxNetWidth
= getMaximumNetWidth(
1311 Cells
.begin(), CellIter
, CellDescs
.InitialSpaces
,
1312 CellDescs
.CellCounts
[0], CellDescs
.CellCounts
.size());
1313 if (ThisNetWidth
< MaxNetWidth
)
1314 Changes
[CellIter
->Index
].Spaces
= (MaxNetWidth
- ThisNetWidth
);
1316 auto Offset
= std::distance(Cells
.begin(), CellIter
);
1317 for (const auto *Next
= CellIter
->NextColumnElement
; Next
;
1318 Next
= Next
->NextColumnElement
) {
1319 if (RowCount
>= CellDescs
.CellCounts
.size())
1321 auto *Start
= (Cells
.begin() + RowCount
* CellDescs
.CellCounts
[0]);
1322 auto *End
= Start
+ Offset
;
1323 ThisNetWidth
= getNetWidth(Start
, End
, CellDescs
.InitialSpaces
);
1324 if (ThisNetWidth
< MaxNetWidth
)
1325 Changes
[Next
->Index
].Spaces
= (MaxNetWidth
- ThisNetWidth
);
1331 calculateCellWidth(CellIter
->Index
, CellIter
->EndIndex
, true) +
1333 if (Changes
[CellIter
->Index
].NewlinesBefore
== 0) {
1334 Changes
[CellIter
->Index
].Spaces
= (CellWidth
- (ThisWidth
+ NetWidth
));
1335 Changes
[CellIter
->Index
].Spaces
+= (i
> 0) ? 1 : BracePadding
;
1337 alignToStartOfCell(CellIter
->Index
, CellIter
->EndIndex
);
1338 for (const auto *Next
= CellIter
->NextColumnElement
; Next
;
1339 Next
= Next
->NextColumnElement
) {
1341 calculateCellWidth(Next
->Index
, Next
->EndIndex
, true) + NetWidth
;
1342 if (Changes
[Next
->Index
].NewlinesBefore
== 0) {
1343 Changes
[Next
->Index
].Spaces
= (CellWidth
- ThisWidth
);
1344 Changes
[Next
->Index
].Spaces
+= (i
> 0) ? 1 : BracePadding
;
1346 alignToStartOfCell(Next
->Index
, Next
->EndIndex
);
1352 void WhitespaceManager::alignArrayInitializersLeftJustified(
1353 CellDescriptions
&&CellDescs
) {
1355 if (!CellDescs
.isRectangular())
1358 const int BracePadding
= Style
.Cpp11BracedListStyle
? 0 : 1;
1359 auto &Cells
= CellDescs
.Cells
;
1360 // Now go through and fixup the spaces.
1361 auto *CellIter
= Cells
.begin();
1362 // The first cell needs to be against the left brace.
1363 if (Changes
[CellIter
->Index
].NewlinesBefore
== 0)
1364 Changes
[CellIter
->Index
].Spaces
= BracePadding
;
1366 Changes
[CellIter
->Index
].Spaces
= CellDescs
.InitialSpaces
;
1368 for (auto i
= 1U; i
< CellDescs
.CellCounts
[0]; i
++, ++CellIter
) {
1369 auto MaxNetWidth
= getMaximumNetWidth(
1370 Cells
.begin(), CellIter
, CellDescs
.InitialSpaces
,
1371 CellDescs
.CellCounts
[0], CellDescs
.CellCounts
.size());
1373 getNetWidth(Cells
.begin(), CellIter
, CellDescs
.InitialSpaces
);
1374 if (Changes
[CellIter
->Index
].NewlinesBefore
== 0) {
1375 Changes
[CellIter
->Index
].Spaces
=
1376 MaxNetWidth
- ThisNetWidth
+
1377 (Changes
[CellIter
->Index
].Tok
->isNot(tok::r_brace
) ? 1
1381 auto Offset
= std::distance(Cells
.begin(), CellIter
);
1382 for (const auto *Next
= CellIter
->NextColumnElement
; Next
;
1383 Next
= Next
->NextColumnElement
) {
1384 if (RowCount
>= CellDescs
.CellCounts
.size())
1386 auto *Start
= (Cells
.begin() + RowCount
* CellDescs
.CellCounts
[0]);
1387 auto *End
= Start
+ Offset
;
1388 auto ThisNetWidth
= getNetWidth(Start
, End
, CellDescs
.InitialSpaces
);
1389 if (Changes
[Next
->Index
].NewlinesBefore
== 0) {
1390 Changes
[Next
->Index
].Spaces
=
1391 MaxNetWidth
- ThisNetWidth
+
1392 (Changes
[Next
->Index
].Tok
->isNot(tok::r_brace
) ? 1 : BracePadding
);
1399 bool WhitespaceManager::isSplitCell(const CellDescription
&Cell
) {
1402 for (const auto *Next
= Cell
.NextColumnElement
; Next
;
1403 Next
= Next
->NextColumnElement
) {
1410 WhitespaceManager::CellDescriptions
WhitespaceManager::getCells(unsigned Start
,
1415 SmallVector
<unsigned> CellCounts
;
1416 unsigned InitialSpaces
= 0;
1417 unsigned InitialTokenLength
= 0;
1418 unsigned EndSpaces
= 0;
1419 SmallVector
<CellDescription
> Cells
;
1420 const FormatToken
*MatchingParen
= nullptr;
1421 for (unsigned i
= Start
; i
< End
; ++i
) {
1422 auto &C
= Changes
[i
];
1423 if (C
.Tok
->is(tok::l_brace
))
1425 else if (C
.Tok
->is(tok::r_brace
))
1428 if (C
.Tok
->is(tok::l_brace
)) {
1430 MatchingParen
= C
.Tok
->MatchingParen
;
1431 if (InitialSpaces
== 0) {
1432 InitialSpaces
= C
.Spaces
+ C
.TokenLength
;
1433 InitialTokenLength
= C
.TokenLength
;
1435 for (; Changes
[j
].NewlinesBefore
== 0 && j
> Start
; --j
) {
1436 InitialSpaces
+= Changes
[j
].Spaces
+ Changes
[j
].TokenLength
;
1437 InitialTokenLength
+= Changes
[j
].TokenLength
;
1439 if (C
.NewlinesBefore
== 0) {
1440 InitialSpaces
+= Changes
[j
].Spaces
+ Changes
[j
].TokenLength
;
1441 InitialTokenLength
+= Changes
[j
].TokenLength
;
1444 } else if (C
.Tok
->is(tok::comma
)) {
1446 Cells
.back().EndIndex
= i
;
1447 if (C
.Tok
->getNextNonComment()->isNot(tok::r_brace
)) // dangling comma
1450 } else if (Depth
== 1) {
1451 if (C
.Tok
== MatchingParen
) {
1453 Cells
.back().EndIndex
= i
;
1454 Cells
.push_back(CellDescription
{i
, ++Cell
, i
+ 1, false, nullptr});
1455 CellCounts
.push_back(C
.Tok
->Previous
->isNot(tok::comma
) ? Cell
+ 1
1457 // Go to the next non-comment and ensure there is a break in front
1458 const auto *NextNonComment
= C
.Tok
->getNextNonComment();
1459 while (NextNonComment
->is(tok::comma
))
1460 NextNonComment
= NextNonComment
->getNextNonComment();
1462 while (Changes
[j
].Tok
!= NextNonComment
&& j
< End
)
1464 if (j
< End
&& Changes
[j
].NewlinesBefore
== 0 &&
1465 Changes
[j
].Tok
->isNot(tok::r_brace
)) {
1466 Changes
[j
].NewlinesBefore
= 1;
1467 // Account for the added token lengths
1468 Changes
[j
].Spaces
= InitialSpaces
- InitialTokenLength
;
1470 } else if (C
.Tok
->is(tok::comment
) && C
.Tok
->NewlinesBefore
== 0) {
1471 // Trailing comments stay at a space past the last token
1472 C
.Spaces
= Changes
[i
- 1].Tok
->is(tok::comma
) ? 1 : 2;
1473 } else if (C
.Tok
->is(tok::l_brace
)) {
1474 // We need to make sure that the ending braces is aligned to the
1475 // start of our initializer
1477 for (; j
> 0 && !Changes
[j
].Tok
->ArrayInitializerLineStart
; --j
)
1478 ; // Nothing the loop does the work
1479 EndSpaces
= Changes
[j
].Spaces
;
1481 } else if (Depth
== 0 && C
.Tok
->is(tok::r_brace
)) {
1482 C
.NewlinesBefore
= 1;
1483 C
.Spaces
= EndSpaces
;
1485 if (C
.Tok
->StartsColumn
) {
1486 // This gets us past tokens that have been split over multiple
1488 bool HasSplit
= false;
1489 if (Changes
[i
].NewlinesBefore
> 0) {
1490 // So if we split a line previously and the tail line + this token is
1491 // less then the column limit we remove the split here and just put
1492 // the column start at a space past the comma
1494 // FIXME This if branch covers the cases where the column is not
1495 // the first column. This leads to weird pathologies like the formatting
1496 // auto foo = Items{
1501 // Well if it doesn't lead to that it's indicative that the line
1502 // breaking should be revisited. Unfortunately alot of other options
1503 // interact with this
1505 if ((j
- 1) > Start
&& Changes
[j
].Tok
->is(tok::comma
) &&
1506 Changes
[j
- 1].NewlinesBefore
> 0) {
1508 auto LineLimit
= Changes
[j
].Spaces
+ Changes
[j
].TokenLength
;
1509 if (LineLimit
< Style
.ColumnLimit
) {
1510 Changes
[i
].NewlinesBefore
= 0;
1511 Changes
[i
].Spaces
= 1;
1515 while (Changes
[i
].NewlinesBefore
> 0 && Changes
[i
].Tok
== C
.Tok
) {
1516 Changes
[i
].Spaces
= InitialSpaces
;
1520 if (Changes
[i
].Tok
!= C
.Tok
)
1522 Cells
.push_back(CellDescription
{i
, Cell
, i
, HasSplit
, nullptr});
1526 return linkCells({Cells
, CellCounts
, InitialSpaces
});
1529 unsigned WhitespaceManager::calculateCellWidth(unsigned Start
, unsigned End
,
1530 bool WithSpaces
) const {
1531 unsigned CellWidth
= 0;
1532 for (auto i
= Start
; i
< End
; i
++) {
1533 if (Changes
[i
].NewlinesBefore
> 0)
1535 CellWidth
+= Changes
[i
].TokenLength
;
1536 CellWidth
+= (WithSpaces
? Changes
[i
].Spaces
: 0);
1541 void WhitespaceManager::alignToStartOfCell(unsigned Start
, unsigned End
) {
1542 if ((End
- Start
) <= 1)
1544 // If the line is broken anywhere in there make sure everything
1545 // is aligned to the parent
1546 for (auto i
= Start
+ 1; i
< End
; i
++)
1547 if (Changes
[i
].NewlinesBefore
> 0)
1548 Changes
[i
].Spaces
= Changes
[Start
].Spaces
;
1551 WhitespaceManager::CellDescriptions
1552 WhitespaceManager::linkCells(CellDescriptions
&&CellDesc
) {
1553 auto &Cells
= CellDesc
.Cells
;
1554 for (auto *CellIter
= Cells
.begin(); CellIter
!= Cells
.end(); ++CellIter
) {
1555 if (!CellIter
->NextColumnElement
&& (CellIter
+ 1) != Cells
.end()) {
1556 for (auto *NextIter
= CellIter
+ 1; NextIter
!= Cells
.end(); ++NextIter
) {
1557 if (NextIter
->Cell
== CellIter
->Cell
) {
1558 CellIter
->NextColumnElement
= &(*NextIter
);
1564 return std::move(CellDesc
);
1567 void WhitespaceManager::generateChanges() {
1568 for (unsigned i
= 0, e
= Changes
.size(); i
!= e
; ++i
) {
1569 const Change
&C
= Changes
[i
];
1571 auto Last
= Changes
[i
- 1].OriginalWhitespaceRange
;
1572 auto New
= Changes
[i
].OriginalWhitespaceRange
;
1573 // Do not generate two replacements for the same location. As a special
1574 // case, it is allowed if there is a replacement for the empty range
1575 // between 2 tokens and another non-empty range at the start of the second
1576 // token. We didn't implement logic to combine replacements for 2
1577 // consecutive source ranges into a single replacement, because the
1578 // program works fine without it.
1580 // We can't eliminate empty original whitespace ranges. They appear when
1581 // 2 tokens have no whitespace in between in the input. It does not
1582 // matter whether whitespace is to be added. If no whitespace is to be
1583 // added, the replacement will be empty, and it gets eliminated after this
1584 // step in storeReplacement. For example, if the input is `foo();`,
1585 // there will be a replacement for the range between every consecutive
1588 // A replacement at the start of a token can be added by
1589 // BreakableStringLiteralUsingOperators::insertBreak when it adds braces
1590 // around the string literal. Say Verilog code is being formatted and the
1591 // first line is to become the next 2 lines.
1592 // x("long string");
1595 // There will be a replacement for the empty range between the parenthesis
1596 // and the string and another replacement for the quote character. The
1597 // replacement for the empty range between the parenthesis and the quote
1598 // comes from ContinuationIndenter::addTokenOnCurrentLine when it changes
1599 // the original empty range between the parenthesis and the string to
1600 // another empty one. The replacement for the quote character comes from
1601 // BreakableStringLiteralUsingOperators::insertBreak when it adds the
1602 // brace. In the example, the replacement for the empty range is the same
1603 // as the original text. However, eliminating replacements that are same
1604 // as the original does not help in general. For example, a newline can
1605 // be inserted, causing the first line to become the next 3 lines.
1606 // xxxxxxxxxxx("long string");
1610 // In that case, the empty range between the parenthesis and the string
1611 // will be replaced by a newline and 4 spaces. So we will still have to
1612 // deal with a replacement for an empty source range followed by a
1613 // replacement for a non-empty source range.
1614 if (Last
.getBegin() == New
.getBegin() &&
1615 (Last
.getEnd() != Last
.getBegin() ||
1616 New
.getEnd() == New
.getBegin())) {
1620 if (C
.CreateReplacement
) {
1621 std::string ReplacementText
= C
.PreviousLinePostfix
;
1622 if (C
.ContinuesPPDirective
) {
1623 appendEscapedNewlineText(ReplacementText
, C
.NewlinesBefore
,
1624 C
.PreviousEndOfTokenColumn
,
1625 C
.EscapedNewlineColumn
);
1627 appendNewlineText(ReplacementText
, C
.NewlinesBefore
);
1629 // FIXME: This assert should hold if we computed the column correctly.
1630 // assert((int)C.StartOfTokenColumn >= C.Spaces);
1632 ReplacementText
, C
.Tok
->IndentLevel
, std::max(0, C
.Spaces
),
1633 std::max((int)C
.StartOfTokenColumn
, C
.Spaces
) - std::max(0, C
.Spaces
),
1635 ReplacementText
.append(C
.CurrentLinePrefix
);
1636 storeReplacement(C
.OriginalWhitespaceRange
, ReplacementText
);
1641 void WhitespaceManager::storeReplacement(SourceRange Range
, StringRef Text
) {
1642 unsigned WhitespaceLength
= SourceMgr
.getFileOffset(Range
.getEnd()) -
1643 SourceMgr
.getFileOffset(Range
.getBegin());
1644 // Don't create a replacement, if it does not change anything.
1645 if (StringRef(SourceMgr
.getCharacterData(Range
.getBegin()),
1646 WhitespaceLength
) == Text
) {
1649 auto Err
= Replaces
.add(tooling::Replacement(
1650 SourceMgr
, CharSourceRange::getCharRange(Range
), Text
));
1651 // FIXME: better error handling. For now, just print an error message in the
1654 llvm::errs() << llvm::toString(std::move(Err
)) << "\n";
1659 void WhitespaceManager::appendNewlineText(std::string
&Text
,
1660 unsigned Newlines
) {
1662 Text
.reserve(Text
.size() + 2 * Newlines
);
1663 for (unsigned i
= 0; i
< Newlines
; ++i
)
1664 Text
.append("\r\n");
1666 Text
.append(Newlines
, '\n');
1670 void WhitespaceManager::appendEscapedNewlineText(
1671 std::string
&Text
, unsigned Newlines
, unsigned PreviousEndOfTokenColumn
,
1672 unsigned EscapedNewlineColumn
) {
1675 std::max
<int>(1, EscapedNewlineColumn
- PreviousEndOfTokenColumn
- 1);
1676 for (unsigned i
= 0; i
< Newlines
; ++i
) {
1677 Text
.append(Spaces
, ' ');
1678 Text
.append(UseCRLF
? "\\\r\n" : "\\\n");
1679 Spaces
= std::max
<int>(0, EscapedNewlineColumn
- 1);
1684 void WhitespaceManager::appendIndentText(std::string
&Text
,
1685 unsigned IndentLevel
, unsigned Spaces
,
1686 unsigned WhitespaceStartColumn
,
1688 switch (Style
.UseTab
) {
1689 case FormatStyle::UT_Never
:
1690 Text
.append(Spaces
, ' ');
1692 case FormatStyle::UT_Always
: {
1693 if (Style
.TabWidth
) {
1694 unsigned FirstTabWidth
=
1695 Style
.TabWidth
- WhitespaceStartColumn
% Style
.TabWidth
;
1697 // Insert only spaces when we want to end up before the next tab.
1698 if (Spaces
< FirstTabWidth
|| Spaces
== 1) {
1699 Text
.append(Spaces
, ' ');
1702 // Align to the next tab.
1703 Spaces
-= FirstTabWidth
;
1706 Text
.append(Spaces
/ Style
.TabWidth
, '\t');
1707 Text
.append(Spaces
% Style
.TabWidth
, ' ');
1708 } else if (Spaces
== 1) {
1709 Text
.append(Spaces
, ' ');
1713 case FormatStyle::UT_ForIndentation
:
1714 if (WhitespaceStartColumn
== 0) {
1715 unsigned Indentation
= IndentLevel
* Style
.IndentWidth
;
1716 Spaces
= appendTabIndent(Text
, Spaces
, Indentation
);
1718 Text
.append(Spaces
, ' ');
1720 case FormatStyle::UT_ForContinuationAndIndentation
:
1721 if (WhitespaceStartColumn
== 0)
1722 Spaces
= appendTabIndent(Text
, Spaces
, Spaces
);
1723 Text
.append(Spaces
, ' ');
1725 case FormatStyle::UT_AlignWithSpaces
:
1726 if (WhitespaceStartColumn
== 0) {
1727 unsigned Indentation
=
1728 IsAligned
? IndentLevel
* Style
.IndentWidth
: Spaces
;
1729 Spaces
= appendTabIndent(Text
, Spaces
, Indentation
);
1731 Text
.append(Spaces
, ' ');
1736 unsigned WhitespaceManager::appendTabIndent(std::string
&Text
, unsigned Spaces
,
1737 unsigned Indentation
) {
1738 // This happens, e.g. when a line in a block comment is indented less than the
1740 if (Indentation
> Spaces
)
1741 Indentation
= Spaces
;
1742 if (Style
.TabWidth
) {
1743 unsigned Tabs
= Indentation
/ Style
.TabWidth
;
1744 Text
.append(Tabs
, '\t');
1745 Spaces
-= Tabs
* Style
.TabWidth
;
1750 } // namespace format
1751 } // namespace clang