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
;
474 Changes
[Previous
].Tok
->isOneOf(tok::star
, tok::amp
, tok::ampamp
));
475 if (Changes
[Previous
].Tok
->isNot(tok::star
)) {
476 if (ReferenceNotRightAligned
)
478 } else if (Style
.PointerAlignment
!= FormatStyle::PAS_Right
) {
481 Changes
[Previous
+ 1].Spaces
-= Shift
;
482 Changes
[Previous
].Spaces
+= Shift
;
483 Changes
[Previous
].StartOfTokenColumn
+= Shift
;
489 // Walk through a subset of the changes, starting at StartAt, and find
490 // sequences of matching tokens to align. To do so, keep track of the lines and
491 // whether or not a matching token was found on a line. If a matching token is
492 // found, extend the current sequence. If the current line cannot be part of a
493 // sequence, e.g. because there is an empty line before it or it contains only
494 // non-matching tokens, finalize the previous sequence.
495 // The value returned is the token on which we stopped, either because we
496 // exhausted all items inside Changes, or because we hit a scope level higher
497 // than our initial scope.
498 // This function is recursive. Each invocation processes only the scope level
499 // equal to the initial level, which is the level of Changes[StartAt].
500 // If we encounter a scope level greater than the initial level, then we call
501 // ourselves recursively, thereby avoiding the pollution of the current state
502 // with the alignment requirements of the nested sub-level. This recursive
503 // behavior is necessary for aligning function prototypes that have one or more
505 // If this function encounters a scope level less than the initial level,
506 // it returns the current position.
507 // There is a non-obvious subtlety in the recursive behavior: Even though we
508 // defer processing of nested levels to recursive invocations of this
509 // function, when it comes time to align a sequence of tokens, we run the
510 // alignment on the entire sequence, including the nested levels.
511 // When doing so, most of the nested tokens are skipped, because their
512 // alignment was already handled by the recursive invocations of this function.
513 // However, the special exception is that we do NOT skip function parameters
514 // that are split across multiple lines. See the test case in FormatTest.cpp
515 // that mentions "split function parameter alignment" for an example of this.
516 // When the parameter RightJustify is true, the operator will be
517 // right-justified. It is used to align compound assignments like `+=` and `=`.
518 // When RightJustify and ACS.PadOperators are true, operators in each block to
519 // be aligned will be padded on the left to the same length before aligning.
520 template <typename F
>
521 static unsigned AlignTokens(const FormatStyle
&Style
, F
&&Matches
,
522 SmallVector
<WhitespaceManager::Change
, 16> &Changes
,
524 const FormatStyle::AlignConsecutiveStyle
&ACS
= {},
525 bool RightJustify
= false) {
526 // We arrange each line in 3 parts. The operator to be aligned (the anchor),
527 // and text to its left and right. In the aligned text the width of each part
528 // will be the maximum of that over the block that has been aligned. Maximum
529 // widths of each part so far. When RightJustify is true and ACS.PadOperators
530 // is false, the part from start of line to the right end of the anchor.
531 // Otherwise, only the part to the left of the anchor. Including the space
532 // that exists on its left from the start. Not including the padding added on
533 // the left to right-justify the anchor.
534 unsigned WidthLeft
= 0;
535 // The operator to be aligned when RightJustify is true and ACS.PadOperators
536 // is false. 0 otherwise.
537 unsigned WidthAnchor
= 0;
538 // Width to the right of the anchor. Plus width of the anchor when
539 // RightJustify is false.
540 unsigned WidthRight
= 0;
542 // Line number of the start and the end of the current token sequence.
543 unsigned StartOfSequence
= 0;
544 unsigned EndOfSequence
= 0;
546 // Measure the scope level (i.e. depth of (), [], {}) of the first token, and
547 // abort when we hit any token in a higher scope than the starting one.
548 auto IndentAndNestingLevel
= StartAt
< Changes
.size()
549 ? Changes
[StartAt
].indentAndNestingLevel()
550 : std::tuple
<unsigned, unsigned, unsigned>();
552 // Keep track of the number of commas before the matching tokens, we will only
553 // align a sequence of matching tokens if they are preceded by the same number
555 unsigned CommasBeforeLastMatch
= 0;
556 unsigned CommasBeforeMatch
= 0;
558 // Whether a matching token has been found on the current line.
559 bool FoundMatchOnLine
= false;
561 // Whether the current line consists purely of comments.
562 bool LineIsComment
= true;
564 // Aligns a sequence of matching tokens, on the MinColumn column.
566 // Sequences start from the first matching token to align, and end at the
567 // first token of the first line that doesn't need to be aligned.
569 // We need to adjust the StartOfTokenColumn of each Change that is on a line
570 // containing any matching token to be aligned and located after such token.
571 auto AlignCurrentSequence
= [&] {
572 if (StartOfSequence
> 0 && StartOfSequence
< EndOfSequence
) {
573 AlignTokenSequence(Style
, StartOfSequence
, EndOfSequence
,
574 WidthLeft
+ WidthAnchor
, RightJustify
, Matches
,
584 unsigned i
= StartAt
;
585 for (unsigned e
= Changes
.size(); i
!= e
; ++i
) {
586 auto &CurrentChange
= Changes
[i
];
587 if (CurrentChange
.indentAndNestingLevel() < IndentAndNestingLevel
)
590 if (CurrentChange
.NewlinesBefore
!= 0) {
591 CommasBeforeMatch
= 0;
594 // Whether to break the alignment sequence because of an empty line.
595 bool EmptyLineBreak
=
596 (CurrentChange
.NewlinesBefore
> 1) && !ACS
.AcrossEmptyLines
;
598 // Whether to break the alignment sequence because of a line without a
601 !FoundMatchOnLine
&& !(LineIsComment
&& ACS
.AcrossComments
);
603 if (EmptyLineBreak
|| NoMatchBreak
)
604 AlignCurrentSequence();
606 // A new line starts, re-initialize line status tracking bools.
607 // Keep the match state if a string literal is continued on this line.
608 if (i
== 0 || CurrentChange
.Tok
->isNot(tok::string_literal
) ||
609 Changes
[i
- 1].Tok
->isNot(tok::string_literal
)) {
610 FoundMatchOnLine
= false;
612 LineIsComment
= true;
615 if (CurrentChange
.Tok
->isNot(tok::comment
))
616 LineIsComment
= false;
618 if (CurrentChange
.Tok
->is(tok::comma
)) {
620 } else if (CurrentChange
.indentAndNestingLevel() > IndentAndNestingLevel
) {
621 // Call AlignTokens recursively, skipping over this scope block.
623 AlignTokens(Style
, Matches
, Changes
, i
, ACS
, RightJustify
);
628 if (!Matches(CurrentChange
))
631 // If there is more than one matching token per line, or if the number of
632 // preceding commas, do not match anymore, end the sequence.
633 if (FoundMatchOnLine
|| CommasBeforeMatch
!= CommasBeforeLastMatch
)
634 AlignCurrentSequence();
636 CommasBeforeLastMatch
= CommasBeforeMatch
;
637 FoundMatchOnLine
= true;
639 if (StartOfSequence
== 0)
642 unsigned ChangeWidthLeft
= CurrentChange
.StartOfTokenColumn
;
643 unsigned ChangeWidthAnchor
= 0;
644 unsigned ChangeWidthRight
= 0;
646 if (ACS
.PadOperators
)
647 ChangeWidthAnchor
= CurrentChange
.TokenLength
;
649 ChangeWidthLeft
+= CurrentChange
.TokenLength
;
651 ChangeWidthRight
= CurrentChange
.TokenLength
;
652 for (unsigned j
= i
+ 1; j
!= e
&& Changes
[j
].NewlinesBefore
== 0; ++j
) {
653 ChangeWidthRight
+= Changes
[j
].Spaces
;
654 // Changes are generally 1:1 with the tokens, but a change could also be
655 // inside of a token, in which case it's counted more than once: once for
656 // the whitespace surrounding the token (!IsInsideToken) and once for
657 // each whitespace change within it (IsInsideToken).
658 // Therefore, changes inside of a token should only count the space.
659 if (!Changes
[j
].IsInsideToken
)
660 ChangeWidthRight
+= Changes
[j
].TokenLength
;
663 // If we are restricted by the maximum column width, end the sequence.
664 unsigned NewLeft
= std::max(ChangeWidthLeft
, WidthLeft
);
665 unsigned NewAnchor
= std::max(ChangeWidthAnchor
, WidthAnchor
);
666 unsigned NewRight
= std::max(ChangeWidthRight
, WidthRight
);
667 // `ColumnLimit == 0` means there is no column limit.
668 if (Style
.ColumnLimit
!= 0 &&
669 Style
.ColumnLimit
< NewLeft
+ NewAnchor
+ NewRight
) {
670 AlignCurrentSequence();
672 WidthLeft
= ChangeWidthLeft
;
673 WidthAnchor
= ChangeWidthAnchor
;
674 WidthRight
= ChangeWidthRight
;
677 WidthAnchor
= NewAnchor
;
678 WidthRight
= NewRight
;
683 AlignCurrentSequence();
687 // Aligns a sequence of matching tokens, on the MinColumn column.
689 // Sequences start from the first matching token to align, and end at the
690 // first token of the first line that doesn't need to be aligned.
692 // We need to adjust the StartOfTokenColumn of each Change that is on a line
693 // containing any matching token to be aligned and located after such token.
694 static void AlignMatchingTokenSequence(
695 unsigned &StartOfSequence
, unsigned &EndOfSequence
, unsigned &MinColumn
,
696 std::function
<bool(const WhitespaceManager::Change
&C
)> Matches
,
697 SmallVector
<WhitespaceManager::Change
, 16> &Changes
) {
698 if (StartOfSequence
> 0 && StartOfSequence
< EndOfSequence
) {
699 bool FoundMatchOnLine
= false;
702 for (unsigned I
= StartOfSequence
; I
!= EndOfSequence
; ++I
) {
703 if (Changes
[I
].NewlinesBefore
> 0) {
705 FoundMatchOnLine
= false;
708 // If this is the first matching token to be aligned, remember by how many
709 // spaces it has to be shifted, so the rest of the changes on the line are
710 // shifted by the same amount.
711 if (!FoundMatchOnLine
&& Matches(Changes
[I
])) {
712 FoundMatchOnLine
= true;
713 Shift
= MinColumn
- Changes
[I
].StartOfTokenColumn
;
714 Changes
[I
].Spaces
+= Shift
;
718 Changes
[I
].StartOfTokenColumn
+= Shift
;
719 if (I
+ 1 != Changes
.size())
720 Changes
[I
+ 1].PreviousEndOfTokenColumn
+= Shift
;
729 void WhitespaceManager::alignConsecutiveMacros() {
730 if (!Style
.AlignConsecutiveMacros
.Enabled
)
733 auto AlignMacrosMatches
= [](const Change
&C
) {
734 const FormatToken
*Current
= C
.Tok
;
735 unsigned SpacesRequiredBefore
= 1;
737 if (Current
->SpacesRequiredBefore
== 0 || !Current
->Previous
)
740 Current
= Current
->Previous
;
742 // If token is a ")", skip over the parameter list, to the
743 // token that precedes the "("
744 if (Current
->is(tok::r_paren
) && Current
->MatchingParen
) {
745 Current
= Current
->MatchingParen
->Previous
;
746 SpacesRequiredBefore
= 0;
749 if (!Current
|| Current
->isNot(tok::identifier
))
752 if (!Current
->Previous
|| Current
->Previous
->isNot(tok::pp_define
))
755 // For a macro function, 0 spaces are required between the
756 // identifier and the lparen that opens the parameter list.
757 // For a simple macro, 1 space is required between the
758 // identifier and the first token of the defined value.
759 return Current
->Next
->SpacesRequiredBefore
== SpacesRequiredBefore
;
762 unsigned MinColumn
= 0;
764 // Start and end of the token sequence we're processing.
765 unsigned StartOfSequence
= 0;
766 unsigned EndOfSequence
= 0;
768 // Whether a matching token has been found on the current line.
769 bool FoundMatchOnLine
= false;
771 // Whether the current line consists only of comments
772 bool LineIsComment
= true;
775 for (unsigned E
= Changes
.size(); I
!= E
; ++I
) {
776 if (Changes
[I
].NewlinesBefore
!= 0) {
779 // Whether to break the alignment sequence because of an empty line.
780 bool EmptyLineBreak
= (Changes
[I
].NewlinesBefore
> 1) &&
781 !Style
.AlignConsecutiveMacros
.AcrossEmptyLines
;
783 // Whether to break the alignment sequence because of a line without a
787 !(LineIsComment
&& Style
.AlignConsecutiveMacros
.AcrossComments
);
789 if (EmptyLineBreak
|| NoMatchBreak
) {
790 AlignMatchingTokenSequence(StartOfSequence
, EndOfSequence
, MinColumn
,
791 AlignMacrosMatches
, Changes
);
794 // A new line starts, re-initialize line status tracking bools.
795 FoundMatchOnLine
= false;
796 LineIsComment
= true;
799 if (Changes
[I
].Tok
->isNot(tok::comment
))
800 LineIsComment
= false;
802 if (!AlignMacrosMatches(Changes
[I
]))
805 FoundMatchOnLine
= true;
807 if (StartOfSequence
== 0)
810 unsigned ChangeMinColumn
= Changes
[I
].StartOfTokenColumn
;
811 MinColumn
= std::max(MinColumn
, ChangeMinColumn
);
815 AlignMatchingTokenSequence(StartOfSequence
, EndOfSequence
, MinColumn
,
816 AlignMacrosMatches
, Changes
);
819 void WhitespaceManager::alignConsecutiveAssignments() {
820 if (!Style
.AlignConsecutiveAssignments
.Enabled
)
825 [&](const Change
&C
) {
826 // Do not align on equal signs that are first on a line.
827 if (C
.NewlinesBefore
> 0)
830 // Do not align on equal signs that are last on a line.
831 if (&C
!= &Changes
.back() && (&C
+ 1)->NewlinesBefore
> 0)
834 // Do not align operator= overloads.
835 FormatToken
*Previous
= C
.Tok
->getPreviousNonComment();
836 if (Previous
&& Previous
->is(tok::kw_operator
))
839 return Style
.AlignConsecutiveAssignments
.AlignCompound
840 ? C
.Tok
->getPrecedence() == prec::Assignment
841 : (C
.Tok
->is(tok::equal
) ||
842 // In Verilog the '<=' is not a compound assignment, thus
843 // it is aligned even when the AlignCompound option is not
845 (Style
.isVerilog() && C
.Tok
->is(tok::lessequal
) &&
846 C
.Tok
->getPrecedence() == prec::Assignment
));
848 Changes
, /*StartAt=*/0, Style
.AlignConsecutiveAssignments
,
849 /*RightJustify=*/true);
852 void WhitespaceManager::alignConsecutiveBitFields() {
853 if (!Style
.AlignConsecutiveBitFields
.Enabled
)
858 [&](Change
const &C
) {
859 // Do not align on ':' that is first on a line.
860 if (C
.NewlinesBefore
> 0)
863 // Do not align on ':' that is last on a line.
864 if (&C
!= &Changes
.back() && (&C
+ 1)->NewlinesBefore
> 0)
867 return C
.Tok
->is(TT_BitFieldColon
);
869 Changes
, /*StartAt=*/0, Style
.AlignConsecutiveBitFields
);
872 void WhitespaceManager::alignConsecutiveShortCaseStatements() {
873 if (!Style
.AlignConsecutiveShortCaseStatements
.Enabled
||
874 !Style
.AllowShortCaseLabelsOnASingleLine
) {
878 auto Matches
= [&](const Change
&C
) {
879 if (Style
.AlignConsecutiveShortCaseStatements
.AlignCaseColons
)
880 return C
.Tok
->is(TT_CaseLabelColon
);
882 // Ignore 'IsInsideToken' to allow matching trailing comments which
883 // need to be reflowed as that causes the token to appear in two
884 // different changes, which will cause incorrect alignment as we'll
885 // reflow early due to detecting multiple aligning tokens per line.
886 return !C
.IsInsideToken
&& C
.Tok
->Previous
&&
887 C
.Tok
->Previous
->is(TT_CaseLabelColon
);
890 unsigned MinColumn
= 0;
892 // Empty case statements don't break the alignment, but don't necessarily
893 // match our predicate, so we need to track their column so they can push out
895 unsigned MinEmptyCaseColumn
= 0;
897 // Start and end of the token sequence we're processing.
898 unsigned StartOfSequence
= 0;
899 unsigned EndOfSequence
= 0;
901 // Whether a matching token has been found on the current line.
902 bool FoundMatchOnLine
= false;
904 bool LineIsComment
= true;
905 bool LineIsEmptyCase
= false;
908 for (unsigned E
= Changes
.size(); I
!= E
; ++I
) {
909 if (Changes
[I
].NewlinesBefore
!= 0) {
910 // Whether to break the alignment sequence because of an empty line.
911 bool EmptyLineBreak
=
912 (Changes
[I
].NewlinesBefore
> 1) &&
913 !Style
.AlignConsecutiveShortCaseStatements
.AcrossEmptyLines
;
915 // Whether to break the alignment sequence because of a line without a
920 Style
.AlignConsecutiveShortCaseStatements
.AcrossComments
) &&
923 if (EmptyLineBreak
|| NoMatchBreak
) {
924 AlignMatchingTokenSequence(StartOfSequence
, EndOfSequence
, MinColumn
,
926 MinEmptyCaseColumn
= 0;
929 // A new line starts, re-initialize line status tracking bools.
930 FoundMatchOnLine
= false;
931 LineIsComment
= true;
932 LineIsEmptyCase
= false;
935 if (Changes
[I
].Tok
->isNot(tok::comment
))
936 LineIsComment
= false;
938 if (Changes
[I
].Tok
->is(TT_CaseLabelColon
)) {
940 !Changes
[I
].Tok
->Next
|| Changes
[I
].Tok
->Next
->isTrailingComment();
942 if (LineIsEmptyCase
) {
943 if (Style
.AlignConsecutiveShortCaseStatements
.AlignCaseColons
) {
945 std::max(MinEmptyCaseColumn
, Changes
[I
].StartOfTokenColumn
);
948 std::max(MinEmptyCaseColumn
, Changes
[I
].StartOfTokenColumn
+ 2);
953 if (!Matches(Changes
[I
]))
959 FoundMatchOnLine
= true;
961 if (StartOfSequence
== 0)
964 EndOfSequence
= I
+ 1;
966 MinColumn
= std::max(MinColumn
, Changes
[I
].StartOfTokenColumn
);
968 // Allow empty case statements to push out our alignment.
969 MinColumn
= std::max(MinColumn
, MinEmptyCaseColumn
);
972 AlignMatchingTokenSequence(StartOfSequence
, EndOfSequence
, MinColumn
, Matches
,
976 void WhitespaceManager::alignConsecutiveDeclarations() {
977 if (!Style
.AlignConsecutiveDeclarations
.Enabled
)
982 [](Change
const &C
) {
983 if (C
.Tok
->is(TT_FunctionDeclarationName
))
985 if (C
.Tok
->isNot(TT_StartOfName
))
987 if (C
.Tok
->Previous
&&
988 C
.Tok
->Previous
->is(TT_StatementAttributeLikeMacro
))
990 // Check if there is a subsequent name that starts the same declaration.
991 for (FormatToken
*Next
= C
.Tok
->Next
; Next
; Next
= Next
->Next
) {
992 if (Next
->is(tok::comment
))
994 if (Next
->is(TT_PointerOrReference
))
996 if (!Next
->Tok
.getIdentifierInfo())
998 if (Next
->isOneOf(TT_StartOfName
, TT_FunctionDeclarationName
,
1005 Changes
, /*StartAt=*/0, Style
.AlignConsecutiveDeclarations
);
1008 void WhitespaceManager::alignChainedConditionals() {
1009 if (Style
.BreakBeforeTernaryOperators
) {
1012 [](Change
const &C
) {
1013 // Align question operators and last colon
1014 return C
.Tok
->is(TT_ConditionalExpr
) &&
1015 ((C
.Tok
->is(tok::question
) && !C
.NewlinesBefore
) ||
1016 (C
.Tok
->is(tok::colon
) && C
.Tok
->Next
&&
1017 (C
.Tok
->Next
->FakeLParens
.size() == 0 ||
1018 C
.Tok
->Next
->FakeLParens
.back() != prec::Conditional
)));
1020 Changes
, /*StartAt=*/0);
1022 static auto AlignWrappedOperand
= [](Change
const &C
) {
1023 FormatToken
*Previous
= C
.Tok
->getPreviousNonComment();
1024 return C
.NewlinesBefore
&& Previous
&& Previous
->is(TT_ConditionalExpr
) &&
1025 (Previous
->is(tok::colon
) &&
1026 (C
.Tok
->FakeLParens
.size() == 0 ||
1027 C
.Tok
->FakeLParens
.back() != prec::Conditional
));
1029 // Ensure we keep alignment of wrapped operands with non-wrapped operands
1030 // Since we actually align the operators, the wrapped operands need the
1031 // extra offset to be properly aligned.
1032 for (Change
&C
: Changes
)
1033 if (AlignWrappedOperand(C
))
1034 C
.StartOfTokenColumn
-= 2;
1037 [this](Change
const &C
) {
1038 // Align question operators if next operand is not wrapped, as
1039 // well as wrapped operands after question operator or last
1040 // colon in conditional sequence
1041 return (C
.Tok
->is(TT_ConditionalExpr
) && C
.Tok
->is(tok::question
) &&
1042 &C
!= &Changes
.back() && (&C
+ 1)->NewlinesBefore
== 0 &&
1043 !(&C
+ 1)->IsTrailingComment
) ||
1044 AlignWrappedOperand(C
);
1046 Changes
, /*StartAt=*/0);
1050 void WhitespaceManager::alignTrailingComments() {
1051 if (Style
.AlignTrailingComments
.Kind
== FormatStyle::TCAS_Never
)
1054 const int Size
= Changes
.size();
1056 int StartOfSequence
= 0;
1057 bool BreakBeforeNext
= false;
1058 int NewLineThreshold
= 1;
1059 if (Style
.AlignTrailingComments
.Kind
== FormatStyle::TCAS_Always
)
1060 NewLineThreshold
= Style
.AlignTrailingComments
.OverEmptyLines
+ 1;
1062 for (int I
= 0, MaxColumn
= INT_MAX
, Newlines
= 0; I
< Size
; ++I
) {
1063 auto &C
= Changes
[I
];
1064 if (C
.StartOfBlockComment
)
1066 Newlines
+= C
.NewlinesBefore
;
1067 if (!C
.IsTrailingComment
)
1070 if (Style
.AlignTrailingComments
.Kind
== FormatStyle::TCAS_Leave
) {
1071 const int OriginalSpaces
=
1072 C
.OriginalWhitespaceRange
.getEnd().getRawEncoding() -
1073 C
.OriginalWhitespaceRange
.getBegin().getRawEncoding() -
1074 C
.Tok
->LastNewlineOffset
;
1075 assert(OriginalSpaces
>= 0);
1076 const auto RestoredLineLength
=
1077 C
.StartOfTokenColumn
+ C
.TokenLength
+ OriginalSpaces
;
1078 // If leaving comments makes the line exceed the column limit, give up to
1079 // leave the comments.
1080 if (RestoredLineLength
>= Style
.ColumnLimit
&& Style
.ColumnLimit
> 0)
1082 C
.Spaces
= OriginalSpaces
;
1086 const int ChangeMinColumn
= C
.StartOfTokenColumn
;
1087 int ChangeMaxColumn
;
1089 // If we don't create a replacement for this change, we have to consider
1090 // it to be immovable.
1091 if (!C
.CreateReplacement
)
1092 ChangeMaxColumn
= ChangeMinColumn
;
1093 else if (Style
.ColumnLimit
== 0)
1094 ChangeMaxColumn
= INT_MAX
;
1095 else if (Style
.ColumnLimit
>= C
.TokenLength
)
1096 ChangeMaxColumn
= Style
.ColumnLimit
- C
.TokenLength
;
1098 ChangeMaxColumn
= ChangeMinColumn
;
1100 if (I
+ 1 < Size
&& Changes
[I
+ 1].ContinuesPPDirective
&&
1101 ChangeMaxColumn
>= 2) {
1102 ChangeMaxColumn
-= 2;
1105 bool WasAlignedWithStartOfNextLine
= false;
1106 if (C
.NewlinesBefore
>= 1) { // A comment on its own line.
1107 const auto CommentColumn
=
1108 SourceMgr
.getSpellingColumnNumber(C
.OriginalWhitespaceRange
.getEnd());
1109 for (int J
= I
+ 1; J
< Size
; ++J
) {
1110 if (Changes
[J
].Tok
->is(tok::comment
))
1113 const auto NextColumn
= SourceMgr
.getSpellingColumnNumber(
1114 Changes
[J
].OriginalWhitespaceRange
.getEnd());
1115 // The start of the next token was previously aligned with the
1116 // start of this comment.
1117 WasAlignedWithStartOfNextLine
=
1118 CommentColumn
== NextColumn
||
1119 CommentColumn
== NextColumn
+ Style
.IndentWidth
;
1124 // We don't want to align comments which end a scope, which are here
1125 // identified by most closing braces.
1126 auto DontAlignThisComment
= [](const auto *Tok
) {
1127 if (Tok
->is(tok::semi
)) {
1128 Tok
= Tok
->getPreviousNonComment();
1132 if (Tok
->is(tok::r_paren
)) {
1133 // Back up past the parentheses and a `TT_DoWhile` that may precede.
1134 Tok
= Tok
->MatchingParen
;
1137 Tok
= Tok
->getPreviousNonComment();
1140 if (Tok
->is(TT_DoWhile
)) {
1141 const auto *Prev
= Tok
->getPreviousNonComment();
1143 // A do-while-loop without braces.
1150 if (Tok
->isNot(tok::r_brace
))
1153 while (Tok
->Previous
&& Tok
->Previous
->is(tok::r_brace
))
1154 Tok
= Tok
->Previous
;
1155 return Tok
->NewlinesBefore
> 0;
1158 if (I
> 0 && C
.NewlinesBefore
== 0 &&
1159 DontAlignThisComment(Changes
[I
- 1].Tok
)) {
1160 alignTrailingComments(StartOfSequence
, I
, MinColumn
);
1161 // Reset to initial values, but skip this change for the next alignment
1164 MaxColumn
= INT_MAX
;
1165 StartOfSequence
= I
+ 1;
1166 } else if (BreakBeforeNext
|| Newlines
> NewLineThreshold
||
1167 (ChangeMinColumn
> MaxColumn
|| ChangeMaxColumn
< MinColumn
) ||
1168 // Break the comment sequence if the previous line did not end
1169 // in a trailing comment.
1170 (C
.NewlinesBefore
== 1 && I
> 0 &&
1171 !Changes
[I
- 1].IsTrailingComment
) ||
1172 WasAlignedWithStartOfNextLine
) {
1173 alignTrailingComments(StartOfSequence
, I
, MinColumn
);
1174 MinColumn
= ChangeMinColumn
;
1175 MaxColumn
= ChangeMaxColumn
;
1176 StartOfSequence
= I
;
1178 MinColumn
= std::max(MinColumn
, ChangeMinColumn
);
1179 MaxColumn
= std::min(MaxColumn
, ChangeMaxColumn
);
1181 BreakBeforeNext
= (I
== 0) || (C
.NewlinesBefore
> 1) ||
1182 // Never start a sequence with a comment at the beginning
1184 (C
.NewlinesBefore
== 1 && StartOfSequence
== I
);
1187 alignTrailingComments(StartOfSequence
, Size
, MinColumn
);
1190 void WhitespaceManager::alignTrailingComments(unsigned Start
, unsigned End
,
1192 for (unsigned i
= Start
; i
!= End
; ++i
) {
1194 if (Changes
[i
].IsTrailingComment
)
1195 Shift
= Column
- Changes
[i
].StartOfTokenColumn
;
1196 if (Changes
[i
].StartOfBlockComment
) {
1197 Shift
= Changes
[i
].IndentationOffset
+
1198 Changes
[i
].StartOfBlockComment
->StartOfTokenColumn
-
1199 Changes
[i
].StartOfTokenColumn
;
1203 Changes
[i
].Spaces
+= Shift
;
1204 if (i
+ 1 != Changes
.size())
1205 Changes
[i
+ 1].PreviousEndOfTokenColumn
+= Shift
;
1206 Changes
[i
].StartOfTokenColumn
+= Shift
;
1210 void WhitespaceManager::alignEscapedNewlines() {
1211 if (Style
.AlignEscapedNewlines
== FormatStyle::ENAS_DontAlign
)
1214 bool AlignLeft
= Style
.AlignEscapedNewlines
== FormatStyle::ENAS_Left
;
1215 unsigned MaxEndOfLine
= AlignLeft
? 0 : Style
.ColumnLimit
;
1216 unsigned StartOfMacro
= 0;
1217 for (unsigned i
= 1, e
= Changes
.size(); i
< e
; ++i
) {
1218 Change
&C
= Changes
[i
];
1219 if (C
.NewlinesBefore
> 0) {
1220 if (C
.ContinuesPPDirective
) {
1221 MaxEndOfLine
= std::max(C
.PreviousEndOfTokenColumn
+ 2, MaxEndOfLine
);
1223 alignEscapedNewlines(StartOfMacro
+ 1, i
, MaxEndOfLine
);
1224 MaxEndOfLine
= AlignLeft
? 0 : Style
.ColumnLimit
;
1229 alignEscapedNewlines(StartOfMacro
+ 1, Changes
.size(), MaxEndOfLine
);
1232 void WhitespaceManager::alignEscapedNewlines(unsigned Start
, unsigned End
,
1234 for (unsigned i
= Start
; i
< End
; ++i
) {
1235 Change
&C
= Changes
[i
];
1236 if (C
.NewlinesBefore
> 0) {
1237 assert(C
.ContinuesPPDirective
);
1238 if (C
.PreviousEndOfTokenColumn
+ 1 > Column
)
1239 C
.EscapedNewlineColumn
= 0;
1241 C
.EscapedNewlineColumn
= Column
;
1246 void WhitespaceManager::alignArrayInitializers() {
1247 if (Style
.AlignArrayOfStructures
== FormatStyle::AIAS_None
)
1250 for (unsigned ChangeIndex
= 1U, ChangeEnd
= Changes
.size();
1251 ChangeIndex
< ChangeEnd
; ++ChangeIndex
) {
1252 auto &C
= Changes
[ChangeIndex
];
1253 if (C
.Tok
->IsArrayInitializer
) {
1254 bool FoundComplete
= false;
1255 for (unsigned InsideIndex
= ChangeIndex
+ 1; InsideIndex
< ChangeEnd
;
1257 if (Changes
[InsideIndex
].Tok
== C
.Tok
->MatchingParen
) {
1258 alignArrayInitializers(ChangeIndex
, InsideIndex
+ 1);
1259 ChangeIndex
= InsideIndex
+ 1;
1260 FoundComplete
= true;
1265 ChangeIndex
= ChangeEnd
;
1270 void WhitespaceManager::alignArrayInitializers(unsigned Start
, unsigned End
) {
1272 if (Style
.AlignArrayOfStructures
== FormatStyle::AIAS_Right
)
1273 alignArrayInitializersRightJustified(getCells(Start
, End
));
1274 else if (Style
.AlignArrayOfStructures
== FormatStyle::AIAS_Left
)
1275 alignArrayInitializersLeftJustified(getCells(Start
, End
));
1278 void WhitespaceManager::alignArrayInitializersRightJustified(
1279 CellDescriptions
&&CellDescs
) {
1280 if (!CellDescs
.isRectangular())
1283 const int BracePadding
= Style
.Cpp11BracedListStyle
? 0 : 1;
1284 auto &Cells
= CellDescs
.Cells
;
1285 // Now go through and fixup the spaces.
1286 auto *CellIter
= Cells
.begin();
1287 for (auto i
= 0U; i
< CellDescs
.CellCounts
[0]; ++i
, ++CellIter
) {
1288 unsigned NetWidth
= 0U;
1289 if (isSplitCell(*CellIter
))
1290 NetWidth
= getNetWidth(Cells
.begin(), CellIter
, CellDescs
.InitialSpaces
);
1291 auto CellWidth
= getMaximumCellWidth(CellIter
, NetWidth
);
1293 if (Changes
[CellIter
->Index
].Tok
->is(tok::r_brace
)) {
1294 // So in here we want to see if there is a brace that falls
1295 // on a line that was split. If so on that line we make sure that
1296 // the spaces in front of the brace are enough.
1297 const auto *Next
= CellIter
;
1299 const FormatToken
*Previous
= Changes
[Next
->Index
].Tok
->Previous
;
1300 if (Previous
&& Previous
->isNot(TT_LineComment
)) {
1301 Changes
[Next
->Index
].Spaces
= BracePadding
;
1302 Changes
[Next
->Index
].NewlinesBefore
= 0;
1304 Next
= Next
->NextColumnElement
;
1306 // Unless the array is empty, we need the position of all the
1307 // immediately adjacent cells
1308 if (CellIter
!= Cells
.begin()) {
1310 getNetWidth(Cells
.begin(), CellIter
, CellDescs
.InitialSpaces
);
1311 auto MaxNetWidth
= getMaximumNetWidth(
1312 Cells
.begin(), CellIter
, CellDescs
.InitialSpaces
,
1313 CellDescs
.CellCounts
[0], CellDescs
.CellCounts
.size());
1314 if (ThisNetWidth
< MaxNetWidth
)
1315 Changes
[CellIter
->Index
].Spaces
= (MaxNetWidth
- ThisNetWidth
);
1317 auto Offset
= std::distance(Cells
.begin(), CellIter
);
1318 for (const auto *Next
= CellIter
->NextColumnElement
; Next
;
1319 Next
= Next
->NextColumnElement
) {
1320 auto *Start
= (Cells
.begin() + RowCount
* CellDescs
.CellCounts
[0]);
1321 auto *End
= Start
+ Offset
;
1322 ThisNetWidth
= getNetWidth(Start
, End
, CellDescs
.InitialSpaces
);
1323 if (ThisNetWidth
< MaxNetWidth
)
1324 Changes
[Next
->Index
].Spaces
= (MaxNetWidth
- ThisNetWidth
);
1330 calculateCellWidth(CellIter
->Index
, CellIter
->EndIndex
, true) +
1332 if (Changes
[CellIter
->Index
].NewlinesBefore
== 0) {
1333 Changes
[CellIter
->Index
].Spaces
= (CellWidth
- (ThisWidth
+ NetWidth
));
1334 Changes
[CellIter
->Index
].Spaces
+= (i
> 0) ? 1 : BracePadding
;
1336 alignToStartOfCell(CellIter
->Index
, CellIter
->EndIndex
);
1337 for (const auto *Next
= CellIter
->NextColumnElement
; Next
;
1338 Next
= Next
->NextColumnElement
) {
1340 calculateCellWidth(Next
->Index
, Next
->EndIndex
, true) + NetWidth
;
1341 if (Changes
[Next
->Index
].NewlinesBefore
== 0) {
1342 Changes
[Next
->Index
].Spaces
= (CellWidth
- ThisWidth
);
1343 Changes
[Next
->Index
].Spaces
+= (i
> 0) ? 1 : BracePadding
;
1345 alignToStartOfCell(Next
->Index
, Next
->EndIndex
);
1351 void WhitespaceManager::alignArrayInitializersLeftJustified(
1352 CellDescriptions
&&CellDescs
) {
1354 if (!CellDescs
.isRectangular())
1357 const int BracePadding
= Style
.Cpp11BracedListStyle
? 0 : 1;
1358 auto &Cells
= CellDescs
.Cells
;
1359 // Now go through and fixup the spaces.
1360 auto *CellIter
= Cells
.begin();
1361 // The first cell needs to be against the left brace.
1362 if (Changes
[CellIter
->Index
].NewlinesBefore
== 0)
1363 Changes
[CellIter
->Index
].Spaces
= BracePadding
;
1365 Changes
[CellIter
->Index
].Spaces
= CellDescs
.InitialSpaces
;
1367 for (auto i
= 1U; i
< CellDescs
.CellCounts
[0]; i
++, ++CellIter
) {
1368 auto MaxNetWidth
= getMaximumNetWidth(
1369 Cells
.begin(), CellIter
, CellDescs
.InitialSpaces
,
1370 CellDescs
.CellCounts
[0], CellDescs
.CellCounts
.size());
1372 getNetWidth(Cells
.begin(), CellIter
, CellDescs
.InitialSpaces
);
1373 if (Changes
[CellIter
->Index
].NewlinesBefore
== 0) {
1374 Changes
[CellIter
->Index
].Spaces
=
1375 MaxNetWidth
- ThisNetWidth
+
1376 (Changes
[CellIter
->Index
].Tok
->isNot(tok::r_brace
) ? 1
1380 auto Offset
= std::distance(Cells
.begin(), CellIter
);
1381 for (const auto *Next
= CellIter
->NextColumnElement
; Next
;
1382 Next
= Next
->NextColumnElement
) {
1383 if (RowCount
> CellDescs
.CellCounts
.size())
1385 auto *Start
= (Cells
.begin() + RowCount
* CellDescs
.CellCounts
[0]);
1386 auto *End
= Start
+ Offset
;
1387 auto ThisNetWidth
= getNetWidth(Start
, End
, CellDescs
.InitialSpaces
);
1388 if (Changes
[Next
->Index
].NewlinesBefore
== 0) {
1389 Changes
[Next
->Index
].Spaces
=
1390 MaxNetWidth
- ThisNetWidth
+
1391 (Changes
[Next
->Index
].Tok
->isNot(tok::r_brace
) ? 1 : BracePadding
);
1398 bool WhitespaceManager::isSplitCell(const CellDescription
&Cell
) {
1401 for (const auto *Next
= Cell
.NextColumnElement
; Next
;
1402 Next
= Next
->NextColumnElement
) {
1409 WhitespaceManager::CellDescriptions
WhitespaceManager::getCells(unsigned Start
,
1414 SmallVector
<unsigned> CellCounts
;
1415 unsigned InitialSpaces
= 0;
1416 unsigned InitialTokenLength
= 0;
1417 unsigned EndSpaces
= 0;
1418 SmallVector
<CellDescription
> Cells
;
1419 const FormatToken
*MatchingParen
= nullptr;
1420 for (unsigned i
= Start
; i
< End
; ++i
) {
1421 auto &C
= Changes
[i
];
1422 if (C
.Tok
->is(tok::l_brace
))
1424 else if (C
.Tok
->is(tok::r_brace
))
1427 if (C
.Tok
->is(tok::l_brace
)) {
1429 MatchingParen
= C
.Tok
->MatchingParen
;
1430 if (InitialSpaces
== 0) {
1431 InitialSpaces
= C
.Spaces
+ C
.TokenLength
;
1432 InitialTokenLength
= C
.TokenLength
;
1434 for (; Changes
[j
].NewlinesBefore
== 0 && j
> Start
; --j
) {
1435 InitialSpaces
+= Changes
[j
].Spaces
+ Changes
[j
].TokenLength
;
1436 InitialTokenLength
+= Changes
[j
].TokenLength
;
1438 if (C
.NewlinesBefore
== 0) {
1439 InitialSpaces
+= Changes
[j
].Spaces
+ Changes
[j
].TokenLength
;
1440 InitialTokenLength
+= Changes
[j
].TokenLength
;
1443 } else if (C
.Tok
->is(tok::comma
)) {
1445 Cells
.back().EndIndex
= i
;
1446 if (C
.Tok
->getNextNonComment()->isNot(tok::r_brace
)) // dangling comma
1449 } else if (Depth
== 1) {
1450 if (C
.Tok
== MatchingParen
) {
1452 Cells
.back().EndIndex
= i
;
1453 Cells
.push_back(CellDescription
{i
, ++Cell
, i
+ 1, false, nullptr});
1454 CellCounts
.push_back(C
.Tok
->Previous
->isNot(tok::comma
) ? Cell
+ 1
1456 // Go to the next non-comment and ensure there is a break in front
1457 const auto *NextNonComment
= C
.Tok
->getNextNonComment();
1458 while (NextNonComment
->is(tok::comma
))
1459 NextNonComment
= NextNonComment
->getNextNonComment();
1461 while (Changes
[j
].Tok
!= NextNonComment
&& j
< End
)
1463 if (j
< End
&& Changes
[j
].NewlinesBefore
== 0 &&
1464 Changes
[j
].Tok
->isNot(tok::r_brace
)) {
1465 Changes
[j
].NewlinesBefore
= 1;
1466 // Account for the added token lengths
1467 Changes
[j
].Spaces
= InitialSpaces
- InitialTokenLength
;
1469 } else if (C
.Tok
->is(tok::comment
)) {
1470 // Trailing comments stay at a space past the last token
1471 C
.Spaces
= Changes
[i
- 1].Tok
->is(tok::comma
) ? 1 : 2;
1472 } else if (C
.Tok
->is(tok::l_brace
)) {
1473 // We need to make sure that the ending braces is aligned to the
1474 // start of our initializer
1476 for (; j
> 0 && !Changes
[j
].Tok
->ArrayInitializerLineStart
; --j
)
1477 ; // Nothing the loop does the work
1478 EndSpaces
= Changes
[j
].Spaces
;
1480 } else if (Depth
== 0 && C
.Tok
->is(tok::r_brace
)) {
1481 C
.NewlinesBefore
= 1;
1482 C
.Spaces
= EndSpaces
;
1484 if (C
.Tok
->StartsColumn
) {
1485 // This gets us past tokens that have been split over multiple
1487 bool HasSplit
= false;
1488 if (Changes
[i
].NewlinesBefore
> 0) {
1489 // So if we split a line previously and the tail line + this token is
1490 // less then the column limit we remove the split here and just put
1491 // the column start at a space past the comma
1493 // FIXME This if branch covers the cases where the column is not
1494 // the first column. This leads to weird pathologies like the formatting
1495 // auto foo = Items{
1500 // Well if it doesn't lead to that it's indicative that the line
1501 // breaking should be revisited. Unfortunately alot of other options
1502 // interact with this
1504 if ((j
- 1) > Start
&& Changes
[j
].Tok
->is(tok::comma
) &&
1505 Changes
[j
- 1].NewlinesBefore
> 0) {
1507 auto LineLimit
= Changes
[j
].Spaces
+ Changes
[j
].TokenLength
;
1508 if (LineLimit
< Style
.ColumnLimit
) {
1509 Changes
[i
].NewlinesBefore
= 0;
1510 Changes
[i
].Spaces
= 1;
1514 while (Changes
[i
].NewlinesBefore
> 0 && Changes
[i
].Tok
== C
.Tok
) {
1515 Changes
[i
].Spaces
= InitialSpaces
;
1519 if (Changes
[i
].Tok
!= C
.Tok
)
1521 Cells
.push_back(CellDescription
{i
, Cell
, i
, HasSplit
, nullptr});
1525 return linkCells({Cells
, CellCounts
, InitialSpaces
});
1528 unsigned WhitespaceManager::calculateCellWidth(unsigned Start
, unsigned End
,
1529 bool WithSpaces
) const {
1530 unsigned CellWidth
= 0;
1531 for (auto i
= Start
; i
< End
; i
++) {
1532 if (Changes
[i
].NewlinesBefore
> 0)
1534 CellWidth
+= Changes
[i
].TokenLength
;
1535 CellWidth
+= (WithSpaces
? Changes
[i
].Spaces
: 0);
1540 void WhitespaceManager::alignToStartOfCell(unsigned Start
, unsigned End
) {
1541 if ((End
- Start
) <= 1)
1543 // If the line is broken anywhere in there make sure everything
1544 // is aligned to the parent
1545 for (auto i
= Start
+ 1; i
< End
; i
++)
1546 if (Changes
[i
].NewlinesBefore
> 0)
1547 Changes
[i
].Spaces
= Changes
[Start
].Spaces
;
1550 WhitespaceManager::CellDescriptions
1551 WhitespaceManager::linkCells(CellDescriptions
&&CellDesc
) {
1552 auto &Cells
= CellDesc
.Cells
;
1553 for (auto *CellIter
= Cells
.begin(); CellIter
!= Cells
.end(); ++CellIter
) {
1554 if (!CellIter
->NextColumnElement
&& (CellIter
+ 1) != Cells
.end()) {
1555 for (auto *NextIter
= CellIter
+ 1; NextIter
!= Cells
.end(); ++NextIter
) {
1556 if (NextIter
->Cell
== CellIter
->Cell
) {
1557 CellIter
->NextColumnElement
= &(*NextIter
);
1563 return std::move(CellDesc
);
1566 void WhitespaceManager::generateChanges() {
1567 for (unsigned i
= 0, e
= Changes
.size(); i
!= e
; ++i
) {
1568 const Change
&C
= Changes
[i
];
1570 auto Last
= Changes
[i
- 1].OriginalWhitespaceRange
;
1571 auto New
= Changes
[i
].OriginalWhitespaceRange
;
1572 // Do not generate two replacements for the same location. As a special
1573 // case, it is allowed if there is a replacement for the empty range
1574 // between 2 tokens and another non-empty range at the start of the second
1575 // token. We didn't implement logic to combine replacements for 2
1576 // consecutive source ranges into a single replacement, because the
1577 // program works fine without it.
1579 // We can't eliminate empty original whitespace ranges. They appear when
1580 // 2 tokens have no whitespace in between in the input. It does not
1581 // matter whether whitespace is to be added. If no whitespace is to be
1582 // added, the replacement will be empty, and it gets eliminated after this
1583 // step in storeReplacement. For example, if the input is `foo();`,
1584 // there will be a replacement for the range between every consecutive
1587 // A replacement at the start of a token can be added by
1588 // BreakableStringLiteralUsingOperators::insertBreak when it adds braces
1589 // around the string literal. Say Verilog code is being formatted and the
1590 // first line is to become the next 2 lines.
1591 // x("long string");
1594 // There will be a replacement for the empty range between the parenthesis
1595 // and the string and another replacement for the quote character. The
1596 // replacement for the empty range between the parenthesis and the quote
1597 // comes from ContinuationIndenter::addTokenOnCurrentLine when it changes
1598 // the original empty range between the parenthesis and the string to
1599 // another empty one. The replacement for the quote character comes from
1600 // BreakableStringLiteralUsingOperators::insertBreak when it adds the
1601 // brace. In the example, the replacement for the empty range is the same
1602 // as the original text. However, eliminating replacements that are same
1603 // as the original does not help in general. For example, a newline can
1604 // be inserted, causing the first line to become the next 3 lines.
1605 // xxxxxxxxxxx("long string");
1609 // In that case, the empty range between the parenthesis and the string
1610 // will be replaced by a newline and 4 spaces. So we will still have to
1611 // deal with a replacement for an empty source range followed by a
1612 // replacement for a non-empty source range.
1613 if (Last
.getBegin() == New
.getBegin() &&
1614 (Last
.getEnd() != Last
.getBegin() ||
1615 New
.getEnd() == New
.getBegin())) {
1619 if (C
.CreateReplacement
) {
1620 std::string ReplacementText
= C
.PreviousLinePostfix
;
1621 if (C
.ContinuesPPDirective
) {
1622 appendEscapedNewlineText(ReplacementText
, C
.NewlinesBefore
,
1623 C
.PreviousEndOfTokenColumn
,
1624 C
.EscapedNewlineColumn
);
1626 appendNewlineText(ReplacementText
, C
.NewlinesBefore
);
1628 // FIXME: This assert should hold if we computed the column correctly.
1629 // assert((int)C.StartOfTokenColumn >= C.Spaces);
1631 ReplacementText
, C
.Tok
->IndentLevel
, std::max(0, C
.Spaces
),
1632 std::max((int)C
.StartOfTokenColumn
, C
.Spaces
) - std::max(0, C
.Spaces
),
1634 ReplacementText
.append(C
.CurrentLinePrefix
);
1635 storeReplacement(C
.OriginalWhitespaceRange
, ReplacementText
);
1640 void WhitespaceManager::storeReplacement(SourceRange Range
, StringRef Text
) {
1641 unsigned WhitespaceLength
= SourceMgr
.getFileOffset(Range
.getEnd()) -
1642 SourceMgr
.getFileOffset(Range
.getBegin());
1643 // Don't create a replacement, if it does not change anything.
1644 if (StringRef(SourceMgr
.getCharacterData(Range
.getBegin()),
1645 WhitespaceLength
) == Text
) {
1648 auto Err
= Replaces
.add(tooling::Replacement(
1649 SourceMgr
, CharSourceRange::getCharRange(Range
), Text
));
1650 // FIXME: better error handling. For now, just print an error message in the
1653 llvm::errs() << llvm::toString(std::move(Err
)) << "\n";
1658 void WhitespaceManager::appendNewlineText(std::string
&Text
,
1659 unsigned Newlines
) {
1661 Text
.reserve(Text
.size() + 2 * Newlines
);
1662 for (unsigned i
= 0; i
< Newlines
; ++i
)
1663 Text
.append("\r\n");
1665 Text
.append(Newlines
, '\n');
1669 void WhitespaceManager::appendEscapedNewlineText(
1670 std::string
&Text
, unsigned Newlines
, unsigned PreviousEndOfTokenColumn
,
1671 unsigned EscapedNewlineColumn
) {
1674 std::max
<int>(1, EscapedNewlineColumn
- PreviousEndOfTokenColumn
- 1);
1675 for (unsigned i
= 0; i
< Newlines
; ++i
) {
1676 Text
.append(Spaces
, ' ');
1677 Text
.append(UseCRLF
? "\\\r\n" : "\\\n");
1678 Spaces
= std::max
<int>(0, EscapedNewlineColumn
- 1);
1683 void WhitespaceManager::appendIndentText(std::string
&Text
,
1684 unsigned IndentLevel
, unsigned Spaces
,
1685 unsigned WhitespaceStartColumn
,
1687 switch (Style
.UseTab
) {
1688 case FormatStyle::UT_Never
:
1689 Text
.append(Spaces
, ' ');
1691 case FormatStyle::UT_Always
: {
1692 if (Style
.TabWidth
) {
1693 unsigned FirstTabWidth
=
1694 Style
.TabWidth
- WhitespaceStartColumn
% Style
.TabWidth
;
1696 // Insert only spaces when we want to end up before the next tab.
1697 if (Spaces
< FirstTabWidth
|| Spaces
== 1) {
1698 Text
.append(Spaces
, ' ');
1701 // Align to the next tab.
1702 Spaces
-= FirstTabWidth
;
1705 Text
.append(Spaces
/ Style
.TabWidth
, '\t');
1706 Text
.append(Spaces
% Style
.TabWidth
, ' ');
1707 } else if (Spaces
== 1) {
1708 Text
.append(Spaces
, ' ');
1712 case FormatStyle::UT_ForIndentation
:
1713 if (WhitespaceStartColumn
== 0) {
1714 unsigned Indentation
= IndentLevel
* Style
.IndentWidth
;
1715 Spaces
= appendTabIndent(Text
, Spaces
, Indentation
);
1717 Text
.append(Spaces
, ' ');
1719 case FormatStyle::UT_ForContinuationAndIndentation
:
1720 if (WhitespaceStartColumn
== 0)
1721 Spaces
= appendTabIndent(Text
, Spaces
, Spaces
);
1722 Text
.append(Spaces
, ' ');
1724 case FormatStyle::UT_AlignWithSpaces
:
1725 if (WhitespaceStartColumn
== 0) {
1726 unsigned Indentation
=
1727 IsAligned
? IndentLevel
* Style
.IndentWidth
: Spaces
;
1728 Spaces
= appendTabIndent(Text
, Spaces
, Indentation
);
1730 Text
.append(Spaces
, ' ');
1735 unsigned WhitespaceManager::appendTabIndent(std::string
&Text
, unsigned Spaces
,
1736 unsigned Indentation
) {
1737 // This happens, e.g. when a line in a block comment is indented less than the
1739 if (Indentation
> Spaces
)
1740 Indentation
= Spaces
;
1741 if (Style
.TabWidth
) {
1742 unsigned Tabs
= Indentation
/ Style
.TabWidth
;
1743 Text
.append(Tabs
, '\t');
1744 Spaces
-= Tabs
* Style
.TabWidth
;
1749 } // namespace format
1750 } // namespace clang