15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/SmallVector.h"
50 unsigned StartOfTokenColumn,
51 bool IsAligned,
bool InPPDirective) {
56 Spaces, StartOfTokenColumn, Newlines,
"",
"",
57 IsAligned, InPPDirective && !Tok.
IsFirst,
65 Changes.push_back(
Change(Tok,
false,
68 false, InPPDirective && !Tok.
IsFirst,
74 return Replaces.
add(Replacement);
78 size_t LF =
Text.count(
'\n');
79 size_t CR =
Text.count(
'\r') * 2;
80 return LF == CR ? DefaultToCRLF : CR > LF;
85 StringRef PreviousPostfix, StringRef CurrentPrefix,
bool InPPDirective,
86 unsigned Newlines,
int Spaces) {
93 std::max(0, Spaces), Newlines, PreviousPostfix, CurrentPrefix,
94 true, InPPDirective && !Tok.
IsFirst,
103 calculateLineBreakInformation();
104 alignConsecutiveMacros();
105 alignConsecutiveDeclarations();
106 alignConsecutiveBitFields();
107 alignConsecutiveAssignments();
108 alignChainedConditionals();
109 alignTrailingComments();
110 alignEscapedNewlines();
111 alignArrayInitializers();
117 void WhitespaceManager::calculateLineBreakInformation() {
118 Changes[0].PreviousEndOfTokenColumn = 0;
119 Change *LastOutsideTokenChange = &Changes[0];
120 for (
unsigned i = 1, e = Changes.size(); i != e; ++i) {
122 Changes[i].OriginalWhitespaceRange.getBegin();
124 Changes[i - 1].OriginalWhitespaceRange.getEnd();
125 unsigned OriginalWhitespaceStartOffset =
127 unsigned PreviousOriginalWhitespaceEndOffset =
129 assert(PreviousOriginalWhitespaceEndOffset <=
130 OriginalWhitespaceStartOffset);
131 const char *
const PreviousOriginalWhitespaceEndData =
133 StringRef
Text(PreviousOriginalWhitespaceEndData,
135 PreviousOriginalWhitespaceEndData);
157 auto NewlinePos =
Text.find_first_of(
'\n');
158 if (NewlinePos == StringRef::npos) {
159 Changes[i - 1].TokenLength = OriginalWhitespaceStartOffset -
160 PreviousOriginalWhitespaceEndOffset +
161 Changes[i].PreviousLinePostfix.size() +
162 Changes[i - 1].CurrentLinePrefix.size();
164 Changes[i - 1].TokenLength =
165 NewlinePos + Changes[i - 1].CurrentLinePrefix.size();
170 if (Changes[i - 1].IsInsideToken && Changes[i - 1].NewlinesBefore == 0) {
171 LastOutsideTokenChange->TokenLength +=
172 Changes[i - 1].TokenLength + Changes[i - 1].Spaces;
174 LastOutsideTokenChange = &Changes[i - 1];
177 Changes[i].PreviousEndOfTokenColumn =
178 Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength;
180 Changes[i - 1].IsTrailingComment =
181 (Changes[i].NewlinesBefore > 0 || Changes[i].Tok->is(
tok::eof) ||
182 (Changes[i].IsInsideToken && Changes[i].Tok->is(tok::comment))) &&
183 Changes[i - 1].Tok->is(tok::comment) &&
214 OriginalWhitespaceStart != PreviousOriginalWhitespaceEnd;
218 Changes.back().TokenLength = 0;
219 Changes.back().IsTrailingComment = Changes.back().Tok->is(tok::comment);
221 const WhitespaceManager::Change *LastBlockComment =
nullptr;
222 for (
auto &Change : Changes) {
226 if (Change.IsInsideToken && Change.NewlinesBefore == 0)
227 Change.IsTrailingComment =
false;
228 Change.StartOfBlockComment =
nullptr;
229 Change.IndentationOffset = 0;
230 if (Change.Tok->is(tok::comment)) {
231 if (Change.Tok->is(TT_LineComment) || !Change.IsInsideToken) {
232 LastBlockComment = &Change;
233 }
else if ((Change.StartOfBlockComment = LastBlockComment)) {
234 Change.IndentationOffset =
235 Change.StartOfTokenColumn -
236 Change.StartOfBlockComment->StartOfTokenColumn;
239 LastBlockComment =
nullptr;
247 SmallVector<bool, 16> ScopeStack;
248 int ConditionalsLevel = 0;
249 for (
auto &Change : Changes) {
250 for (
unsigned i = 0, e = Change.Tok->FakeLParens.size(); i != e; ++i) {
251 bool isNestedConditional =
253 !(i == 0 && Change.Tok->Previous &&
254 Change.Tok->Previous->is(TT_ConditionalExpr) &&
255 Change.Tok->Previous->is(tok::colon));
256 if (isNestedConditional)
258 ScopeStack.push_back(isNestedConditional);
261 Change.ConditionalsLevel = ConditionalsLevel;
263 for (
unsigned i = Change.Tok->FakeRParens; i > 0 && ScopeStack.size(); --i)
264 if (ScopeStack.pop_back_val())
273 template <
typename F>
276 unsigned Column,
bool RightJustify, F &&Matches,
278 bool FoundMatchOnLine =
false;
303 for (
unsigned i = Start; i !=
End; ++i) {
304 if (ScopeStack.size() != 0 &&
305 Changes[i].indentAndNestingLevel() <
306 Changes[ScopeStack.back()].indentAndNestingLevel()) {
307 ScopeStack.pop_back();
312 unsigned PreviousNonComment = i - 1;
313 while (PreviousNonComment > Start &&
314 Changes[PreviousNonComment].Tok->is(tok::comment)) {
315 --PreviousNonComment;
317 if (i != Start && Changes[i].indentAndNestingLevel() >
318 Changes[PreviousNonComment].indentAndNestingLevel()) {
319 ScopeStack.push_back(i);
322 bool InsideNestedScope = ScopeStack.size() != 0;
323 bool ContinuedStringLiteral = i > Start &&
324 Changes[i].Tok->is(tok::string_literal) &&
325 Changes[i - 1].Tok->is(tok::string_literal);
326 bool SkipMatchCheck = InsideNestedScope || ContinuedStringLiteral;
328 if (Changes[i].NewlinesBefore > 0 && !SkipMatchCheck) {
330 FoundMatchOnLine =
false;
336 if (!FoundMatchOnLine && !SkipMatchCheck && Matches(Changes[i])) {
337 FoundMatchOnLine =
true;
338 Shift = Column - (RightJustify ? Changes[i].TokenLength : 0) -
339 Changes[i].StartOfTokenColumn;
340 Changes[i].Spaces +=
Shift;
343 if (Changes[i].NewlinesBefore == 0) {
346 static_cast<int>(Changes[i].Tok->SpacesRequiredBefore));
352 if (InsideNestedScope && Changes[i].NewlinesBefore > 0) {
353 unsigned ScopeStart = ScopeStack.back();
354 auto ShouldShiftBeAdded = [&] {
356 if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
360 if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
364 if (ScopeStart > Start + 1 &&
365 Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)) {
370 if (ScopeStart > Start + 1 &&
371 Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
372 Changes[ScopeStart - 1].Tok->is(tok::l_paren) &&
373 Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)) {
374 if (Changes[i].Tok->MatchingParen &&
375 Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace)) {
378 if (Changes[ScopeStart].NewlinesBefore > 0)
380 if (Changes[i].Tok->is(tok::l_brace) &&
384 return Style.BinPackArguments;
388 if (Changes[i].Tok->is(TT_ConditionalExpr))
392 if (Changes[i].Tok->is(TT_DesignatedInitializerPeriod))
396 if (Changes[i].Tok->Previous &&
397 Changes[i].Tok->Previous->is(TT_ConditionalExpr)) {
402 if (ScopeStart > Start + 1 &&
403 Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
404 Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
405 Changes[i].Tok->is(tok::l_brace) &&
411 if (ScopeStart > Start + 1 &&
412 Changes[ScopeStart - 2].Tok->isNot(tok::identifier) &&
413 Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
414 Changes[i].Tok->isNot(tok::r_brace)) {
415 for (
unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
417 if (OuterScopeStart > Start &&
418 Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace)) {
422 if (Changes[ScopeStart].NewlinesBefore > 0)
430 if (ShouldShiftBeAdded())
431 Changes[i].Spaces +=
Shift;
434 if (ContinuedStringLiteral)
435 Changes[i].Spaces +=
Shift;
438 assert(
Shift >= 0 || Changes[i].NewlinesBefore > 0 ||
440 static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
443 Changes[i].StartOfTokenColumn +=
Shift;
444 if (i + 1 != Changes.size())
445 Changes[i + 1].PreviousEndOfTokenColumn +=
Shift;
449 Changes[i].Spaces != 0) {
452 Changes[
Previous].Tok->getType() == TT_PointerOrReference;
493 template <
typename F>
498 bool RightJustify =
false) {
507 unsigned WidthLeft = 0;
510 unsigned WidthAnchor = 0;
513 unsigned WidthRight = 0;
516 unsigned StartOfSequence = 0;
517 unsigned EndOfSequence = 0;
521 auto IndentAndNestingLevel = StartAt < Changes.size()
522 ? Changes[StartAt].indentAndNestingLevel()
523 : std::tuple<unsigned, unsigned, unsigned>();
528 unsigned CommasBeforeLastMatch = 0;
529 unsigned CommasBeforeMatch = 0;
532 bool FoundMatchOnLine =
false;
535 bool LineIsComment =
true;
544 auto AlignCurrentSequence = [&] {
545 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
547 WidthLeft + WidthAnchor, RightJustify, Matches,
557 unsigned i = StartAt;
558 for (
unsigned e = Changes.size(); i != e; ++i) {
559 if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel)
562 if (Changes[i].NewlinesBefore != 0) {
563 CommasBeforeMatch = 0;
567 bool EmptyLineBreak =
568 (Changes[i].NewlinesBefore > 1) && !ACS.AcrossEmptyLines;
573 !FoundMatchOnLine && !(LineIsComment && ACS.AcrossComments);
575 if (EmptyLineBreak || NoMatchBreak)
576 AlignCurrentSequence();
580 if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
581 !Changes[i - 1].Tok->is(tok::string_literal)) {
582 FoundMatchOnLine =
false;
584 LineIsComment =
true;
587 if (!Changes[i].Tok->is(tok::comment))
588 LineIsComment =
false;
590 if (Changes[i].Tok->is(tok::comma)) {
592 }
else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
594 unsigned StoppedAt =
AlignTokens(Style, Matches, Changes, i, ACS);
599 if (!Matches(Changes[i]))
604 if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
605 AlignCurrentSequence();
607 CommasBeforeLastMatch = CommasBeforeMatch;
608 FoundMatchOnLine =
true;
610 if (StartOfSequence == 0)
613 unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
614 unsigned ChangeWidthAnchor = 0;
615 unsigned ChangeWidthRight = 0;
617 if (ACS.PadOperators)
618 ChangeWidthAnchor = Changes[i].TokenLength;
620 ChangeWidthLeft += Changes[i].TokenLength;
622 ChangeWidthRight = Changes[i].TokenLength;
623 for (
unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) {
624 ChangeWidthRight += Changes[j].Spaces;
630 if (!Changes[j].IsInsideToken)
631 ChangeWidthRight += Changes[j].TokenLength;
635 unsigned NewLeft =
std::max(ChangeWidthLeft, WidthLeft);
636 unsigned NewAnchor =
std::max(ChangeWidthAnchor, WidthAnchor);
637 unsigned NewRight =
std::max(ChangeWidthRight, WidthRight);
639 if (Style.ColumnLimit != 0 &&
640 Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
641 AlignCurrentSequence();
643 WidthLeft = ChangeWidthLeft;
644 WidthAnchor = ChangeWidthAnchor;
645 WidthRight = ChangeWidthRight;
648 WidthAnchor = NewAnchor;
649 WidthRight = NewRight;
654 AlignCurrentSequence();
666 unsigned &StartOfSequence,
unsigned &EndOfSequence,
unsigned &MinColumn,
667 unsigned &MaxColumn,
bool &FoundMatchOnLine,
670 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
672 FoundMatchOnLine =
false;
675 for (
unsigned I = StartOfSequence; I != EndOfSequence; ++I) {
676 if (Changes[I].NewlinesBefore > 0) {
678 FoundMatchOnLine =
false;
684 if (!FoundMatchOnLine && AlignMacrosMatches(Changes[I])) {
685 FoundMatchOnLine =
true;
686 Shift = MinColumn - Changes[I].StartOfTokenColumn;
687 Changes[I].Spaces +=
Shift;
691 Changes[I].StartOfTokenColumn +=
Shift;
692 if (I + 1 != Changes.size())
693 Changes[I + 1].PreviousEndOfTokenColumn +=
Shift;
703 void WhitespaceManager::alignConsecutiveMacros() {
704 if (!Style.AlignConsecutiveMacros.Enabled)
707 auto AlignMacrosMatches = [](
const Change &C) {
708 const FormatToken *Current = C.Tok;
709 unsigned SpacesRequiredBefore = 1;
711 if (Current->SpacesRequiredBefore == 0 || !Current->Previous)
714 Current = Current->Previous;
718 if (Current->is(tok::r_paren) && Current->MatchingParen) {
719 Current = Current->MatchingParen->Previous;
720 SpacesRequiredBefore = 0;
723 if (!Current || !Current->is(tok::identifier))
733 return Current->Next->SpacesRequiredBefore == SpacesRequiredBefore;
736 unsigned MinColumn = 0;
740 unsigned StartOfSequence = 0;
741 unsigned EndOfSequence = 0;
744 bool FoundMatchOnLine =
false;
747 bool LineIsComment =
true;
750 for (
unsigned E = Changes.size(); I != E; ++I) {
751 if (Changes[I].NewlinesBefore != 0) {
755 bool EmptyLineBreak = (Changes[I].NewlinesBefore > 1) &&
756 !Style.AlignConsecutiveMacros.AcrossEmptyLines;
762 !(LineIsComment && Style.AlignConsecutiveMacros.AcrossComments);
764 if (EmptyLineBreak || NoMatchBreak) {
766 FoundMatchOnLine, AlignMacrosMatches, Changes);
770 FoundMatchOnLine =
false;
771 LineIsComment =
true;
774 if (!Changes[I].Tok->is(tok::comment))
775 LineIsComment =
false;
777 if (!AlignMacrosMatches(Changes[I]))
780 FoundMatchOnLine =
true;
782 if (StartOfSequence == 0)
785 unsigned ChangeMinColumn = Changes[I].StartOfTokenColumn;
786 int LineLengthAfter = -Changes[I].Spaces;
787 for (
unsigned j = I; j != E && Changes[j].NewlinesBefore == 0; ++j)
788 LineLengthAfter += Changes[j].Spaces + Changes[j].TokenLength;
789 unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
791 MinColumn =
std::max(MinColumn, ChangeMinColumn);
792 MaxColumn =
std::min(MaxColumn, ChangeMaxColumn);
797 FoundMatchOnLine, AlignMacrosMatches, Changes);
800 void WhitespaceManager::alignConsecutiveAssignments() {
801 if (!Style.AlignConsecutiveAssignments.Enabled)
806 [&](
const Change &C) {
808 if (
C.NewlinesBefore > 0)
812 if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
816 FormatToken *
Previous =
C.Tok->getPreviousNonComment();
820 return Style.AlignConsecutiveAssignments.AlignCompound
822 :
C.Tok->is(tok::equal);
824 Changes, 0, Style.AlignConsecutiveAssignments,
828 void WhitespaceManager::alignConsecutiveBitFields() {
829 if (!Style.AlignConsecutiveBitFields.Enabled)
834 [&](Change
const &C) {
836 if (
C.NewlinesBefore > 0)
840 if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
843 return C.Tok->is(TT_BitFieldColon);
845 Changes, 0, Style.AlignConsecutiveBitFields);
848 void WhitespaceManager::alignConsecutiveDeclarations() {
849 if (!Style.AlignConsecutiveDeclarations.Enabled)
854 [](Change
const &C) {
857 if (
C.Tok->isOneOf(TT_FunctionDeclarationName, tok::kw_operator))
859 if (
C.Tok->isNot(TT_StartOfName))
861 if (
C.Tok->Previous &&
862 C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
865 for (FormatToken *Next =
C.Tok->Next; Next; Next = Next->Next) {
866 if (Next->is(tok::comment))
868 if (Next->is(TT_PointerOrReference))
870 if (!Next->Tok.getIdentifierInfo())
872 if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
879 Changes, 0, Style.AlignConsecutiveDeclarations);
882 void WhitespaceManager::alignChainedConditionals() {
883 if (Style.BreakBeforeTernaryOperators) {
886 [](Change
const &C) {
888 return C.Tok->is(TT_ConditionalExpr) &&
889 ((
C.Tok->is(tok::question) && !
C.NewlinesBefore) ||
890 (
C.Tok->is(tok::colon) &&
C.Tok->Next &&
891 (
C.Tok->Next->FakeLParens.size() == 0 ||
896 static auto AlignWrappedOperand = [](Change
const &
C) {
897 FormatToken *
Previous =
C.Tok->getPreviousNonComment();
900 (
C.Tok->FakeLParens.size() == 0 ||
906 for (Change &C : Changes)
907 if (AlignWrappedOperand(C))
908 C.StartOfTokenColumn -= 2;
911 [
this](Change
const &C) {
915 return (
C.Tok->is(TT_ConditionalExpr) &&
C.Tok->is(tok::question) &&
916 &
C != &Changes.back() && (&
C + 1)->NewlinesBefore == 0 &&
917 !(&C + 1)->IsTrailingComment) ||
918 AlignWrappedOperand(C);
924 void WhitespaceManager::alignTrailingComments() {
925 unsigned MinColumn = 0;
927 unsigned StartOfSequence = 0;
928 bool BreakBeforeNext =
false;
929 unsigned Newlines = 0;
930 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
931 if (Changes[i].StartOfBlockComment)
933 Newlines += Changes[i].NewlinesBefore;
934 if (!Changes[i].IsTrailingComment)
937 unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
938 unsigned ChangeMaxColumn;
940 if (Style.ColumnLimit == 0)
942 else if (Style.ColumnLimit >= Changes[i].TokenLength)
943 ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength;
945 ChangeMaxColumn = ChangeMinColumn;
949 if (!Changes[i].CreateReplacement)
950 ChangeMaxColumn = ChangeMinColumn;
952 if (i + 1 != e && Changes[i + 1].ContinuesPPDirective)
953 ChangeMaxColumn -= 2;
956 bool FollowsRBraceInColumn0 = i > 0 && Changes[i].NewlinesBefore == 0 &&
957 Changes[i - 1].Tok->is(tok::r_brace) &&
958 Changes[i - 1].StartOfTokenColumn == 0;
959 bool WasAlignedWithStartOfNextLine =
false;
960 if (Changes[i].NewlinesBefore == 1) {
962 Changes[i].OriginalWhitespaceRange.getEnd());
963 for (
unsigned j = i + 1; j != e; ++j) {
964 if (Changes[j].Tok->is(tok::comment))
968 Changes[j].OriginalWhitespaceRange.getEnd());
971 WasAlignedWithStartOfNextLine =
972 CommentColumn == NextColumn ||
973 CommentColumn == NextColumn + Style.IndentWidth;
977 if (!Style.AlignTrailingComments || FollowsRBraceInColumn0) {
978 alignTrailingComments(StartOfSequence, i, MinColumn);
979 MinColumn = ChangeMinColumn;
980 MaxColumn = ChangeMinColumn;
982 }
else if (BreakBeforeNext || Newlines > 1 ||
983 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
986 (Changes[i].NewlinesBefore == 1 && i > 0 &&
987 !Changes[i - 1].IsTrailingComment) ||
988 WasAlignedWithStartOfNextLine) {
989 alignTrailingComments(StartOfSequence, i, MinColumn);
990 MinColumn = ChangeMinColumn;
991 MaxColumn = ChangeMaxColumn;
994 MinColumn =
std::max(MinColumn, ChangeMinColumn);
995 MaxColumn =
std::min(MaxColumn, ChangeMaxColumn);
997 BreakBeforeNext = (i == 0) || (Changes[i].NewlinesBefore > 1) ||
1000 (Changes[i].NewlinesBefore == 1 && StartOfSequence == i);
1003 alignTrailingComments(StartOfSequence, Changes.size(), MinColumn);
1006 void WhitespaceManager::alignTrailingComments(
unsigned Start,
unsigned End,
1008 for (
unsigned i = Start; i !=
End; ++i) {
1010 if (Changes[i].IsTrailingComment)
1011 Shift = Column - Changes[i].StartOfTokenColumn;
1012 if (Changes[i].StartOfBlockComment) {
1013 Shift = Changes[i].IndentationOffset +
1014 Changes[i].StartOfBlockComment->StartOfTokenColumn -
1015 Changes[i].StartOfTokenColumn;
1019 Changes[i].Spaces +=
Shift;
1020 if (i + 1 != Changes.size())
1021 Changes[i + 1].PreviousEndOfTokenColumn +=
Shift;
1022 Changes[i].StartOfTokenColumn +=
Shift;
1026 void WhitespaceManager::alignEscapedNewlines() {
1031 unsigned MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit;
1032 unsigned StartOfMacro = 0;
1033 for (
unsigned i = 1, e = Changes.size(); i < e; ++i) {
1034 Change &
C = Changes[i];
1035 if (
C.NewlinesBefore > 0) {
1036 if (
C.ContinuesPPDirective) {
1037 MaxEndOfLine =
std::max(
C.PreviousEndOfTokenColumn + 2, MaxEndOfLine);
1039 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
1040 MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit;
1045 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
1048 void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
1050 for (
unsigned i = Start; i <
End; ++i) {
1051 Change &
C = Changes[i];
1052 if (
C.NewlinesBefore > 0) {
1053 assert(
C.ContinuesPPDirective);
1054 if (
C.PreviousEndOfTokenColumn + 1 > Column)
1055 C.EscapedNewlineColumn = 0;
1057 C.EscapedNewlineColumn = Column;
1062 void WhitespaceManager::alignArrayInitializers() {
1066 for (
unsigned ChangeIndex = 1
U, ChangeEnd = Changes.size();
1067 ChangeIndex < ChangeEnd; ++ChangeIndex) {
1068 auto &
C = Changes[ChangeIndex];
1069 if (
C.Tok->IsArrayInitializer) {
1070 bool FoundComplete =
false;
1071 for (
unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
1073 if (Changes[InsideIndex].Tok ==
C.Tok->MatchingParen) {
1074 alignArrayInitializers(ChangeIndex, InsideIndex + 1);
1075 ChangeIndex = InsideIndex + 1;
1076 FoundComplete =
true;
1081 ChangeIndex = ChangeEnd;
1086 void WhitespaceManager::alignArrayInitializers(
unsigned Start,
unsigned End) {
1089 alignArrayInitializersRightJustified(getCells(Start,
End));
1091 alignArrayInitializersLeftJustified(getCells(Start,
End));
1094 void WhitespaceManager::alignArrayInitializersRightJustified(
1095 CellDescriptions &&CellDescs) {
1096 if (!CellDescs.isRectangular())
1099 auto &Cells = CellDescs.Cells;
1101 auto *CellIter = Cells.begin();
1102 for (
auto i = 0
U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {
1103 unsigned NetWidth = 0
U;
1104 if (isSplitCell(*CellIter))
1105 NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1106 auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1108 if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1112 const auto *Next = CellIter;
1114 const FormatToken *
Previous = Changes[Next->Index].Tok->Previous;
1116 Changes[Next->Index].Spaces = 0;
1117 Changes[Next->Index].NewlinesBefore = 0;
1119 Next = Next->NextColumnElement;
1123 if (CellIter != Cells.begin()) {
1125 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1126 auto MaxNetWidth = getMaximumNetWidth(
1127 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1128 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1129 if (ThisNetWidth < MaxNetWidth)
1130 Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1133 for (
const auto *Next = CellIter->NextColumnElement; Next !=
nullptr;
1134 Next = Next->NextColumnElement) {
1135 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1137 ThisNetWidth = getNetWidth(Start,
End, CellDescs.InitialSpaces);
1138 if (ThisNetWidth < MaxNetWidth)
1139 Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1145 calculateCellWidth(CellIter->Index, CellIter->EndIndex,
true) +
1147 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1148 Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
1149 Changes[CellIter->Index].Spaces += (i > 0) ? 1 : 0;
1151 alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1152 for (
const auto *Next = CellIter->NextColumnElement; Next !=
nullptr;
1153 Next = Next->NextColumnElement) {
1155 calculateCellWidth(Next->Index, Next->EndIndex,
true) + NetWidth;
1156 if (Changes[Next->Index].NewlinesBefore == 0) {
1157 Changes[Next->Index].Spaces = (CellWidth - ThisWidth);
1158 Changes[Next->Index].Spaces += (i > 0) ? 1 : 0;
1160 alignToStartOfCell(Next->Index, Next->EndIndex);
1166 void WhitespaceManager::alignArrayInitializersLeftJustified(
1167 CellDescriptions &&CellDescs) {
1169 if (!CellDescs.isRectangular())
1172 auto &Cells = CellDescs.Cells;
1174 auto *CellIter = Cells.begin();
1176 if (Changes[CellIter->Index].NewlinesBefore == 0)
1177 Changes[CellIter->Index].Spaces = 0;
1179 Changes[CellIter->Index].Spaces = CellDescs.InitialSpaces;
1181 for (
auto i = 1
U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {
1182 auto MaxNetWidth = getMaximumNetWidth(
1183 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1184 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1186 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1187 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1188 Changes[CellIter->Index].Spaces =
1189 MaxNetWidth - ThisNetWidth +
1190 (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1 : 0);
1194 for (
const auto *Next = CellIter->NextColumnElement; Next !=
nullptr;
1195 Next = Next->NextColumnElement) {
1196 if (RowCount > CellDescs.CellCounts.size())
1198 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1200 auto ThisNetWidth = getNetWidth(Start,
End, CellDescs.InitialSpaces);
1201 if (Changes[Next->Index].NewlinesBefore == 0) {
1202 Changes[Next->Index].Spaces =
1203 MaxNetWidth - ThisNetWidth +
1204 (Changes[Next->Index].Tok->isNot(tok::r_brace) ? 1 : 0);
1211 bool WhitespaceManager::isSplitCell(
const CellDescription &Cell) {
1214 for (
const auto *Next = Cell.NextColumnElement; Next !=
nullptr;
1215 Next = Next->NextColumnElement) {
1222 WhitespaceManager::CellDescriptions WhitespaceManager::getCells(
unsigned Start,
1227 SmallVector<unsigned> CellCounts;
1228 unsigned InitialSpaces = 0;
1229 unsigned InitialTokenLength = 0;
1230 unsigned EndSpaces = 0;
1231 SmallVector<CellDescription> Cells;
1232 const FormatToken *MatchingParen =
nullptr;
1233 for (
unsigned i = Start; i <
End; ++i) {
1234 auto &
C = Changes[i];
1235 if (
C.Tok->is(tok::l_brace))
1237 else if (
C.Tok->is(tok::r_brace))
1240 if (
C.Tok->is(tok::l_brace)) {
1242 MatchingParen =
C.Tok->MatchingParen;
1243 if (InitialSpaces == 0) {
1244 InitialSpaces =
C.Spaces +
C.TokenLength;
1245 InitialTokenLength =
C.TokenLength;
1247 for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
1248 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1249 InitialTokenLength += Changes[j].TokenLength;
1251 if (
C.NewlinesBefore == 0) {
1252 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1253 InitialTokenLength += Changes[j].TokenLength;
1256 }
else if (
C.Tok->is(tok::comma)) {
1258 Cells.back().EndIndex = i;
1259 if (
C.Tok->getNextNonComment()->isNot(tok::r_brace))
1262 }
else if (
Depth == 1) {
1263 if (
C.Tok == MatchingParen) {
1265 Cells.back().EndIndex = i;
1266 Cells.push_back(CellDescription{i, ++Cell, i + 1,
false,
nullptr});
1267 CellCounts.push_back(
C.Tok->Previous->isNot(tok::comma) ? Cell + 1
1270 const auto *NextNonComment =
C.Tok->getNextNonComment();
1271 while (NextNonComment->is(tok::comma))
1272 NextNonComment = NextNonComment->getNextNonComment();
1274 while (Changes[j].Tok != NextNonComment && j <
End)
1276 if (j <
End && Changes[j].NewlinesBefore == 0 &&
1277 Changes[j].Tok->isNot(tok::r_brace)) {
1278 Changes[j].NewlinesBefore = 1;
1280 Changes[j].Spaces = InitialSpaces - InitialTokenLength;
1282 }
else if (
C.Tok->is(tok::comment)) {
1284 C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 1 : 2;
1285 }
else if (
C.Tok->is(tok::l_brace)) {
1289 for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
1291 EndSpaces = Changes[j].Spaces;
1293 }
else if (
Depth == 0 &&
C.Tok->is(tok::r_brace)) {
1294 C.NewlinesBefore = 1;
1295 C.Spaces = EndSpaces;
1297 if (
C.Tok->StartsColumn) {
1300 bool HasSplit =
false;
1301 if (Changes[i].NewlinesBefore > 0) {
1317 if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) &&
1318 Changes[j - 1].NewlinesBefore > 0) {
1320 auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1321 if (LineLimit < Style.ColumnLimit) {
1322 Changes[i].NewlinesBefore = 0;
1323 Changes[i].Spaces = 1;
1327 while (Changes[i].NewlinesBefore > 0 && Changes[i].Tok ==
C.Tok) {
1328 Changes[i].Spaces = InitialSpaces;
1332 if (Changes[i].Tok !=
C.Tok)
1334 Cells.push_back(CellDescription{i, Cell, i, HasSplit,
nullptr});
1338 return linkCells({Cells, CellCounts, InitialSpaces});
1341 unsigned WhitespaceManager::calculateCellWidth(
unsigned Start,
unsigned End,
1342 bool WithSpaces)
const {
1343 unsigned CellWidth = 0;
1344 for (
auto i = Start; i <
End; i++) {
1345 if (Changes[i].NewlinesBefore > 0)
1347 CellWidth += Changes[i].TokenLength;
1348 CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
1353 void WhitespaceManager::alignToStartOfCell(
unsigned Start,
unsigned End) {
1354 if ((
End - Start) <= 1)
1358 for (
auto i = Start + 1; i <
End; i++)
1359 if (Changes[i].NewlinesBefore > 0)
1360 Changes[i].Spaces = Changes[Start].Spaces;
1363 WhitespaceManager::CellDescriptions
1364 WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1365 auto &Cells = CellDesc.Cells;
1366 for (
auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
1367 if (CellIter->NextColumnElement ==
nullptr &&
1368 ((CellIter + 1) != Cells.end())) {
1369 for (
auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
1370 if (NextIter->Cell == CellIter->Cell) {
1371 CellIter->NextColumnElement = &(*NextIter);
1377 return std::move(CellDesc);
1380 void WhitespaceManager::generateChanges() {
1381 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
1382 const Change &
C = Changes[i];
1383 if (i > 0 && Changes[i - 1].OriginalWhitespaceRange.getBegin() ==
1384 C.OriginalWhitespaceRange.getBegin()) {
1388 if (
C.CreateReplacement) {
1390 if (
C.ContinuesPPDirective) {
1391 appendEscapedNewlineText(ReplacementText,
C.NewlinesBefore,
1392 C.PreviousEndOfTokenColumn,
1393 C.EscapedNewlineColumn);
1395 appendNewlineText(ReplacementText,
C.NewlinesBefore);
1400 ReplacementText,
C.Tok->IndentLevel,
std::max(0,
C.Spaces),
1403 ReplacementText.append(
C.CurrentLinePrefix);
1404 storeReplacement(
C.OriginalWhitespaceRange, ReplacementText);
1409 void WhitespaceManager::storeReplacement(SourceRange Range, StringRef
Text) {
1414 WhitespaceLength) ==
Text) {
1417 auto Err = Replaces.
add(tooling::Replacement(
1428 unsigned Newlines) {
1430 Text.reserve(
Text.size() + 2 * Newlines);
1431 for (
unsigned i = 0; i < Newlines; ++i)
1432 Text.append(
"\r\n");
1434 Text.append(Newlines,
'\n');
1438 void WhitespaceManager::appendEscapedNewlineText(
1439 std::string &
Text,
unsigned Newlines,
unsigned PreviousEndOfTokenColumn,
1440 unsigned EscapedNewlineColumn) {
1443 std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
1444 for (
unsigned i = 0; i < Newlines; ++i) {
1445 Text.append(Spaces,
' ');
1446 Text.append(UseCRLF ?
"\\\r\n" :
"\\\n");
1447 Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
1453 unsigned IndentLevel,
unsigned Spaces,
1454 unsigned WhitespaceStartColumn,
1456 switch (Style.UseTab) {
1458 Text.append(Spaces,
' ');
1461 if (Style.TabWidth) {
1462 unsigned FirstTabWidth =
1463 Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
1466 if (Spaces < FirstTabWidth || Spaces == 1) {
1467 Text.append(Spaces,
' ');
1471 Spaces -= FirstTabWidth;
1474 Text.append(Spaces / Style.TabWidth,
'\t');
1475 Text.append(Spaces % Style.TabWidth,
' ');
1476 }
else if (Spaces == 1) {
1477 Text.append(Spaces,
' ');
1482 if (WhitespaceStartColumn == 0) {
1483 unsigned Indentation = IndentLevel * Style.IndentWidth;
1484 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1486 Text.append(Spaces,
' ');
1489 if (WhitespaceStartColumn == 0)
1490 Spaces = appendTabIndent(
Text, Spaces, Spaces);
1491 Text.append(Spaces,
' ');
1494 if (WhitespaceStartColumn == 0) {
1495 unsigned Indentation =
1496 IsAligned ? IndentLevel * Style.IndentWidth : Spaces;
1497 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1499 Text.append(Spaces,
' ');
1504 unsigned WhitespaceManager::appendTabIndent(
std::string &
Text,
unsigned Spaces,
1505 unsigned Indentation) {
1508 if (Indentation > Spaces)
1509 Indentation = Spaces;
1510 if (Style.TabWidth) {
1511 unsigned Tabs = Indentation / Style.TabWidth;
1512 Text.append(Tabs,
'\t');
1513 Spaces -= Tabs * Style.TabWidth;