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();
117void 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())
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) {
345 std::max(Changes[i].Spaces,
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) ||
441 Changes[i].Tok->is(tok::eof));
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;
454 Changes[
Previous + 1].Spaces -= Shift;
456 Changes[
Previous].StartOfTokenColumn += Shift;
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 bool HasInitialIndentAndNesting =
530 IndentAndNestingLevel > std::tuple<unsigned, unsigned, unsigned>();
535 unsigned CommasBeforeLastMatch = 0;
536 unsigned CommasBeforeMatch = 0;
539 bool FoundMatchOnLine =
false;
542 bool LineIsComment =
true;
551 auto AlignCurrentSequence = [&] {
552 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
554 WidthLeft + WidthAnchor, RightJustify, Matches,
564 unsigned i = StartAt;
565 for (
unsigned e = Changes.size(); i != e; ++i) {
566 if (Changes[i].indentAndNestingLevel() < IndentAndNestingLevel) {
567 if (!HasInitialIndentAndNesting)
575 AlignCurrentSequence();
576 IndentAndNestingLevel =
577 Changes[i].indentAndNestingLevel();
580 if (Changes[i].NewlinesBefore != 0) {
581 CommasBeforeMatch = 0;
585 bool EmptyLineBreak =
586 (Changes[i].NewlinesBefore > 1) && !ACS.AcrossEmptyLines;
591 !FoundMatchOnLine && !(LineIsComment && ACS.AcrossComments);
593 if (EmptyLineBreak || NoMatchBreak)
594 AlignCurrentSequence();
598 if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
599 !Changes[i - 1].Tok->is(tok::string_literal)) {
600 FoundMatchOnLine =
false;
602 LineIsComment =
true;
605 if (!Changes[i].Tok->is(tok::comment))
606 LineIsComment =
false;
608 if (Changes[i].Tok->is(tok::comma)) {
610 }
else if (Changes[i].indentAndNestingLevel() > IndentAndNestingLevel) {
613 AlignTokens(Style, Matches, Changes, i, ACS, RightJustify);
618 if (!Matches(Changes[i]))
623 if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
624 AlignCurrentSequence();
626 CommasBeforeLastMatch = CommasBeforeMatch;
627 FoundMatchOnLine =
true;
629 if (StartOfSequence == 0)
632 unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
633 unsigned ChangeWidthAnchor = 0;
634 unsigned ChangeWidthRight = 0;
636 if (ACS.PadOperators)
637 ChangeWidthAnchor = Changes[i].TokenLength;
639 ChangeWidthLeft += Changes[i].TokenLength;
641 ChangeWidthRight = Changes[i].TokenLength;
642 for (
unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) {
643 ChangeWidthRight += Changes[j].Spaces;
649 if (!Changes[j].IsInsideToken)
650 ChangeWidthRight += Changes[j].TokenLength;
654 unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
655 unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
656 unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
658 if (Style.ColumnLimit != 0 &&
659 Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
660 AlignCurrentSequence();
662 WidthLeft = ChangeWidthLeft;
663 WidthAnchor = ChangeWidthAnchor;
664 WidthRight = ChangeWidthRight;
667 WidthAnchor = NewAnchor;
668 WidthRight = NewRight;
673 AlignCurrentSequence();
685 unsigned &StartOfSequence,
unsigned &EndOfSequence,
unsigned &MinColumn,
686 unsigned &MaxColumn,
bool &FoundMatchOnLine,
689 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
691 FoundMatchOnLine =
false;
694 for (
unsigned I = StartOfSequence; I != EndOfSequence; ++I) {
695 if (Changes[I].NewlinesBefore > 0) {
697 FoundMatchOnLine =
false;
703 if (!FoundMatchOnLine && AlignMacrosMatches(Changes[I])) {
704 FoundMatchOnLine =
true;
705 Shift = MinColumn - Changes[I].StartOfTokenColumn;
706 Changes[I].Spaces += Shift;
710 Changes[I].StartOfTokenColumn += Shift;
711 if (I + 1 != Changes.size())
712 Changes[I + 1].PreviousEndOfTokenColumn += Shift;
722void WhitespaceManager::alignConsecutiveMacros() {
723 if (!Style.AlignConsecutiveMacros.Enabled)
726 auto AlignMacrosMatches = [](
const Change &
C) {
727 const FormatToken *Current =
C.Tok;
728 unsigned SpacesRequiredBefore = 1;
730 if (Current->SpacesRequiredBefore == 0 || !Current->Previous)
733 Current = Current->Previous;
737 if (Current->is(tok::r_paren) && Current->MatchingParen) {
738 Current = Current->MatchingParen->Previous;
739 SpacesRequiredBefore = 0;
742 if (!Current || !Current->is(tok::identifier))
745 if (!Current->Previous || !Current->Previous->is(tok::pp_define))
752 return Current->Next->SpacesRequiredBefore == SpacesRequiredBefore;
755 unsigned MinColumn = 0;
759 unsigned StartOfSequence = 0;
760 unsigned EndOfSequence = 0;
763 bool FoundMatchOnLine =
false;
766 bool LineIsComment =
true;
769 for (
unsigned E = Changes.size(); I != E; ++I) {
770 if (Changes[I].NewlinesBefore != 0) {
774 bool EmptyLineBreak = (Changes[I].NewlinesBefore > 1) &&
775 !Style.AlignConsecutiveMacros.AcrossEmptyLines;
781 !(LineIsComment && Style.AlignConsecutiveMacros.AcrossComments);
783 if (EmptyLineBreak || NoMatchBreak) {
785 FoundMatchOnLine, AlignMacrosMatches, Changes);
789 FoundMatchOnLine =
false;
790 LineIsComment =
true;
793 if (!Changes[I].Tok->is(tok::comment))
794 LineIsComment =
false;
796 if (!AlignMacrosMatches(Changes[I]))
799 FoundMatchOnLine =
true;
801 if (StartOfSequence == 0)
804 unsigned ChangeMinColumn = Changes[I].StartOfTokenColumn;
805 int LineLengthAfter = -Changes[I].Spaces;
806 for (
unsigned j = I; j != E && Changes[j].NewlinesBefore == 0; ++j)
807 LineLengthAfter += Changes[j].Spaces + Changes[j].TokenLength;
808 unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
810 MinColumn = std::max(MinColumn, ChangeMinColumn);
811 MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
816 FoundMatchOnLine, AlignMacrosMatches, Changes);
819void WhitespaceManager::alignConsecutiveAssignments() {
820 if (!Style.AlignConsecutiveAssignments.Enabled)
825 [&](
const Change &
C) {
827 if (
C.NewlinesBefore > 0)
831 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
835 FormatToken *
Previous =
C.Tok->getPreviousNonComment();
839 return Style.AlignConsecutiveAssignments.AlignCompound
841 : (
C.Tok->is(tok::equal) ||
845 (Style.isVerilog() &&
C.Tok->is(tok::lessequal) &&
848 Changes, 0, Style.AlignConsecutiveAssignments,
852void WhitespaceManager::alignConsecutiveBitFields() {
853 if (!Style.AlignConsecutiveBitFields.Enabled)
858 [&](Change
const &
C) {
860 if (
C.NewlinesBefore > 0)
864 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
867 return C.Tok->is(TT_BitFieldColon);
869 Changes, 0, Style.AlignConsecutiveBitFields);
872void WhitespaceManager::alignConsecutiveDeclarations() {
873 if (!Style.AlignConsecutiveDeclarations.Enabled)
878 [](Change
const &
C) {
879 if (
C.Tok->is(TT_FunctionDeclarationName))
881 if (
C.Tok->isNot(TT_StartOfName))
883 if (
C.Tok->Previous &&
884 C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
887 for (FormatToken *Next =
C.Tok->Next; Next; Next = Next->Next) {
888 if (Next->is(tok::comment))
890 if (Next->is(TT_PointerOrReference))
892 if (!Next->Tok.getIdentifierInfo())
894 if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
901 Changes, 0, Style.AlignConsecutiveDeclarations);
904void WhitespaceManager::alignChainedConditionals() {
905 if (Style.BreakBeforeTernaryOperators) {
908 [](Change
const &
C) {
910 return C.Tok->is(TT_ConditionalExpr) &&
911 ((
C.Tok->is(tok::question) && !
C.NewlinesBefore) ||
912 (
C.Tok->is(tok::colon) &&
C.Tok->Next &&
913 (
C.Tok->Next->FakeLParens.size() == 0 ||
918 static auto AlignWrappedOperand = [](Change
const &
C) {
919 FormatToken *
Previous =
C.Tok->getPreviousNonComment();
922 (
C.Tok->FakeLParens.size() == 0 ||
928 for (Change &
C : Changes)
929 if (AlignWrappedOperand(
C))
930 C.StartOfTokenColumn -= 2;
933 [
this](Change
const &
C) {
937 return (
C.Tok->is(TT_ConditionalExpr) &&
C.Tok->is(tok::question) &&
938 &
C != &Changes.back() && (&
C + 1)->NewlinesBefore == 0 &&
939 !(&
C + 1)->IsTrailingComment) ||
940 AlignWrappedOperand(
C);
946void WhitespaceManager::alignTrailingComments() {
947 unsigned MinColumn = 0;
949 unsigned StartOfSequence = 0;
950 bool BreakBeforeNext =
false;
951 unsigned Newlines = 0;
952 unsigned int NewLineThreshold = 1;
954 NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
956 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
957 if (Changes[i].StartOfBlockComment)
959 Newlines += Changes[i].NewlinesBefore;
960 if (!Changes[i].IsTrailingComment)
964 auto OriginalSpaces =
965 Changes[i].OriginalWhitespaceRange.getEnd().getRawEncoding() -
966 Changes[i].OriginalWhitespaceRange.getBegin().getRawEncoding() -
967 Changes[i].Tok->NewlinesBefore;
968 unsigned RestoredLineLength = Changes[i].StartOfTokenColumn +
969 Changes[i].TokenLength + OriginalSpaces;
972 if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit != 0)
974 Changes[i].Spaces = OriginalSpaces;
978 unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
979 unsigned ChangeMaxColumn;
981 if (Style.ColumnLimit == 0)
983 else if (Style.ColumnLimit >= Changes[i].TokenLength)
984 ChangeMaxColumn = Style.ColumnLimit - Changes[i].TokenLength;
986 ChangeMaxColumn = ChangeMinColumn;
990 if (!Changes[i].CreateReplacement)
991 ChangeMaxColumn = ChangeMinColumn;
993 if (i + 1 != e && Changes[i + 1].ContinuesPPDirective)
994 ChangeMaxColumn -= 2;
997 bool FollowsRBraceInColumn0 = i > 0 && Changes[i].NewlinesBefore == 0 &&
998 Changes[i - 1].Tok->is(tok::r_brace) &&
999 Changes[i - 1].StartOfTokenColumn == 0;
1000 bool WasAlignedWithStartOfNextLine =
false;
1001 if (Changes[i].NewlinesBefore >= 1) {
1003 Changes[i].OriginalWhitespaceRange.getEnd());
1004 for (
unsigned j = i + 1; j != e; ++j) {
1005 if (Changes[j].Tok->is(tok::comment))
1009 Changes[j].OriginalWhitespaceRange.getEnd());
1012 WasAlignedWithStartOfNextLine =
1013 CommentColumn == NextColumn ||
1014 CommentColumn == NextColumn + Style.IndentWidth;
1019 FollowsRBraceInColumn0) {
1020 alignTrailingComments(StartOfSequence, i, MinColumn);
1021 MinColumn = ChangeMinColumn;
1022 MaxColumn = ChangeMinColumn;
1023 StartOfSequence = i;
1024 }
else if (BreakBeforeNext || Newlines > NewLineThreshold ||
1025 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
1028 (Changes[i].NewlinesBefore == 1 && i > 0 &&
1029 !Changes[i - 1].IsTrailingComment) ||
1030 WasAlignedWithStartOfNextLine) {
1031 alignTrailingComments(StartOfSequence, i, MinColumn);
1032 MinColumn = ChangeMinColumn;
1033 MaxColumn = ChangeMaxColumn;
1034 StartOfSequence = i;
1036 MinColumn = std::max(MinColumn, ChangeMinColumn);
1037 MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
1039 BreakBeforeNext = (i == 0) || (Changes[i].NewlinesBefore > 1) ||
1042 (Changes[i].NewlinesBefore == 1 && StartOfSequence == i);
1045 alignTrailingComments(StartOfSequence, Changes.size(), MinColumn);
1048void WhitespaceManager::alignTrailingComments(
unsigned Start,
unsigned End,
1050 for (
unsigned i = Start; i != End; ++i) {
1052 if (Changes[i].IsTrailingComment)
1053 Shift = Column - Changes[i].StartOfTokenColumn;
1054 if (Changes[i].StartOfBlockComment) {
1055 Shift = Changes[i].IndentationOffset +
1056 Changes[i].StartOfBlockComment->StartOfTokenColumn -
1057 Changes[i].StartOfTokenColumn;
1061 Changes[i].Spaces +=
Shift;
1062 if (i + 1 != Changes.size())
1063 Changes[i + 1].PreviousEndOfTokenColumn +=
Shift;
1064 Changes[i].StartOfTokenColumn +=
Shift;
1068void WhitespaceManager::alignEscapedNewlines() {
1073 unsigned MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit;
1074 unsigned StartOfMacro = 0;
1075 for (
unsigned i = 1, e = Changes.size(); i < e; ++i) {
1076 Change &
C = Changes[i];
1077 if (
C.NewlinesBefore > 0) {
1078 if (
C.ContinuesPPDirective) {
1079 MaxEndOfLine = std::max(
C.PreviousEndOfTokenColumn + 2, MaxEndOfLine);
1081 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
1082 MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit;
1087 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
1090void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
1092 for (
unsigned i = Start; i < End; ++i) {
1093 Change &
C = Changes[i];
1094 if (
C.NewlinesBefore > 0) {
1095 assert(
C.ContinuesPPDirective);
1096 if (
C.PreviousEndOfTokenColumn + 1 > Column)
1097 C.EscapedNewlineColumn = 0;
1099 C.EscapedNewlineColumn = Column;
1104void WhitespaceManager::alignArrayInitializers() {
1108 for (
unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
1109 ChangeIndex < ChangeEnd; ++ChangeIndex) {
1110 auto &
C = Changes[ChangeIndex];
1111 if (
C.Tok->IsArrayInitializer) {
1112 bool FoundComplete =
false;
1113 for (
unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
1115 if (Changes[InsideIndex].Tok ==
C.Tok->MatchingParen) {
1116 alignArrayInitializers(ChangeIndex, InsideIndex + 1);
1117 ChangeIndex = InsideIndex + 1;
1118 FoundComplete =
true;
1123 ChangeIndex = ChangeEnd;
1128void WhitespaceManager::alignArrayInitializers(
unsigned Start,
unsigned End) {
1131 alignArrayInitializersRightJustified(getCells(Start, End));
1133 alignArrayInitializersLeftJustified(getCells(Start, End));
1136void WhitespaceManager::alignArrayInitializersRightJustified(
1137 CellDescriptions &&CellDescs) {
1138 if (!CellDescs.isRectangular())
1141 auto &Cells = CellDescs.Cells;
1143 auto *CellIter = Cells.begin();
1144 for (
auto i = 0
U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {
1145 unsigned NetWidth = 0
U;
1146 if (isSplitCell(*CellIter))
1147 NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1148 auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1150 if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1154 const auto *Next = CellIter;
1156 const FormatToken *
Previous = Changes[Next->Index].Tok->Previous;
1158 Changes[Next->Index].Spaces = 0;
1159 Changes[Next->Index].NewlinesBefore = 0;
1161 Next = Next->NextColumnElement;
1165 if (CellIter != Cells.begin()) {
1167 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1168 auto MaxNetWidth = getMaximumNetWidth(
1169 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1170 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1171 if (ThisNetWidth < MaxNetWidth)
1172 Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1174 auto Offset = std::distance(Cells.begin(), CellIter);
1175 for (
const auto *Next = CellIter->NextColumnElement; Next;
1176 Next = Next->NextColumnElement) {
1177 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1178 auto *End = Start +
Offset;
1179 ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1180 if (ThisNetWidth < MaxNetWidth)
1181 Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1187 calculateCellWidth(CellIter->Index, CellIter->EndIndex,
true) +
1189 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1190 Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
1191 Changes[CellIter->Index].Spaces += (i > 0) ? 1 : 0;
1193 alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1194 for (
const auto *Next = CellIter->NextColumnElement; Next;
1195 Next = Next->NextColumnElement) {
1197 calculateCellWidth(Next->Index, Next->EndIndex,
true) + NetWidth;
1198 if (Changes[Next->Index].NewlinesBefore == 0) {
1199 Changes[Next->Index].Spaces = (CellWidth - ThisWidth);
1200 Changes[Next->Index].Spaces += (i > 0) ? 1 : 0;
1202 alignToStartOfCell(Next->Index, Next->EndIndex);
1208void WhitespaceManager::alignArrayInitializersLeftJustified(
1209 CellDescriptions &&CellDescs) {
1211 if (!CellDescs.isRectangular())
1214 auto &Cells = CellDescs.Cells;
1216 auto *CellIter = Cells.begin();
1218 if (Changes[CellIter->Index].NewlinesBefore == 0)
1219 Changes[CellIter->Index].Spaces = 0;
1221 Changes[CellIter->Index].Spaces = CellDescs.InitialSpaces;
1223 for (
auto i = 1U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {
1224 auto MaxNetWidth = getMaximumNetWidth(
1225 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1226 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1228 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1229 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1230 Changes[CellIter->Index].Spaces =
1231 MaxNetWidth - ThisNetWidth +
1232 (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1 : 0);
1235 auto Offset = std::distance(Cells.begin(), CellIter);
1236 for (
const auto *Next = CellIter->NextColumnElement; Next;
1237 Next = Next->NextColumnElement) {
1238 if (RowCount > CellDescs.CellCounts.size())
1240 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1241 auto *End = Start +
Offset;
1242 auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1243 if (Changes[Next->Index].NewlinesBefore == 0) {
1244 Changes[Next->Index].Spaces =
1245 MaxNetWidth - ThisNetWidth +
1246 (Changes[Next->Index].Tok->isNot(tok::r_brace) ? 1 : 0);
1253bool WhitespaceManager::isSplitCell(
const CellDescription &Cell) {
1256 for (
const auto *Next = Cell.NextColumnElement; Next;
1257 Next = Next->NextColumnElement) {
1264WhitespaceManager::CellDescriptions WhitespaceManager::getCells(
unsigned Start,
1269 SmallVector<unsigned> CellCounts;
1270 unsigned InitialSpaces = 0;
1271 unsigned InitialTokenLength = 0;
1272 unsigned EndSpaces = 0;
1273 SmallVector<CellDescription> Cells;
1274 const FormatToken *MatchingParen =
nullptr;
1275 for (
unsigned i = Start; i < End; ++i) {
1276 auto &
C = Changes[i];
1277 if (
C.Tok->is(tok::l_brace))
1279 else if (
C.Tok->is(tok::r_brace))
1282 if (
C.Tok->is(tok::l_brace)) {
1284 MatchingParen =
C.Tok->MatchingParen;
1285 if (InitialSpaces == 0) {
1286 InitialSpaces =
C.Spaces +
C.TokenLength;
1287 InitialTokenLength =
C.TokenLength;
1289 for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
1290 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1291 InitialTokenLength += Changes[j].TokenLength;
1293 if (
C.NewlinesBefore == 0) {
1294 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1295 InitialTokenLength += Changes[j].TokenLength;
1298 }
else if (
C.Tok->is(tok::comma)) {
1300 Cells.back().EndIndex = i;
1301 if (
C.Tok->getNextNonComment()->isNot(tok::r_brace))
1304 }
else if (Depth == 1) {
1305 if (
C.Tok == MatchingParen) {
1307 Cells.back().EndIndex = i;
1308 Cells.push_back(CellDescription{i, ++Cell, i + 1,
false,
nullptr});
1309 CellCounts.push_back(
C.Tok->Previous->isNot(tok::comma) ? Cell + 1
1312 const auto *NextNonComment =
C.Tok->getNextNonComment();
1313 while (NextNonComment->is(tok::comma))
1314 NextNonComment = NextNonComment->getNextNonComment();
1316 while (Changes[j].Tok != NextNonComment && j < End)
1318 if (j < End && Changes[j].NewlinesBefore == 0 &&
1319 Changes[j].Tok->isNot(tok::r_brace)) {
1320 Changes[j].NewlinesBefore = 1;
1322 Changes[j].Spaces = InitialSpaces - InitialTokenLength;
1324 }
else if (
C.Tok->is(tok::comment)) {
1326 C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 1 : 2;
1327 }
else if (
C.Tok->is(tok::l_brace)) {
1331 for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
1333 EndSpaces = Changes[j].Spaces;
1335 }
else if (Depth == 0 &&
C.Tok->is(tok::r_brace)) {
1336 C.NewlinesBefore = 1;
1337 C.Spaces = EndSpaces;
1339 if (
C.Tok->StartsColumn) {
1342 bool HasSplit =
false;
1343 if (Changes[i].NewlinesBefore > 0) {
1359 if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) &&
1360 Changes[j - 1].NewlinesBefore > 0) {
1362 auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1363 if (LineLimit < Style.ColumnLimit) {
1364 Changes[i].NewlinesBefore = 0;
1365 Changes[i].Spaces = 1;
1369 while (Changes[i].NewlinesBefore > 0 && Changes[i].Tok ==
C.Tok) {
1370 Changes[i].Spaces = InitialSpaces;
1374 if (Changes[i].Tok !=
C.Tok)
1376 Cells.push_back(CellDescription{i, Cell, i, HasSplit,
nullptr});
1380 return linkCells({Cells, CellCounts, InitialSpaces});
1383unsigned WhitespaceManager::calculateCellWidth(
unsigned Start,
unsigned End,
1384 bool WithSpaces)
const {
1385 unsigned CellWidth = 0;
1386 for (
auto i = Start; i < End; i++) {
1387 if (Changes[i].NewlinesBefore > 0)
1389 CellWidth += Changes[i].TokenLength;
1390 CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
1395void WhitespaceManager::alignToStartOfCell(
unsigned Start,
unsigned End) {
1396 if ((End - Start) <= 1)
1400 for (
auto i = Start + 1; i < End; i++)
1401 if (Changes[i].NewlinesBefore > 0)
1402 Changes[i].Spaces = Changes[Start].Spaces;
1405WhitespaceManager::CellDescriptions
1406WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1407 auto &Cells = CellDesc.Cells;
1408 for (
auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
1409 if (!CellIter->NextColumnElement && (CellIter + 1) != Cells.end()) {
1410 for (
auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
1411 if (NextIter->Cell == CellIter->Cell) {
1412 CellIter->NextColumnElement = &(*NextIter);
1418 return std::move(CellDesc);
1421void WhitespaceManager::generateChanges() {
1422 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
1423 const Change &
C = Changes[i];
1424 if (i > 0 && Changes[i - 1].OriginalWhitespaceRange.getBegin() ==
1425 C.OriginalWhitespaceRange.getBegin()) {
1429 if (
C.CreateReplacement) {
1430 std::string ReplacementText =
C.PreviousLinePostfix;
1431 if (
C.ContinuesPPDirective) {
1432 appendEscapedNewlineText(ReplacementText,
C.NewlinesBefore,
1433 C.PreviousEndOfTokenColumn,
1434 C.EscapedNewlineColumn);
1436 appendNewlineText(ReplacementText,
C.NewlinesBefore);
1441 ReplacementText,
C.Tok->IndentLevel, std::max(0,
C.Spaces),
1442 std::max((
int)
C.StartOfTokenColumn,
C.Spaces) - std::max(0,
C.Spaces),
1444 ReplacementText.append(
C.CurrentLinePrefix);
1445 storeReplacement(
C.OriginalWhitespaceRange, ReplacementText);
1450void WhitespaceManager::storeReplacement(SourceRange Range, StringRef
Text) {
1455 WhitespaceLength) ==
Text) {
1458 auto Err = Replaces.
add(tooling::Replacement(
1463 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
1468void WhitespaceManager::appendNewlineText(std::string &
Text,
1469 unsigned Newlines) {
1471 Text.reserve(
Text.size() + 2 * Newlines);
1472 for (
unsigned i = 0; i < Newlines; ++i)
1473 Text.append(
"\r\n");
1475 Text.append(Newlines,
'\n');
1479void WhitespaceManager::appendEscapedNewlineText(
1480 std::string &
Text,
unsigned Newlines,
unsigned PreviousEndOfTokenColumn,
1481 unsigned EscapedNewlineColumn) {
1484 std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
1485 for (
unsigned i = 0; i < Newlines; ++i) {
1486 Text.append(Spaces,
' ');
1487 Text.append(UseCRLF ?
"\\\r\n" :
"\\\n");
1488 Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
1493void WhitespaceManager::appendIndentText(std::string &
Text,
1494 unsigned IndentLevel,
unsigned Spaces,
1495 unsigned WhitespaceStartColumn,
1497 switch (Style.UseTab) {
1499 Text.append(Spaces,
' ');
1502 if (Style.TabWidth) {
1503 unsigned FirstTabWidth =
1504 Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
1507 if (Spaces < FirstTabWidth || Spaces == 1) {
1508 Text.append(Spaces,
' ');
1512 Spaces -= FirstTabWidth;
1515 Text.append(Spaces / Style.TabWidth,
'\t');
1516 Text.append(Spaces % Style.TabWidth,
' ');
1517 }
else if (Spaces == 1) {
1518 Text.append(Spaces,
' ');
1523 if (WhitespaceStartColumn == 0) {
1524 unsigned Indentation = IndentLevel * Style.IndentWidth;
1525 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1527 Text.append(Spaces,
' ');
1530 if (WhitespaceStartColumn == 0)
1531 Spaces = appendTabIndent(
Text, Spaces, Spaces);
1532 Text.append(Spaces,
' ');
1535 if (WhitespaceStartColumn == 0) {
1536 unsigned Indentation =
1537 IsAligned ? IndentLevel * Style.IndentWidth : Spaces;
1538 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1540 Text.append(Spaces,
' ');
1545unsigned WhitespaceManager::appendTabIndent(std::string &
Text,
unsigned Spaces,
1546 unsigned Indentation) {
1549 if (Indentation > Spaces)
1550 Indentation = Spaces;
1551 if (Style.TabWidth) {
1552 unsigned Tabs = Indentation / Style.TabWidth;
1553 Text.append(Tabs,
'\t');
1554 Spaces -= Tabs * Style.TabWidth;
WhitespaceManager class manages whitespace around tokens and their replacements.
static CharSourceRange getCharRange(SourceRange R)
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
unsigned getFileOffset(SourceLocation SpellingLoc) const
Returns the offset from the start of the file that the specified SourceLocation represents.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
for(unsigned I=0, E=TL.getNumArgs();I !=E;++I)
@ C
Languages that the frontend can parse and compile.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))