15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallVector.h"
55 unsigned StartOfTokenColumn,
56 bool IsAligned,
bool InPPDirective) {
61 Spaces, StartOfTokenColumn, Newlines,
"",
"",
62 IsAligned, InPPDirective && !Tok.
IsFirst,
70 Changes.push_back(
Change(Tok,
false,
73 false, InPPDirective && !Tok.
IsFirst,
79 return Replaces.
add(Replacement);
83 size_t LF =
Text.count(
'\n');
84 size_t CR =
Text.count(
'\r') * 2;
85 return LF == CR ? DefaultToCRLF : CR > LF;
89 const FormatToken &Tok,
unsigned Offset,
unsigned ReplaceChars,
90 StringRef PreviousPostfix, StringRef CurrentPrefix,
bool InPPDirective,
91 unsigned Newlines,
int Spaces) {
98 std::max(0, Spaces), Newlines, PreviousPostfix, CurrentPrefix,
99 true, InPPDirective && !Tok.
IsFirst,
108 calculateLineBreakInformation();
109 alignConsecutiveMacros();
110 alignConsecutiveShortCaseStatements(
true);
111 alignConsecutiveShortCaseStatements(
false);
112 alignConsecutiveDeclarations();
113 alignConsecutiveBitFields();
114 alignConsecutiveAssignments();
116 alignConsecutiveTableGenBreakingDAGArgColons();
117 alignConsecutiveTableGenCondOperatorColons();
118 alignConsecutiveTableGenDefinitions();
120 alignChainedConditionals();
121 alignTrailingComments();
122 alignEscapedNewlines();
123 alignArrayInitializers();
129void WhitespaceManager::calculateLineBreakInformation() {
130 Changes[0].PreviousEndOfTokenColumn = 0;
131 Change *LastOutsideTokenChange = &Changes[0];
132 for (
unsigned I = 1, e = Changes.size(); I != e; ++I) {
133 auto &
C = Changes[I];
134 auto &
P = Changes[I - 1];
135 auto &PrevTokLength =
P.TokenLength;
137 C.OriginalWhitespaceRange.getBegin();
139 P.OriginalWhitespaceRange.getEnd();
140 unsigned OriginalWhitespaceStartOffset =
142 unsigned PreviousOriginalWhitespaceEndOffset =
144 assert(PreviousOriginalWhitespaceEndOffset <=
145 OriginalWhitespaceStartOffset);
146 const char *
const PreviousOriginalWhitespaceEndData =
148 StringRef
Text(PreviousOriginalWhitespaceEndData,
150 PreviousOriginalWhitespaceEndData);
172 auto NewlinePos =
Text.find_first_of(
'\n');
173 if (NewlinePos == StringRef::npos) {
174 PrevTokLength = OriginalWhitespaceStartOffset -
175 PreviousOriginalWhitespaceEndOffset +
176 C.PreviousLinePostfix.size() +
P.CurrentLinePrefix.size();
177 if (!
P.IsInsideToken)
178 PrevTokLength = std::min(PrevTokLength,
P.Tok->ColumnWidth);
180 PrevTokLength = NewlinePos +
P.CurrentLinePrefix.size();
185 if (
P.IsInsideToken &&
P.NewlinesBefore == 0)
186 LastOutsideTokenChange->TokenLength += PrevTokLength +
P.Spaces;
188 LastOutsideTokenChange = &
P;
190 C.PreviousEndOfTokenColumn =
P.StartOfTokenColumn + PrevTokLength;
192 P.IsTrailingComment =
193 (
C.NewlinesBefore > 0 ||
C.Tok->is(tok::eof) ||
194 (
C.IsInsideToken &&
C.Tok->is(tok::comment))) &&
195 P.Tok->is(tok::comment) &&
226 OriginalWhitespaceStart != PreviousOriginalWhitespaceEnd;
230 Changes.back().TokenLength = 0;
231 Changes.back().IsTrailingComment = Changes.back().Tok->is(tok::comment);
233 const WhitespaceManager::Change *LastBlockComment =
nullptr;
234 for (
auto &Change : Changes) {
238 if (Change.IsInsideToken && Change.NewlinesBefore == 0)
239 Change.IsTrailingComment =
false;
240 Change.StartOfBlockComment =
nullptr;
241 Change.IndentationOffset = 0;
242 if (Change.Tok->is(tok::comment)) {
243 if (Change.Tok->is(TT_LineComment) || !Change.IsInsideToken) {
244 LastBlockComment = &Change;
245 }
else if ((Change.StartOfBlockComment = LastBlockComment)) {
246 Change.IndentationOffset =
247 Change.StartOfTokenColumn -
248 Change.StartOfBlockComment->StartOfTokenColumn;
251 LastBlockComment =
nullptr;
259 SmallVector<bool, 16> ScopeStack;
260 int ConditionalsLevel = 0;
261 for (
auto &Change : Changes) {
262 for (
unsigned i = 0, e = Change.Tok->FakeLParens.size(); i != e; ++i) {
263 bool isNestedConditional =
265 !(i == 0 && Change.Tok->Previous &&
266 Change.Tok->Previous->is(TT_ConditionalExpr) &&
267 Change.Tok->Previous->is(tok::colon));
268 if (isNestedConditional)
270 ScopeStack.push_back(isNestedConditional);
273 Change.ConditionalsLevel = ConditionalsLevel;
275 for (
unsigned i = Change.Tok->FakeRParens; i > 0 && ScopeStack.size(); --i)
276 if (ScopeStack.pop_back_val())
288 unsigned Column,
bool RightJustify, F &&Matches,
290 bool FoundMatchOnLine =
false;
315 for (
unsigned i = Start; i != End; ++i) {
316 auto &CurrentChange = Changes[i];
317 if (ScopeStack.size() != 0 &&
318 CurrentChange.indentAndNestingLevel() <
319 Changes[ScopeStack.back()].indentAndNestingLevel()) {
320 ScopeStack.pop_back();
325 unsigned PreviousNonComment = i - 1;
326 while (PreviousNonComment > Start &&
327 Changes[PreviousNonComment].Tok->is(tok::comment)) {
328 --PreviousNonComment;
330 if (i != Start && CurrentChange.indentAndNestingLevel() >
331 Changes[PreviousNonComment].indentAndNestingLevel()) {
332 ScopeStack.push_back(i);
335 bool InsideNestedScope = ScopeStack.size() != 0;
336 bool ContinuedStringLiteral = i > Start &&
337 CurrentChange.Tok->is(tok::string_literal) &&
338 Changes[i - 1].Tok->is(tok::string_literal);
339 bool SkipMatchCheck = InsideNestedScope || ContinuedStringLiteral;
341 if (CurrentChange.NewlinesBefore > 0 && !SkipMatchCheck) {
343 FoundMatchOnLine =
false;
349 if (!FoundMatchOnLine && !SkipMatchCheck && Matches(CurrentChange)) {
350 FoundMatchOnLine =
true;
351 Shift =
Column - (RightJustify ? CurrentChange.TokenLength : 0) -
352 CurrentChange.StartOfTokenColumn;
353 CurrentChange.Spaces += Shift;
356 if (CurrentChange.NewlinesBefore == 0) {
357 CurrentChange.Spaces =
358 std::max(CurrentChange.Spaces,
359 static_cast<int>(CurrentChange.Tok->SpacesRequiredBefore));
368 if (InsideNestedScope && CurrentChange.NewlinesBefore > 0) {
369 unsigned ScopeStart = ScopeStack.back();
370 auto ShouldShiftBeAdded = [&] {
372 if (Changes[ScopeStart - 1].Tok->is(TT_FunctionDeclarationName))
376 if (Changes[ScopeStart - 1].Tok->is(TT_LambdaLBrace))
380 if (ScopeStart > Start + 1 &&
381 Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)) {
386 if (ScopeStart > Start + 1 &&
387 Changes[ScopeStart - 2].Tok->isOneOf(tok::identifier,
388 TT_TemplateCloser) &&
389 Changes[ScopeStart - 1].Tok->is(tok::l_paren) &&
390 Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)) {
391 if (CurrentChange.Tok->MatchingParen &&
392 CurrentChange.Tok->MatchingParen->is(TT_LambdaLBrace)) {
395 if (Changes[ScopeStart].NewlinesBefore > 0)
397 if (CurrentChange.Tok->is(tok::l_brace) &&
401 return Style.BinPackArguments;
405 if (CurrentChange.Tok->is(TT_ConditionalExpr))
409 if (CurrentChange.Tok->is(TT_DesignatedInitializerPeriod))
413 if (CurrentChange.Tok->Previous &&
414 CurrentChange.Tok->Previous->is(TT_ConditionalExpr)) {
419 if (ScopeStart > Start + 1 &&
420 Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
421 Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
422 CurrentChange.Tok->is(tok::l_brace) &&
428 if (ScopeStart > Start + 1 &&
429 Changes[ScopeStart - 2].Tok->isNot(tok::identifier) &&
430 Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
431 CurrentChange.Tok->isNot(tok::r_brace)) {
432 for (
unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
434 if (OuterScopeStart > Start &&
435 Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace)) {
439 if (Changes[ScopeStart].NewlinesBefore > 0)
445 if (Changes[ScopeStart - 1].Tok->is(TT_TemplateOpener))
451 if (ShouldShiftBeAdded())
452 CurrentChange.Spaces += Shift;
455 if (ContinuedStringLiteral)
456 CurrentChange.Spaces += Shift;
459 assert(Shift > 0 || Changes[i].NewlinesBefore > 0 ||
460 CurrentChange.Spaces >=
461 static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
462 CurrentChange.Tok->is(tok::eof));
464 CurrentChange.StartOfTokenColumn += Shift;
465 if (i + 1 != Changes.size())
466 Changes[i + 1].PreviousEndOfTokenColumn += Shift;
472 CurrentChange.Spaces != 0 && CurrentChange.Tok->isNot(tok::equal)) {
473 const bool ReferenceNotRightAligned =
479 assert(Changes[
Previous].Tok->isPointerOrReference());
480 if (Changes[
Previous].Tok->isNot(tok::star)) {
481 if (ReferenceNotRightAligned)
486 Changes[
Previous + 1].Spaces -= Shift;
488 Changes[
Previous].StartOfTokenColumn += Shift;
530 bool RightJustify =
false) {
539 unsigned WidthLeft = 0;
542 unsigned WidthAnchor = 0;
545 unsigned WidthRight = 0;
548 unsigned StartOfSequence = 0;
549 unsigned EndOfSequence = 0;
553 auto IndentAndNestingLevel = StartAt < Changes.size()
554 ? Changes[StartAt].indentAndNestingLevel()
555 : std::tuple<unsigned, unsigned, unsigned>();
560 unsigned CommasBeforeLastMatch = 0;
561 unsigned CommasBeforeMatch = 0;
564 bool FoundMatchOnLine =
false;
567 bool LineIsComment =
true;
576 auto AlignCurrentSequence = [&] {
577 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
579 WidthLeft + WidthAnchor, RightJustify, Matches,
589 unsigned i = StartAt;
590 for (
unsigned e = Changes.size(); i != e; ++i) {
591 auto &CurrentChange = Changes[i];
592 if (CurrentChange.indentAndNestingLevel() < IndentAndNestingLevel)
595 if (CurrentChange.NewlinesBefore != 0) {
596 CommasBeforeMatch = 0;
600 bool EmptyLineBreak =
601 (CurrentChange.NewlinesBefore > 1) && !ACS.AcrossEmptyLines;
606 !FoundMatchOnLine && !(LineIsComment && ACS.AcrossComments);
608 if (EmptyLineBreak || NoMatchBreak)
609 AlignCurrentSequence();
613 if (i == 0 || CurrentChange.Tok->isNot(tok::string_literal) ||
614 Changes[i - 1].Tok->isNot(tok::string_literal)) {
615 FoundMatchOnLine =
false;
617 LineIsComment =
true;
620 if (CurrentChange.Tok->isNot(tok::comment))
621 LineIsComment =
false;
623 if (CurrentChange.Tok->is(tok::comma)) {
625 }
else if (CurrentChange.indentAndNestingLevel() > IndentAndNestingLevel) {
628 AlignTokens(Style, Matches, Changes, i, ACS, RightJustify);
633 if (!Matches(CurrentChange))
638 if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
639 AlignCurrentSequence();
641 CommasBeforeLastMatch = CommasBeforeMatch;
642 FoundMatchOnLine =
true;
644 if (StartOfSequence == 0)
647 unsigned ChangeWidthLeft = CurrentChange.StartOfTokenColumn;
648 unsigned ChangeWidthAnchor = 0;
649 unsigned ChangeWidthRight = 0;
651 if (ACS.PadOperators)
652 ChangeWidthAnchor = CurrentChange.TokenLength;
654 ChangeWidthLeft += CurrentChange.TokenLength;
656 ChangeWidthRight = CurrentChange.TokenLength;
657 for (
unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) {
658 ChangeWidthRight += Changes[j].Spaces;
664 if (!Changes[j].IsInsideToken)
665 ChangeWidthRight += Changes[j].TokenLength;
669 unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
670 unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
671 unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
673 if (Style.ColumnLimit != 0 &&
674 Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
675 AlignCurrentSequence();
677 WidthLeft = ChangeWidthLeft;
678 WidthAnchor = ChangeWidthAnchor;
679 WidthRight = ChangeWidthRight;
682 WidthAnchor = NewAnchor;
683 WidthRight = NewRight;
688 AlignCurrentSequence();
700 unsigned &StartOfSequence,
unsigned &EndOfSequence,
unsigned &MinColumn,
703 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
704 bool FoundMatchOnLine =
false;
707 for (
unsigned I = StartOfSequence; I != EndOfSequence; ++I) {
708 if (Changes[I].NewlinesBefore > 0) {
710 FoundMatchOnLine =
false;
716 if (!FoundMatchOnLine && Matches(Changes[I])) {
717 FoundMatchOnLine =
true;
718 Shift = MinColumn - Changes[I].StartOfTokenColumn;
719 Changes[I].Spaces += Shift;
723 Changes[I].StartOfTokenColumn += Shift;
724 if (I + 1 != Changes.size())
725 Changes[I + 1].PreviousEndOfTokenColumn += Shift;
734void WhitespaceManager::alignConsecutiveMacros() {
735 if (!Style.AlignConsecutiveMacros.Enabled)
738 auto AlignMacrosMatches = [](
const Change &
C) {
739 const FormatToken *Current =
C.Tok;
740 unsigned SpacesRequiredBefore = 1;
742 if (Current->SpacesRequiredBefore == 0 || !Current->Previous)
745 Current = Current->Previous;
749 if (Current->is(tok::r_paren) && Current->MatchingParen) {
750 Current = Current->MatchingParen->Previous;
751 SpacesRequiredBefore = 0;
754 if (!Current || Current->isNot(tok::identifier))
757 if (!Current->Previous || Current->Previous->isNot(tok::pp_define))
764 return Current->Next->SpacesRequiredBefore == SpacesRequiredBefore;
767 unsigned MinColumn = 0;
770 unsigned StartOfSequence = 0;
771 unsigned EndOfSequence = 0;
774 bool FoundMatchOnLine =
false;
777 bool LineIsComment =
true;
780 for (
unsigned E = Changes.size(); I != E; ++I) {
781 if (Changes[I].NewlinesBefore != 0) {
785 bool EmptyLineBreak = (Changes[I].NewlinesBefore > 1) &&
786 !Style.AlignConsecutiveMacros.AcrossEmptyLines;
792 !(LineIsComment && Style.AlignConsecutiveMacros.AcrossComments);
794 if (EmptyLineBreak || NoMatchBreak) {
796 AlignMacrosMatches, Changes);
800 FoundMatchOnLine =
false;
801 LineIsComment =
true;
804 if (Changes[I].Tok->isNot(tok::comment))
805 LineIsComment =
false;
807 if (!AlignMacrosMatches(Changes[I]))
810 FoundMatchOnLine =
true;
812 if (StartOfSequence == 0)
815 unsigned ChangeMinColumn = Changes[I].StartOfTokenColumn;
816 MinColumn = std::max(MinColumn, ChangeMinColumn);
821 AlignMacrosMatches, Changes);
824void WhitespaceManager::alignConsecutiveAssignments() {
825 if (!Style.AlignConsecutiveAssignments.Enabled)
830 [&](
const Change &
C) {
832 if (
C.NewlinesBefore > 0)
836 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
840 FormatToken *
Previous =
C.Tok->getPreviousNonComment();
844 return Style.AlignConsecutiveAssignments.AlignCompound
846 : (
C.Tok->is(tok::equal) ||
850 (Style.isVerilog() &&
C.Tok->is(tok::lessequal) &&
853 Changes, 0, Style.AlignConsecutiveAssignments,
857void WhitespaceManager::alignConsecutiveBitFields() {
858 alignConsecutiveColons(Style.AlignConsecutiveBitFields, TT_BitFieldColon);
861void WhitespaceManager::alignConsecutiveColons(
862 const FormatStyle::AlignConsecutiveStyle &AlignStyle,
TokenType Type) {
863 if (!AlignStyle.Enabled)
868 [&](Change
const &
C) {
870 if (
C.NewlinesBefore > 0)
874 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
877 return C.Tok->is(Type);
879 Changes, 0, AlignStyle);
882void WhitespaceManager::alignConsecutiveShortCaseStatements(
bool IsExpr) {
883 if (!Style.AlignConsecutiveShortCaseStatements.Enabled ||
884 !(IsExpr ? Style.AllowShortCaseExpressionOnASingleLine
885 : Style.AllowShortCaseLabelsOnASingleLine)) {
889 const auto Type = IsExpr ? TT_CaseLabelArrow : TT_CaseLabelColon;
890 const auto &Option = Style.AlignConsecutiveShortCaseStatements;
891 const bool AlignArrowOrColon =
892 IsExpr ? Option.AlignCaseArrows : Option.AlignCaseColons;
894 auto Matches = [&](
const Change &
C) {
895 if (AlignArrowOrColon)
896 return C.Tok->is(Type);
902 return !
C.IsInsideToken &&
C.Tok->Previous &&
C.Tok->Previous->is(Type);
905 unsigned MinColumn = 0;
910 unsigned MinEmptyCaseColumn = 0;
913 unsigned StartOfSequence = 0;
914 unsigned EndOfSequence = 0;
917 bool FoundMatchOnLine =
false;
919 bool LineIsComment =
true;
920 bool LineIsEmptyCase =
false;
923 for (
unsigned E = Changes.size(); I != E; ++I) {
924 if (Changes[I].NewlinesBefore != 0) {
926 bool EmptyLineBreak =
927 (Changes[I].NewlinesBefore > 1) &&
928 !Style.AlignConsecutiveShortCaseStatements.AcrossEmptyLines;
935 Style.AlignConsecutiveShortCaseStatements.AcrossComments) &&
938 if (EmptyLineBreak || NoMatchBreak) {
941 MinEmptyCaseColumn = 0;
945 FoundMatchOnLine =
false;
946 LineIsComment =
true;
947 LineIsEmptyCase =
false;
950 if (Changes[I].Tok->isNot(tok::comment))
951 LineIsComment =
false;
953 if (Changes[I].Tok->is(Type)) {
955 !Changes[I].Tok->Next || Changes[I].Tok->Next->isTrailingComment();
957 if (LineIsEmptyCase) {
958 if (Style.AlignConsecutiveShortCaseStatements.AlignCaseColons) {
960 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn);
963 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn + 2);
968 if (!Matches(Changes[I]))
974 FoundMatchOnLine =
true;
976 if (StartOfSequence == 0)
979 EndOfSequence = I + 1;
981 MinColumn = std::max(MinColumn, Changes[I].StartOfTokenColumn);
984 MinColumn = std::max(MinColumn, MinEmptyCaseColumn);
991void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() {
992 alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons,
993 TT_TableGenDAGArgListColonToAlign);
996void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() {
997 alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons,
998 TT_TableGenCondOperatorColon);
1001void WhitespaceManager::alignConsecutiveTableGenDefinitions() {
1002 alignConsecutiveColons(Style.AlignConsecutiveTableGenDefinitionColons,
1003 TT_InheritanceColon);
1006void WhitespaceManager::alignConsecutiveDeclarations() {
1007 if (!Style.AlignConsecutiveDeclarations.Enabled)
1012 [&](Change
const &
C) {
1013 if (Style.AlignConsecutiveDeclarations.AlignFunctionPointers) {
1014 for (const auto *Prev = C.Tok->Previous; Prev; Prev = Prev->Previous)
1015 if (Prev->is(tok::equal))
1017 if (C.Tok->is(TT_FunctionTypeLParen))
1020 if (
C.Tok->is(TT_FunctionDeclarationName))
1022 if (
C.Tok->isNot(TT_StartOfName))
1024 if (
C.Tok->Previous &&
1025 C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
1028 for (FormatToken *Next =
C.Tok->Next; Next; Next = Next->Next) {
1029 if (Next->is(tok::comment))
1031 if (Next->is(TT_PointerOrReference))
1033 if (!Next->Tok.getIdentifierInfo())
1035 if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
1036 tok::kw_operator)) {
1042 Changes, 0, Style.AlignConsecutiveDeclarations);
1045void WhitespaceManager::alignChainedConditionals() {
1046 if (Style.BreakBeforeTernaryOperators) {
1049 [](Change
const &
C) {
1051 return C.Tok->is(TT_ConditionalExpr) &&
1052 ((
C.Tok->is(tok::question) && !
C.NewlinesBefore) ||
1053 (
C.Tok->is(tok::colon) &&
C.Tok->Next &&
1054 (
C.Tok->Next->FakeLParens.size() == 0 ||
1059 static auto AlignWrappedOperand = [](Change
const &
C) {
1060 FormatToken *
Previous =
C.Tok->getPreviousNonComment();
1063 (
C.Tok->FakeLParens.size() == 0 ||
1069 for (Change &
C : Changes)
1070 if (AlignWrappedOperand(
C))
1071 C.StartOfTokenColumn -= 2;
1074 [
this](Change
const &
C) {
1078 return (
C.Tok->is(TT_ConditionalExpr) &&
C.Tok->is(tok::question) &&
1079 &
C != &Changes.back() && (&
C + 1)->NewlinesBefore == 0 &&
1080 !(&
C + 1)->IsTrailingComment) ||
1081 AlignWrappedOperand(
C);
1087void WhitespaceManager::alignTrailingComments() {
1091 const int Size = Changes.size();
1093 int StartOfSequence = 0;
1094 bool BreakBeforeNext =
false;
1095 int NewLineThreshold = 1;
1097 NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
1099 for (
int I = 0, MaxColumn =
INT_MAX, Newlines = 0; I <
Size; ++I) {
1100 auto &
C = Changes[I];
1101 if (
C.StartOfBlockComment)
1103 Newlines +=
C.NewlinesBefore;
1104 if (!
C.IsTrailingComment)
1108 const int OriginalSpaces =
1109 C.OriginalWhitespaceRange.getEnd().getRawEncoding() -
1110 C.OriginalWhitespaceRange.getBegin().getRawEncoding() -
1111 C.Tok->LastNewlineOffset;
1112 assert(OriginalSpaces >= 0);
1113 const auto RestoredLineLength =
1114 C.StartOfTokenColumn +
C.TokenLength + OriginalSpaces;
1117 if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
1119 C.Spaces = OriginalSpaces;
1123 const int ChangeMinColumn =
C.StartOfTokenColumn;
1124 int ChangeMaxColumn;
1128 if (!
C.CreateReplacement)
1129 ChangeMaxColumn = ChangeMinColumn;
1130 else if (Style.ColumnLimit == 0)
1132 else if (Style.ColumnLimit >=
C.TokenLength)
1133 ChangeMaxColumn = Style.ColumnLimit -
C.TokenLength;
1135 ChangeMaxColumn = ChangeMinColumn;
1137 if (I + 1 < Size && Changes[I + 1].ContinuesPPDirective &&
1138 ChangeMaxColumn >= 2) {
1139 ChangeMaxColumn -= 2;
1142 bool WasAlignedWithStartOfNextLine =
false;
1143 if (
C.NewlinesBefore >= 1) {
1144 const auto CommentColumn =
1146 for (
int J = I + 1; J <
Size; ++J) {
1147 if (Changes[J].Tok->is(tok::comment))
1151 Changes[J].OriginalWhitespaceRange.getEnd());
1154 WasAlignedWithStartOfNextLine =
1155 CommentColumn == NextColumn ||
1156 CommentColumn == NextColumn + Style.IndentWidth;
1163 auto DontAlignThisComment = [](
const auto *Tok) {
1164 if (Tok->is(tok::semi)) {
1165 Tok = Tok->getPreviousNonComment();
1169 if (Tok->is(tok::r_paren)) {
1171 Tok = Tok->MatchingParen;
1174 Tok = Tok->getPreviousNonComment();
1177 if (Tok->is(TT_DoWhile)) {
1178 const auto *Prev = Tok->getPreviousNonComment();
1187 if (Tok->isNot(tok::r_brace))
1190 while (Tok->Previous && Tok->Previous->is(tok::r_brace))
1191 Tok = Tok->Previous;
1192 return Tok->NewlinesBefore > 0;
1195 if (I > 0 &&
C.NewlinesBefore == 0 &&
1196 DontAlignThisComment(Changes[I - 1].Tok)) {
1197 alignTrailingComments(StartOfSequence, I, MinColumn);
1202 StartOfSequence = I + 1;
1203 }
else if (BreakBeforeNext || Newlines > NewLineThreshold ||
1204 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
1207 (
C.NewlinesBefore == 1 && I > 0 &&
1208 !Changes[I - 1].IsTrailingComment) ||
1209 WasAlignedWithStartOfNextLine) {
1210 alignTrailingComments(StartOfSequence, I, MinColumn);
1211 MinColumn = ChangeMinColumn;
1212 MaxColumn = ChangeMaxColumn;
1213 StartOfSequence = I;
1215 MinColumn = std::max(MinColumn, ChangeMinColumn);
1216 MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
1218 BreakBeforeNext = (I == 0) || (
C.NewlinesBefore > 1) ||
1221 (
C.NewlinesBefore == 1 && StartOfSequence == I);
1224 alignTrailingComments(StartOfSequence, Size, MinColumn);
1227void WhitespaceManager::alignTrailingComments(
unsigned Start,
unsigned End,
1229 for (
unsigned i = Start; i != End; ++i) {
1231 if (Changes[i].IsTrailingComment)
1233 if (Changes[i].StartOfBlockComment) {
1234 Shift = Changes[i].IndentationOffset +
1235 Changes[i].StartOfBlockComment->StartOfTokenColumn -
1236 Changes[i].StartOfTokenColumn;
1240 Changes[i].Spaces +=
Shift;
1241 if (i + 1 != Changes.size())
1242 Changes[i + 1].PreviousEndOfTokenColumn +=
Shift;
1243 Changes[i].StartOfTokenColumn +=
Shift;
1247void WhitespaceManager::alignEscapedNewlines() {
1252 unsigned MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit;
1253 unsigned StartOfMacro = 0;
1254 for (
unsigned i = 1, e = Changes.size(); i < e; ++i) {
1255 Change &
C = Changes[i];
1256 if (
C.NewlinesBefore > 0) {
1257 if (
C.ContinuesPPDirective) {
1258 MaxEndOfLine = std::max(
C.PreviousEndOfTokenColumn + 2, MaxEndOfLine);
1260 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
1261 MaxEndOfLine = AlignLeft ? 0 : Style.ColumnLimit;
1266 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
1269void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
1271 for (
unsigned i = Start; i < End; ++i) {
1272 Change &
C = Changes[i];
1273 if (
C.NewlinesBefore > 0) {
1274 assert(
C.ContinuesPPDirective);
1275 if (
C.PreviousEndOfTokenColumn + 1 >
Column)
1276 C.EscapedNewlineColumn = 0;
1278 C.EscapedNewlineColumn =
Column;
1283void WhitespaceManager::alignArrayInitializers() {
1287 for (
unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
1288 ChangeIndex < ChangeEnd; ++ChangeIndex) {
1289 auto &
C = Changes[ChangeIndex];
1290 if (
C.Tok->IsArrayInitializer) {
1291 bool FoundComplete =
false;
1292 for (
unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
1294 if (Changes[InsideIndex].Tok ==
C.Tok->MatchingParen) {
1295 alignArrayInitializers(ChangeIndex, InsideIndex + 1);
1296 ChangeIndex = InsideIndex + 1;
1297 FoundComplete =
true;
1302 ChangeIndex = ChangeEnd;
1307void WhitespaceManager::alignArrayInitializers(
unsigned Start,
unsigned End) {
1310 alignArrayInitializersRightJustified(getCells(Start, End));
1312 alignArrayInitializersLeftJustified(getCells(Start, End));
1315void WhitespaceManager::alignArrayInitializersRightJustified(
1316 CellDescriptions &&CellDescs) {
1317 if (!CellDescs.isRectangular())
1320 const int BracePadding = Style.Cpp11BracedListStyle ? 0 : 1;
1321 auto &Cells = CellDescs.Cells;
1323 auto *CellIter = Cells.begin();
1324 for (
auto i = 0
U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {
1325 unsigned NetWidth = 0
U;
1326 if (isSplitCell(*CellIter))
1327 NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1328 auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1330 if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1334 const auto *Next = CellIter;
1336 const FormatToken *
Previous = Changes[Next->Index].Tok->Previous;
1338 Changes[Next->Index].Spaces = BracePadding;
1339 Changes[Next->Index].NewlinesBefore = 0;
1341 Next = Next->NextColumnElement;
1345 if (CellIter != Cells.begin()) {
1347 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1348 auto MaxNetWidth = getMaximumNetWidth(
1349 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1350 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1351 if (ThisNetWidth < MaxNetWidth)
1352 Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1354 auto Offset = std::distance(Cells.begin(), CellIter);
1355 for (
const auto *Next = CellIter->NextColumnElement; Next;
1356 Next = Next->NextColumnElement) {
1357 if (RowCount >= CellDescs.CellCounts.size())
1359 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1360 auto *End = Start + Offset;
1361 ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1362 if (ThisNetWidth < MaxNetWidth)
1363 Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1369 calculateCellWidth(CellIter->Index, CellIter->EndIndex,
true) +
1371 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1372 Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
1373 Changes[CellIter->Index].Spaces += (i > 0) ? 1 : BracePadding;
1375 alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1376 for (
const auto *Next = CellIter->NextColumnElement; Next;
1377 Next = Next->NextColumnElement) {
1379 calculateCellWidth(Next->Index, Next->EndIndex,
true) + NetWidth;
1380 if (Changes[Next->Index].NewlinesBefore == 0) {
1381 Changes[Next->Index].Spaces = (CellWidth - ThisWidth);
1382 Changes[Next->Index].Spaces += (i > 0) ? 1 : BracePadding;
1384 alignToStartOfCell(Next->Index, Next->EndIndex);
1390void WhitespaceManager::alignArrayInitializersLeftJustified(
1391 CellDescriptions &&CellDescs) {
1393 if (!CellDescs.isRectangular())
1396 const int BracePadding = Style.Cpp11BracedListStyle ? 0 : 1;
1397 auto &Cells = CellDescs.Cells;
1399 auto *CellIter = Cells.begin();
1401 for (
const auto *Next = CellIter; Next; Next = Next->NextColumnElement) {
1402 auto &Change = Changes[Next->Index];
1404 Change.NewlinesBefore == 0 ? BracePadding : CellDescs.InitialSpaces;
1407 for (
auto i = 1U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {
1408 auto MaxNetWidth = getMaximumNetWidth(
1409 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1410 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1412 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1413 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1414 Changes[CellIter->Index].Spaces =
1415 MaxNetWidth - ThisNetWidth +
1416 (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1
1420 auto Offset = std::distance(Cells.begin(), CellIter);
1421 for (
const auto *Next = CellIter->NextColumnElement; Next;
1422 Next = Next->NextColumnElement) {
1423 if (RowCount >= CellDescs.CellCounts.size())
1425 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1426 auto *End = Start + Offset;
1427 auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1428 if (Changes[Next->Index].NewlinesBefore == 0) {
1429 Changes[Next->Index].Spaces =
1430 MaxNetWidth - ThisNetWidth +
1431 (Changes[Next->Index].Tok->isNot(tok::r_brace) ? 1 : BracePadding);
1438bool WhitespaceManager::isSplitCell(
const CellDescription &Cell) {
1441 for (
const auto *Next = Cell.NextColumnElement; Next;
1442 Next = Next->NextColumnElement) {
1449WhitespaceManager::CellDescriptions WhitespaceManager::getCells(
unsigned Start,
1454 SmallVector<unsigned> CellCounts;
1455 unsigned InitialSpaces = 0;
1456 unsigned InitialTokenLength = 0;
1457 unsigned EndSpaces = 0;
1458 SmallVector<CellDescription> Cells;
1459 const FormatToken *MatchingParen =
nullptr;
1460 for (
unsigned i = Start; i < End; ++i) {
1461 auto &
C = Changes[i];
1462 if (
C.Tok->is(tok::l_brace))
1464 else if (
C.Tok->is(tok::r_brace))
1467 if (
C.Tok->is(tok::l_brace)) {
1469 MatchingParen =
C.Tok->MatchingParen;
1470 if (InitialSpaces == 0) {
1471 InitialSpaces =
C.Spaces +
C.TokenLength;
1472 InitialTokenLength =
C.TokenLength;
1474 for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
1475 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1476 InitialTokenLength += Changes[j].TokenLength;
1478 if (
C.NewlinesBefore == 0) {
1479 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1480 InitialTokenLength += Changes[j].TokenLength;
1483 }
else if (
C.Tok->is(tok::comma)) {
1485 Cells.back().EndIndex = i;
1486 if (
const auto *Next =
C.Tok->getNextNonComment();
1487 Next && Next->isNot(tok::r_brace)) {
1491 }
else if (Depth == 1) {
1492 if (
C.Tok == MatchingParen) {
1494 Cells.back().EndIndex = i;
1495 Cells.push_back(CellDescription{i, ++Cell, i + 1,
false,
nullptr});
1496 CellCounts.push_back(
C.Tok->Previous->isNot(tok::comma) ? Cell + 1
1499 const auto *NextNonComment =
C.Tok->getNextNonComment();
1500 while (NextNonComment && NextNonComment->is(tok::comma))
1501 NextNonComment = NextNonComment->getNextNonComment();
1503 while (j < End && Changes[j].Tok != NextNonComment)
1505 if (j < End && Changes[j].NewlinesBefore == 0 &&
1506 Changes[j].Tok->isNot(tok::r_brace)) {
1507 Changes[j].NewlinesBefore = 1;
1509 Changes[j].Spaces = InitialSpaces - InitialTokenLength;
1511 }
else if (
C.Tok->is(tok::comment) &&
C.Tok->NewlinesBefore == 0) {
1513 C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 1 : 2;
1514 }
else if (
C.Tok->is(tok::l_brace)) {
1518 for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
1520 EndSpaces = Changes[j].Spaces;
1522 }
else if (Depth == 0 &&
C.Tok->is(tok::r_brace)) {
1523 C.NewlinesBefore = 1;
1524 C.Spaces = EndSpaces;
1526 if (
C.Tok->StartsColumn) {
1529 bool HasSplit =
false;
1530 if (Changes[i].NewlinesBefore > 0) {
1546 if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) &&
1547 Changes[j - 1].NewlinesBefore > 0) {
1549 auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1550 if (LineLimit < Style.ColumnLimit) {
1551 Changes[i].NewlinesBefore = 0;
1552 Changes[i].Spaces = 1;
1556 while (Changes[i].NewlinesBefore > 0 && Changes[i].Tok ==
C.Tok) {
1557 Changes[i].Spaces = InitialSpaces;
1561 if (Changes[i].Tok !=
C.Tok)
1563 Cells.push_back(CellDescription{i, Cell, i, HasSplit,
nullptr});
1567 return linkCells({Cells, CellCounts, InitialSpaces});
1570unsigned WhitespaceManager::calculateCellWidth(
unsigned Start,
unsigned End,
1571 bool WithSpaces)
const {
1572 unsigned CellWidth = 0;
1573 for (
auto i = Start; i < End; i++) {
1574 if (Changes[i].NewlinesBefore > 0)
1576 CellWidth += Changes[i].TokenLength;
1577 CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
1582void WhitespaceManager::alignToStartOfCell(
unsigned Start,
unsigned End) {
1583 if ((End - Start) <= 1)
1587 for (
auto i = Start + 1; i < End; i++)
1588 if (Changes[i].NewlinesBefore > 0)
1589 Changes[i].Spaces = Changes[Start].Spaces;
1592WhitespaceManager::CellDescriptions
1593WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1594 auto &Cells = CellDesc.Cells;
1595 for (
auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
1596 if (!CellIter->NextColumnElement && (CellIter + 1) != Cells.end()) {
1597 for (
auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
1598 if (NextIter->Cell == CellIter->Cell) {
1599 CellIter->NextColumnElement = &(*NextIter);
1605 return std::move(CellDesc);
1608void WhitespaceManager::generateChanges() {
1609 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
1610 const Change &
C = Changes[i];
1612 auto Last = Changes[i - 1].OriginalWhitespaceRange;
1613 auto New = Changes[i].OriginalWhitespaceRange;
1655 if (
Last.getBegin() == New.getBegin() &&
1656 (
Last.getEnd() !=
Last.getBegin() ||
1657 New.getEnd() == New.getBegin())) {
1661 if (
C.CreateReplacement) {
1662 std::string ReplacementText =
C.PreviousLinePostfix;
1663 if (
C.ContinuesPPDirective) {
1664 appendEscapedNewlineText(ReplacementText,
C.NewlinesBefore,
1665 C.PreviousEndOfTokenColumn,
1666 C.EscapedNewlineColumn);
1668 appendNewlineText(ReplacementText,
C.NewlinesBefore);
1673 ReplacementText,
C.Tok->IndentLevel, std::max(0,
C.Spaces),
1674 std::max((
int)
C.StartOfTokenColumn,
C.Spaces) - std::max(0,
C.Spaces),
1676 ReplacementText.append(
C.CurrentLinePrefix);
1677 storeReplacement(
C.OriginalWhitespaceRange, ReplacementText);
1682void WhitespaceManager::storeReplacement(SourceRange
Range, StringRef
Text) {
1687 WhitespaceLength) ==
Text) {
1690 auto Err = Replaces.
add(tooling::Replacement(
1695 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
1700void WhitespaceManager::appendNewlineText(std::string &
Text,
1701 unsigned Newlines) {
1703 Text.reserve(
Text.size() + 2 * Newlines);
1704 for (
unsigned i = 0; i < Newlines; ++i)
1705 Text.append(
"\r\n");
1707 Text.append(Newlines,
'\n');
1711void WhitespaceManager::appendEscapedNewlineText(
1712 std::string &
Text,
unsigned Newlines,
unsigned PreviousEndOfTokenColumn,
1713 unsigned EscapedNewlineColumn) {
1716 std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
1717 for (
unsigned i = 0; i < Newlines; ++i) {
1718 Text.append(Spaces,
' ');
1719 Text.append(UseCRLF ?
"\\\r\n" :
"\\\n");
1720 Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
1725void WhitespaceManager::appendIndentText(std::string &
Text,
1726 unsigned IndentLevel,
unsigned Spaces,
1727 unsigned WhitespaceStartColumn,
1729 switch (Style.UseTab) {
1731 Text.append(Spaces,
' ');
1734 if (Style.TabWidth) {
1735 unsigned FirstTabWidth =
1736 Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
1739 if (Spaces < FirstTabWidth || Spaces == 1) {
1740 Text.append(Spaces,
' ');
1744 Spaces -= FirstTabWidth;
1747 Text.append(Spaces / Style.TabWidth,
'\t');
1748 Text.append(Spaces % Style.TabWidth,
' ');
1749 }
else if (Spaces == 1) {
1750 Text.append(Spaces,
' ');
1755 if (WhitespaceStartColumn == 0) {
1756 unsigned Indentation = IndentLevel * Style.IndentWidth;
1757 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1759 Text.append(Spaces,
' ');
1762 if (WhitespaceStartColumn == 0)
1763 Spaces = appendTabIndent(
Text, Spaces, Spaces);
1764 Text.append(Spaces,
' ');
1767 if (WhitespaceStartColumn == 0) {
1768 unsigned Indentation =
1769 IsAligned ? IndentLevel * Style.IndentWidth : Spaces;
1770 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1772 Text.append(Spaces,
' ');
1777unsigned WhitespaceManager::appendTabIndent(std::string &
Text,
unsigned Spaces,
1778 unsigned Indentation) {
1781 if (Indentation > Spaces)
1782 Indentation = Spaces;
1783 if (Style.TabWidth) {
1784 unsigned Tabs = Indentation / Style.TabWidth;
1785 Text.append(Tabs,
'\t');
1786 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 getEnd() const
SourceLocation getBegin() const
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
for(const auto &A :T->param_types())