15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallVector.h"
25 return SourceMgr.isBeforeInTranslationUnit(
30 SourceMgr.isBeforeInTranslationUnit(
58 unsigned StartOfTokenColumn,
59 bool IsAligned,
bool InPPDirective,
60 unsigned IndentedFromColumn) {
65 Spaces, StartOfTokenColumn, IndentedFromColumn,
67 InPPDirective && !
Tok.IsFirst,
76 Tok,
false,
Tok.WhitespaceRange, 0,
77 Tok.OriginalColumn, 0,
Tok.NewlinesBefore,
"",
"",
78 false, InPPDirective && !
Tok.IsFirst,
84 return Replaces.add(Replacement);
88 size_t LF =
Text.count(
'\n');
89 size_t CR =
Text.count(
'\r') * 2;
90 return LF == CR ? DefaultToCRLF : CR > LF;
95 StringRef PreviousPostfix, StringRef CurrentPrefix,
bool InPPDirective,
104 PreviousPostfix, CurrentPrefix,
105 true, InPPDirective && !
Tok.IsFirst,
114 calculateLineBreakInformation();
115 alignConsecutiveMacros();
116 alignConsecutiveShortCaseStatements(
true);
117 alignConsecutiveShortCaseStatements(
false);
118 alignConsecutiveDeclarations();
119 alignConsecutiveBitFields();
120 alignConsecutiveAssignments();
121 if (Style.isTableGen()) {
122 alignConsecutiveTableGenBreakingDAGArgColons();
123 alignConsecutiveTableGenCondOperatorColons();
124 alignConsecutiveTableGenDefinitions();
126 alignChainedConditionals();
127 alignTrailingComments();
128 alignEscapedNewlines();
129 alignArrayInitializers();
135void WhitespaceManager::calculateLineBreakInformation() {
136 Changes[0].PreviousEndOfTokenColumn = 0;
137 Change *LastOutsideTokenChange = &Changes[0];
138 for (
unsigned I = 1, e = Changes.size(); I != e; ++I) {
139 auto &
C = Changes[I];
140 auto &P = Changes[I - 1];
141 auto &PrevTokLength = P.TokenLength;
143 C.OriginalWhitespaceRange.getBegin();
145 P.OriginalWhitespaceRange.getEnd();
146 unsigned OriginalWhitespaceStartOffset =
147 SourceMgr.getFileOffset(OriginalWhitespaceStart);
148 unsigned PreviousOriginalWhitespaceEndOffset =
149 SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd);
150 assert(PreviousOriginalWhitespaceEndOffset <=
151 OriginalWhitespaceStartOffset);
152 const char *
const PreviousOriginalWhitespaceEndData =
153 SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd);
154 StringRef
Text(PreviousOriginalWhitespaceEndData,
155 SourceMgr.getCharacterData(OriginalWhitespaceStart) -
156 PreviousOriginalWhitespaceEndData);
178 auto NewlinePos =
Text.find_first_of(
'\n');
179 if (NewlinePos == StringRef::npos) {
180 PrevTokLength = OriginalWhitespaceStartOffset -
181 PreviousOriginalWhitespaceEndOffset +
182 C.PreviousLinePostfix.size() + P.CurrentLinePrefix.size();
183 if (!P.IsInsideToken)
184 PrevTokLength = std::min(PrevTokLength, P.Tok->ColumnWidth);
186 PrevTokLength = NewlinePos + P.CurrentLinePrefix.size();
191 if (P.IsInsideToken && P.NewlinesBefore == 0)
192 LastOutsideTokenChange->TokenLength += PrevTokLength + P.Spaces;
194 LastOutsideTokenChange = &P;
196 C.PreviousEndOfTokenColumn = P.StartOfTokenColumn + PrevTokLength;
198 P.IsTrailingComment =
199 (
C.NewlinesBefore > 0 ||
C.Tok->is(tok::eof) ||
200 (
C.IsInsideToken &&
C.Tok->is(tok::comment))) &&
201 P.Tok->is(tok::comment) &&
232 OriginalWhitespaceStart != PreviousOriginalWhitespaceEnd;
236 Changes.back().TokenLength = 0;
237 Changes.back().IsTrailingComment = Changes.back().Tok->is(tok::comment);
239 const WhitespaceManager::Change *LastBlockComment =
nullptr;
240 for (
auto &
Change : Changes) {
250 LastBlockComment = &
Change;
257 LastBlockComment =
nullptr;
265 SmallVector<bool, 16> ScopeStack;
266 int ConditionalsLevel = 0;
267 for (
auto &
Change : Changes) {
269 bool isNestedConditional =
274 if (isNestedConditional)
276 ScopeStack.push_back(isNestedConditional);
282 if (ScopeStack.pop_back_val())
293 auto &FirstChange = Changes[Start];
294 const int ColumnChange = Spaces - FirstChange.Spaces;
296 if (ColumnChange == 0)
299 FirstChange.Spaces += ColumnChange;
300 FirstChange.StartOfTokenColumn += ColumnChange;
302 for (
auto I = Start + 1; I < Changes.size(); I++) {
303 auto &Change = Changes[I];
305 Change.PreviousEndOfTokenColumn += ColumnChange;
307 if (Change.NewlinesBefore > 0)
310 Change.StartOfTokenColumn += ColumnChange;
320 assert(Delta > 0 || (
abs(Delta) <= Changes[Start].Spaces));
330 unsigned Column,
bool RightJustify,
333 unsigned OriginalMatchColumn = 0;
361 for (
unsigned i = Start; i != End; ++i) {
362 auto &CurrentChange = Changes[i];
363 if (!Matches.empty() && Matches[0] < i)
364 Matches.consume_front();
365 assert(Matches.empty() || Matches[0] >= i);
366 while (!ScopeStack.empty() &&
367 CurrentChange.indentAndNestingLevel() < ScopeStack.back()) {
368 ScopeStack.pop_back();
372 if (ScopeStack.size() == 1u && CurrentChange.NewlinesBefore != 0u &&
373 CurrentChange.indentAndNestingLevel() > ScopeStack[0] &&
374 CurrentChange.IndentedFromColumn < OriginalMatchColumn) {
375 ScopeStack.push_back(CurrentChange.indentAndNestingLevel());
378 bool InsideNestedScope =
379 !ScopeStack.empty() &&
380 (CurrentChange.indentAndNestingLevel() > ScopeStack[0] ||
381 (CurrentChange.indentAndNestingLevel() == ScopeStack[0] &&
382 CurrentChange.IndentedFromColumn >= OriginalMatchColumn));
384 if (CurrentChange.NewlinesBefore > 0 && !InsideNestedScope)
390 if (!Matches.empty() && Matches[0] == i) {
391 OriginalMatchColumn = CurrentChange.StartOfTokenColumn;
392 Shift =
Column - (RightJustify ? CurrentChange.TokenLength : 0) -
393 CurrentChange.StartOfTokenColumn;
394 ScopeStack = {CurrentChange.indentAndNestingLevel()};
403 if ((!Matches.empty() && Matches[0] == i) ||
404 (ScopeStack.size() == 1u && CurrentChange.NewlinesBefore > 0 &&
405 InsideNestedScope)) {
406 CurrentChange.IndentedFromColumn += Shift;
412 CurrentChange.Spaces >=
413 static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
414 CurrentChange.Tok->is(tok::eof));
418 if ((Style.PointerAlignment == FormatStyle::PAS_Right ||
419 Style.ReferenceAlignment == FormatStyle::RAS_Right) &&
420 CurrentChange.Spaces != 0 &&
421 CurrentChange.Tok->isNoneOf(tok::equal, tok::r_paren,
422 TT_TemplateCloser)) {
423 const bool ReferenceNotRightAligned =
424 Style.ReferenceAlignment != FormatStyle::RAS_Right &&
425 Style.ReferenceAlignment != FormatStyle::RAS_Pointer;
429 assert(Changes[
Previous].
Tok->isPointerOrReference());
431 if (ReferenceNotRightAligned)
433 }
else if (Style.PointerAlignment != FormatStyle::PAS_Right) {
479template <
typename F,
bool SimpleCheck = false>
483 const FormatStyle::AlignConsecutiveStyle &ACS = {},
484 bool RightJustify =
false) {
495 unsigned WidthLeft = 0;
498 unsigned WidthAnchor = 0;
501 unsigned WidthRight = 0;
504 unsigned StartOfSequence = 0;
505 unsigned EndOfSequence = 0;
512 const auto IndentAndNestingLevel =
513 StartAt < Changes.size() ? Changes[StartAt].indentAndNestingLevel()
514 : std::tuple<unsigned, unsigned, unsigned>();
519 unsigned CommasBeforeLastMatch = 0;
520 unsigned CommasBeforeMatch = 0;
523 std::optional<unsigned> MatchingColumn;
526 bool LineIsComment =
true;
535 auto AlignCurrentSequence = [&] {
536 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
538 WidthLeft + WidthAnchor, RightJustify, MatchedIndices,
546 MatchedIndices.clear();
549 unsigned I = StartAt;
550 const auto E = Changes.size();
551 for (; I != E; ++I) {
552 auto &CurrentChange = Changes[I];
553 if (CurrentChange.indentAndNestingLevel() < IndentAndNestingLevel)
556 if (CurrentChange.NewlinesBefore != 0) {
557 CommasBeforeMatch = 0;
561 bool EmptyLineBreak =
562 (CurrentChange.NewlinesBefore > 1) && !ACS.AcrossEmptyLines;
567 !MatchingColumn && !(LineIsComment && ACS.AcrossComments);
569 if (EmptyLineBreak || NoMatchBreak)
570 AlignCurrentSequence();
574 if (MatchingColumn && CurrentChange.IndentedFromColumn < *MatchingColumn)
575 MatchingColumn.reset();
576 LineIsComment =
true;
579 if (CurrentChange.Tok->isNot(tok::comment))
580 LineIsComment =
false;
583 if (CurrentChange.Tok->is(tok::comma)) {
585 }
else if (CurrentChange.indentAndNestingLevel() >
586 IndentAndNestingLevel) {
588 const auto StoppedAt =
589 AlignTokens(Style, Matches, Changes, I, ACS, RightJustify);
595 if (!Matches(CurrentChange))
600 if ((CurrentChange.NewlinesBefore == 0U && MatchingColumn) ||
601 CommasBeforeMatch != CommasBeforeLastMatch) {
602 MatchedIndices.push_back(I);
603 AlignCurrentSequence();
606 CommasBeforeLastMatch = CommasBeforeMatch;
607 MatchingColumn = CurrentChange.StartOfTokenColumn;
609 if (StartOfSequence == 0)
612 unsigned ChangeWidthLeft = CurrentChange.StartOfTokenColumn;
613 unsigned ChangeWidthAnchor = 0;
614 unsigned ChangeWidthRight = 0;
615 unsigned CurrentChangeWidthRight = 0;
617 if (ACS.PadOperators)
618 ChangeWidthAnchor = CurrentChange.TokenLength;
620 ChangeWidthLeft += CurrentChange.TokenLength;
622 CurrentChangeWidthRight = CurrentChange.TokenLength;
623 const FormatToken *MatchingParenToEncounter =
nullptr;
624 for (
unsigned J = I + 1;
625 J != E && (Changes[J].NewlinesBefore == 0 ||
626 MatchingParenToEncounter || Changes[J].IsAligned);
628 const auto &
Change = Changes[J];
631 if (
Tok->MatchingParen) {
632 if (
Tok->isOneOf(tok::l_paren, tok::l_brace, tok::l_square,
633 TT_TemplateOpener) &&
634 !MatchingParenToEncounter) {
639 MatchingParenToEncounter =
Tok->MatchingParen;
640 }
else if (MatchingParenToEncounter ==
Tok->MatchingParen) {
641 MatchingParenToEncounter =
nullptr;
646 ChangeWidthRight = std::max(ChangeWidthRight, CurrentChangeWidthRight);
647 const auto ChangeWidthStart = ChangeWidthLeft + ChangeWidthAnchor;
658 CurrentChangeWidthRight =
Change.
Spaces - ChangeWidthStart;
672 ChangeWidthRight = std::max(ChangeWidthRight, CurrentChangeWidthRight);
675 unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
676 unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
677 unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
679 if (Style.ColumnLimit != 0 &&
680 Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
681 AlignCurrentSequence();
683 WidthLeft = ChangeWidthLeft;
684 WidthAnchor = ChangeWidthAnchor;
685 WidthRight = ChangeWidthRight;
688 WidthAnchor = NewAnchor;
689 WidthRight = NewRight;
691 MatchedIndices.push_back(I);
696 for (EndOfSequence = I;
697 EndOfSequence < E && Changes[EndOfSequence].NewlinesBefore == 0;
700 AlignCurrentSequence();
714 unsigned &StartOfSequence,
unsigned &EndOfSequence,
unsigned &MinColumn,
717 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
718 bool FoundMatchOnLine =
false;
720 for (
unsigned I = StartOfSequence; I != EndOfSequence; ++I) {
722 FoundMatchOnLine =
false;
727 if (!FoundMatchOnLine && Matches(Changes[I])) {
728 FoundMatchOnLine =
true;
729 int Shift = MinColumn - Changes[I].StartOfTokenColumn;
740void WhitespaceManager::alignConsecutiveMacros() {
741 if (!Style.AlignConsecutiveMacros.Enabled)
744 auto AlignMacrosMatches = [](
const Change &
C) {
748 if (Current->SpacesRequiredBefore == 0 || !Current->Previous)
751 Current = Current->Previous;
755 if (Current->is(tok::r_paren)) {
764 }
else if (Current->Next->SpacesRequiredBefore != 1) {
770 return Current->endsSequence(tok::identifier, tok::pp_define);
774 Style, AlignMacrosMatches, Changes, 0, Style.AlignConsecutiveMacros);
777void WhitespaceManager::alignConsecutiveAssignments() {
778 if (!Style.AlignConsecutiveAssignments.Enabled)
785 if (
C.NewlinesBefore > 0)
789 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
797 return Style.AlignConsecutiveAssignments.AlignCompound
799 : (
C.Tok->is(tok::equal) ||
803 (Style.isVerilog() &&
C.Tok->is(tok::lessequal) &&
806 Changes, 0, Style.AlignConsecutiveAssignments,
810void WhitespaceManager::alignConsecutiveBitFields() {
811 alignConsecutiveColons(Style.AlignConsecutiveBitFields, TT_BitFieldColon);
814void WhitespaceManager::alignConsecutiveColons(
815 const FormatStyle::AlignConsecutiveStyle &AlignStyle,
TokenType Type) {
816 if (!AlignStyle.Enabled)
823 if (
C.NewlinesBefore > 0)
827 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
830 return C.Tok->is(
Type);
832 Changes, 0, AlignStyle);
835void WhitespaceManager::alignConsecutiveShortCaseStatements(
bool IsExpr) {
836 if (!Style.AlignConsecutiveShortCaseStatements.Enabled ||
837 !(IsExpr ? Style.AllowShortCaseExpressionOnASingleLine
838 : Style.AllowShortCaseLabelsOnASingleLine)) {
842 const auto Type = IsExpr ? TT_CaseLabelArrow : TT_CaseLabelColon;
843 const auto &Option = Style.AlignConsecutiveShortCaseStatements;
844 const bool AlignArrowOrColon =
845 IsExpr ? Option.AlignCaseArrows : Option.AlignCaseColons;
847 auto Matches = [&](
const Change &
C) {
848 if (AlignArrowOrColon)
849 return C.Tok->is(
Type);
855 return !
C.IsInsideToken &&
C.Tok->Previous &&
C.Tok->Previous->is(
Type);
858 unsigned MinColumn = 0;
863 unsigned MinEmptyCaseColumn = 0;
866 unsigned StartOfSequence = 0;
867 unsigned EndOfSequence = 0;
870 bool FoundMatchOnLine =
false;
872 bool LineIsComment =
true;
873 bool LineIsEmptyCase =
false;
876 for (
unsigned E = Changes.size(); I != E; ++I) {
879 bool EmptyLineBreak =
880 (Changes[I].NewlinesBefore > 1) &&
881 !Style.AlignConsecutiveShortCaseStatements.AcrossEmptyLines;
888 Style.AlignConsecutiveShortCaseStatements.AcrossComments) &&
891 if (EmptyLineBreak || NoMatchBreak) {
894 MinEmptyCaseColumn = 0;
898 FoundMatchOnLine =
false;
899 LineIsComment =
true;
900 LineIsEmptyCase =
false;
903 if (Changes[I].
Tok->isNot(tok::comment))
904 LineIsComment =
false;
906 if (Changes[I].
Tok->is(
Type)) {
908 !Changes[I].Tok->Next || Changes[I].Tok->Next->isTrailingComment();
910 if (LineIsEmptyCase) {
911 if (Style.AlignConsecutiveShortCaseStatements.AlignCaseColons) {
913 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn);
916 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn + 2);
921 if (!Matches(Changes[I]))
927 FoundMatchOnLine =
true;
929 if (StartOfSequence == 0)
932 EndOfSequence = I + 1;
934 MinColumn = std::max(MinColumn, Changes[I].StartOfTokenColumn);
937 MinColumn = std::max(MinColumn, MinEmptyCaseColumn);
944void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() {
945 alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons,
946 TT_TableGenDAGArgListColonToAlign);
949void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() {
950 alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons,
951 TT_TableGenCondOperatorColon);
954void WhitespaceManager::alignConsecutiveTableGenDefinitions() {
955 alignConsecutiveColons(Style.AlignConsecutiveTableGenDefinitionColons,
956 TT_InheritanceColon);
959void WhitespaceManager::alignConsecutiveDeclarations() {
960 if (!Style.AlignConsecutiveDeclarations.Enabled)
966 if (
C.Tok->is(TT_FunctionTypeLParen))
967 return Style.AlignConsecutiveDeclarations.AlignFunctionPointers;
968 if (
C.Tok->is(TT_FunctionDeclarationName))
969 return Style.AlignConsecutiveDeclarations.AlignFunctionDeclarations;
970 if (
C.Tok->isNot(TT_StartOfName))
972 if (
C.Tok->Previous &&
973 C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
977 if (
Next->is(tok::comment))
979 if (
Next->is(TT_PointerOrReference))
981 if (!
Next->Tok.getIdentifierInfo())
983 if (
Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
990 Changes, 0, Style.AlignConsecutiveDeclarations);
993void WhitespaceManager::alignChainedConditionals() {
994 if (Style.BreakBeforeTernaryOperators) {
999 return C.Tok->is(TT_ConditionalExpr) &&
1000 ((
C.Tok->is(tok::question) && !
C.NewlinesBefore) ||
1001 (
C.Tok->is(tok::colon) &&
C.Tok->Next &&
1002 (
C.Tok->Next->FakeLParens.empty() ||
1007 static auto AlignWrappedOperand = [](
Change const &
C) {
1011 (
C.Tok->FakeLParens.empty() ||
1018 if (AlignWrappedOperand(
C))
1019 C.StartOfTokenColumn -= 2;
1026 return (
C.Tok->is(TT_ConditionalExpr) &&
C.Tok->is(tok::question) &&
1027 &
C != &Changes.back() && (&
C + 1)->NewlinesBefore == 0 &&
1028 !(&
C + 1)->IsTrailingComment) ||
1029 AlignWrappedOperand(
C);
1035void WhitespaceManager::alignTrailingComments() {
1036 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Never)
1039 const int Size = Changes.size();
1044 int StartOfSequence = 0;
1045 bool BreakBeforeNext =
false;
1046 bool IsInPP = Changes.front().Tok->Tok.is(tok::hash);
1047 int NewLineThreshold = 1;
1048 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always)
1049 NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
1052 auto &
C = Changes[I];
1053 if (
C.StartOfBlockComment)
1055 if (
C.NewlinesBefore != 0) {
1057 const bool WasInPP = std::exchange(
1058 IsInPP,
C.Tok->Tok.is(tok::hash) || (IsInPP &&
C.IsTrailingComment) ||
1059 C.ContinuesPPDirective);
1060 if (IsInPP != WasInPP && !Style.AlignTrailingComments.AlignPPAndNotPP) {
1061 alignTrailingComments(StartOfSequence, I, MinColumn);
1064 StartOfSequence = I;
1068 if (!
C.IsTrailingComment)
1071 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Leave) {
1072 const int OriginalSpaces =
1073 C.OriginalWhitespaceRange.getEnd().getRawEncoding() -
1074 C.OriginalWhitespaceRange.getBegin().getRawEncoding() -
1075 C.Tok->LastNewlineOffset;
1076 assert(OriginalSpaces >= 0);
1077 const auto RestoredLineLength =
1078 C.StartOfTokenColumn +
C.TokenLength + OriginalSpaces;
1081 if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
1085 C.NewlinesBefore > 0 ?
C.Tok->OriginalColumn : OriginalSpaces;
1086 setChangeSpaces(I, Spaces);
1090 const int ChangeMinColumn =
C.StartOfTokenColumn;
1091 int ChangeMaxColumn;
1095 if (!
C.CreateReplacement)
1096 ChangeMaxColumn = ChangeMinColumn;
1097 else if (Style.ColumnLimit == 0)
1099 else if (Style.ColumnLimit >=
C.TokenLength)
1100 ChangeMaxColumn = Style.ColumnLimit -
C.TokenLength;
1102 ChangeMaxColumn = ChangeMinColumn;
1104 if (I + 1 < Size && Changes[I + 1].ContinuesPPDirective &&
1105 ChangeMaxColumn >= 2) {
1106 ChangeMaxColumn -= 2;
1109 bool WasAlignedWithStartOfNextLine =
false;
1110 if (
C.NewlinesBefore >= 1) {
1111 const auto CommentColumn =
1112 SourceMgr.getSpellingColumnNumber(
C.OriginalWhitespaceRange.getEnd());
1113 for (
int J = I + 1; J <
Size; ++J) {
1114 if (Changes[J].
Tok->is(tok::comment))
1117 const auto NextColumn = SourceMgr.getSpellingColumnNumber(
1118 Changes[J].OriginalWhitespaceRange.getEnd());
1121 WasAlignedWithStartOfNextLine =
1122 CommentColumn == NextColumn ||
1123 CommentColumn == NextColumn + Style.IndentWidth;
1130 auto DontAlignThisComment = [](
const auto *
Tok) {
1131 if (
Tok->is(tok::semi)) {
1132 Tok =
Tok->getPreviousNonComment();
1136 if (
Tok->is(tok::r_paren)) {
1138 Tok =
Tok->MatchingParen;
1141 Tok =
Tok->getPreviousNonComment();
1144 if (
Tok->is(TT_DoWhile)) {
1145 const auto *Prev =
Tok->getPreviousNonComment();
1154 if (
Tok->isNot(tok::r_brace))
1157 while (
Tok->Previous &&
Tok->Previous->is(tok::r_brace))
1159 return Tok->NewlinesBefore > 0;
1162 if (I > 0 &&
C.NewlinesBefore == 0 &&
1163 DontAlignThisComment(Changes[I - 1].
Tok)) {
1164 alignTrailingComments(StartOfSequence, I, MinColumn);
1169 StartOfSequence = I + 1;
1170 }
else if (BreakBeforeNext ||
Newlines > NewLineThreshold ||
1171 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
1174 (
C.NewlinesBefore == 1 && I > 0 &&
1175 !Changes[I - 1].IsTrailingComment) ||
1176 WasAlignedWithStartOfNextLine) {
1177 alignTrailingComments(StartOfSequence, I, MinColumn);
1178 MinColumn = ChangeMinColumn;
1179 MaxColumn = ChangeMaxColumn;
1180 StartOfSequence = I;
1182 MinColumn = std::max(MinColumn, ChangeMinColumn);
1183 MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
1185 BreakBeforeNext = (I == 0) || (
C.NewlinesBefore > 1) ||
1188 (
C.NewlinesBefore == 1 && StartOfSequence == I);
1191 alignTrailingComments(StartOfSequence, Size, MinColumn);
1194void WhitespaceManager::alignTrailingComments(
unsigned Start,
unsigned End,
1196 for (
unsigned i = Start; i != End; ++i) {
1198 if (Changes[i].IsTrailingComment)
1200 if (Changes[i].StartOfBlockComment) {
1201 Shift = Changes[i].IndentationOffset +
1202 Changes[i].StartOfBlockComment->StartOfTokenColumn -
1203 Changes[i].StartOfTokenColumn;
1208 setChangeSpaces(i, Changes[i].Spaces + Shift);
1212void WhitespaceManager::alignEscapedNewlines() {
1213 const auto Align = Style.AlignEscapedNewlines;
1214 if (Align == FormatStyle::ENAS_DontAlign)
1217 const bool WithLastLine = Align == FormatStyle::ENAS_LeftWithLastLine;
1218 const bool AlignLeft = Align == FormatStyle::ENAS_Left || WithLastLine;
1219 const auto MaxColumn = Style.ColumnLimit;
1220 unsigned MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1221 unsigned StartOfMacro = 0;
1222 for (
unsigned i = 1, e = Changes.size(); i < e; ++i) {
1224 if (
C.NewlinesBefore == 0 && (!WithLastLine ||
C.Tok->isNot(tok::eof)))
1227 const auto BackslashColumn =
C.PreviousEndOfTokenColumn + 2;
1228 if (InPPDirective ||
1229 (WithLastLine && (MaxColumn == 0 || BackslashColumn <= MaxColumn))) {
1230 MaxEndOfLine = std::max(BackslashColumn, MaxEndOfLine);
1232 if (!InPPDirective) {
1233 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
1234 MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1238 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
1241void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
1243 for (
unsigned i = Start; i < End; ++i) {
1245 if (
C.NewlinesBefore > 0) {
1246 assert(
C.ContinuesPPDirective);
1247 if (
C.PreviousEndOfTokenColumn + 1 >
Column)
1248 C.EscapedNewlineColumn = 0;
1250 C.EscapedNewlineColumn =
Column;
1255void WhitespaceManager::alignArrayInitializers() {
1256 if (Style.AlignArrayOfStructures == FormatStyle::AIAS_None)
1259 for (
unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
1260 ChangeIndex < ChangeEnd; ++ChangeIndex) {
1261 auto &
C = Changes[ChangeIndex];
1262 if (
C.Tok->IsArrayInitializer) {
1263 bool FoundComplete =
false;
1264 for (
unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
1266 const auto *
Tok = Changes[InsideIndex].Tok;
1267 if (
Tok->is(tok::pp_define))
1269 if (
Tok ==
C.Tok->MatchingParen) {
1270 alignArrayInitializers(ChangeIndex, InsideIndex + 1);
1271 ChangeIndex = InsideIndex + 1;
1272 FoundComplete =
true;
1277 ChangeIndex = ChangeEnd;
1282void WhitespaceManager::alignArrayInitializers(
unsigned Start,
unsigned End) {
1284 if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Right)
1285 alignArrayInitializersRightJustified(getCells(Start, End));
1286 else if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Left)
1287 alignArrayInitializersLeftJustified(getCells(Start, End));
1290void WhitespaceManager::alignArrayInitializersRightJustified(
1291 CellDescriptions &&CellDescs) {
1292 if (!CellDescs.isRectangular())
1295 const int BracePadding =
1296 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? 0 : 1;
1297 auto &Cells = CellDescs.Cells;
1299 auto *CellIter = Cells.begin();
1300 for (
auto i = 0U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {
1301 unsigned NetWidth = 0U;
1302 if (isSplitCell(*CellIter))
1303 NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1304 auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1306 if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1310 const auto *
Next = CellIter;
1314 Changes[
Next->Index].NewlinesBefore = 0;
1315 setChangeSpaces(
Next->Index, BracePadding);
1321 if (CellIter != Cells.begin()) {
1323 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1324 auto MaxNetWidth = getMaximumNetWidth(
1325 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1326 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1327 if (ThisNetWidth < MaxNetWidth)
1328 setChangeSpaces(CellIter->Index, MaxNetWidth - ThisNetWidth);
1330 auto Offset = std::distance(Cells.begin(), CellIter);
1331 for (
const auto *
Next = CellIter->NextColumnElement;
Next;
1333 if (RowCount >= CellDescs.CellCounts.size())
1335 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1336 auto *End = Start + Offset;
1337 ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1338 if (ThisNetWidth < MaxNetWidth)
1339 setChangeSpaces(
Next->Index, MaxNetWidth - ThisNetWidth);
1345 calculateCellWidth(CellIter->Index, CellIter->EndIndex,
true) +
1347 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1348 int Spaces = (CellWidth - (ThisWidth + NetWidth));
1349 Spaces += (i > 0) ? 1 : BracePadding;
1351 setChangeSpaces(CellIter->Index, Spaces);
1353 alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1354 for (
const auto *
Next = CellIter->NextColumnElement;
Next;
1357 calculateCellWidth(
Next->Index,
Next->EndIndex,
true) + NetWidth;
1358 if (Changes[
Next->Index].NewlinesBefore == 0) {
1359 int Spaces = (CellWidth - ThisWidth);
1360 Spaces += (i > 0) ? 1 : BracePadding;
1362 setChangeSpaces(
Next->Index, Spaces);
1364 alignToStartOfCell(
Next->Index,
Next->EndIndex);
1370void WhitespaceManager::alignArrayInitializersLeftJustified(
1371 CellDescriptions &&CellDescs) {
1373 if (!CellDescs.isRectangular())
1376 const int BracePadding =
1377 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? 0 : 1;
1378 auto &Cells = CellDescs.Cells;
1380 auto *CellIter = Cells.begin();
1386 setChangeSpaces(
Next->Index, Spaces);
1389 for (
auto i = 1U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {
1390 auto MaxNetWidth = getMaximumNetWidth(
1391 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1392 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1394 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1395 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1397 MaxNetWidth - ThisNetWidth +
1398 (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1
1400 setChangeSpaces(CellIter->Index, Spaces);
1403 auto Offset = std::distance(Cells.begin(), CellIter);
1404 for (
const auto *
Next = CellIter->NextColumnElement;
Next;
1406 if (RowCount >= CellDescs.CellCounts.size())
1408 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1409 auto *End = Start + Offset;
1410 auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1411 if (Changes[
Next->Index].NewlinesBefore == 0) {
1413 MaxNetWidth - ThisNetWidth +
1414 (Changes[
Next->Index].Tok->isNot(tok::r_brace) ? 1 : BracePadding);
1415 setChangeSpaces(
Next->Index, Spaces);
1422bool WhitespaceManager::isSplitCell(
const CellDescription &Cell) {
1425 for (
const auto *
Next = Cell.NextColumnElement;
Next;
1433WhitespaceManager::CellDescriptions WhitespaceManager::getCells(
unsigned Start,
1438 SmallVector<unsigned> CellCounts;
1439 unsigned InitialSpaces = 0;
1440 unsigned InitialTokenLength = 0;
1441 unsigned EndSpaces = 0;
1442 SmallVector<CellDescription> Cells;
1444 for (
unsigned i = Start; i < End; ++i) {
1445 auto &
C = Changes[i];
1446 if (
C.Tok->is(tok::l_brace))
1448 else if (
C.Tok->is(tok::r_brace))
1451 if (
C.Tok->is(tok::l_brace)) {
1454 if (InitialSpaces == 0) {
1455 InitialSpaces =
C.Spaces +
C.TokenLength;
1456 InitialTokenLength =
C.TokenLength;
1458 for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
1459 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1460 InitialTokenLength += Changes[j].TokenLength;
1462 if (
C.NewlinesBefore == 0) {
1463 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1464 InitialTokenLength += Changes[j].TokenLength;
1467 }
else if (
C.Tok->is(tok::comma)) {
1469 Cells.back().EndIndex = i;
1470 if (
const auto *
Next =
C.Tok->getNextNonComment();
1471 Next &&
Next->isNot(tok::r_brace)) {
1475 }
else if (Depth == 1) {
1478 Cells.back().EndIndex = i;
1479 Cells.push_back(CellDescription{i, ++Cell, i + 1,
false,
nullptr});
1480 CellCounts.push_back(
C.Tok->Previous->isNot(tok::comma) ? Cell + 1
1483 const auto *NextNonComment =
C.Tok->getNextNonComment();
1484 while (NextNonComment && NextNonComment->is(tok::comma))
1485 NextNonComment = NextNonComment->getNextNonComment();
1487 while (j < End && Changes[j].
Tok != NextNonComment)
1490 Changes[j].
Tok->isNot(tok::r_brace)) {
1491 Changes[j].NewlinesBefore = 1;
1493 setChangeSpaces(j, InitialSpaces - InitialTokenLength);
1495 }
else if (
C.Tok->is(tok::comment) &&
C.Tok->NewlinesBefore == 0) {
1497 setChangeSpaces(i, Changes[i - 1].
Tok->is(tok::comma) ? 1 : 2);
1498 }
else if (
C.Tok->is(tok::l_brace)) {
1502 for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
1504 EndSpaces = Changes[j].Spaces;
1506 }
else if (Depth == 0 &&
C.Tok->is(tok::r_brace)) {
1507 C.NewlinesBefore = 1;
1508 setChangeSpaces(i, EndSpaces);
1510 if (
C.Tok->StartsColumn) {
1513 bool HasSplit =
false;
1530 if ((j - 1) > Start && Changes[j].
Tok->is(tok::comma) &&
1531 Changes[j - 1].NewlinesBefore > 0) {
1533 auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1534 if (LineLimit < Style.ColumnLimit) {
1535 Changes[i].NewlinesBefore = 0;
1536 setChangeSpaces(i, 1);
1541 setChangeSpaces(i, InitialSpaces);
1545 if (Changes[i].
Tok !=
C.Tok)
1547 Cells.push_back(CellDescription{i, Cell, i, HasSplit,
nullptr});
1551 return linkCells({Cells, CellCounts, InitialSpaces});
1554unsigned WhitespaceManager::calculateCellWidth(
unsigned Start,
unsigned End,
1555 bool WithSpaces)
const {
1556 unsigned CellWidth = 0;
1557 for (
auto i = Start; i < End; i++) {
1560 CellWidth += Changes[i].TokenLength;
1561 CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
1566void WhitespaceManager::alignToStartOfCell(
unsigned Start,
unsigned End) {
1567 if ((End - Start) <= 1)
1571 for (
auto i = Start + 1; i < End; i++)
1573 setChangeSpaces(i, Changes[Start].Spaces);
1576WhitespaceManager::CellDescriptions
1577WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1578 auto &Cells = CellDesc.Cells;
1579 for (
auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
1580 if (!CellIter->NextColumnElement && (CellIter + 1) != Cells.end()) {
1581 for (
auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
1582 if (NextIter->Cell == CellIter->Cell) {
1583 CellIter->NextColumnElement = &(*NextIter);
1589 return std::move(CellDesc);
1592void WhitespaceManager::setChangeSpaces(
unsigned Start,
unsigned Spaces) {
1596void WhitespaceManager::generateChanges() {
1597 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
1600 auto Last = Changes[i - 1].OriginalWhitespaceRange;
1601 auto New = Changes[i].OriginalWhitespaceRange;
1643 if (
Last.getBegin() ==
New.getBegin() &&
1644 (
Last.getEnd() !=
Last.getBegin() ||
1645 New.getEnd() ==
New.getBegin())) {
1649 if (
C.CreateReplacement) {
1650 std::string ReplacementText =
C.PreviousLinePostfix;
1651 if (
C.ContinuesPPDirective) {
1652 appendEscapedNewlineText(ReplacementText,
C.NewlinesBefore,
1653 C.PreviousEndOfTokenColumn,
1654 C.EscapedNewlineColumn);
1656 appendNewlineText(ReplacementText,
C);
1661 ReplacementText,
C.Tok->IndentLevel, std::max(0,
C.Spaces),
1662 std::max((
int)
C.StartOfTokenColumn,
C.Spaces) - std::max(0,
C.Spaces),
1664 ReplacementText.append(
C.CurrentLinePrefix);
1665 storeReplacement(
C.OriginalWhitespaceRange, ReplacementText);
1670void WhitespaceManager::storeReplacement(SourceRange Range, StringRef
Text) {
1671 unsigned WhitespaceLength = SourceMgr.getFileOffset(
Range.getEnd()) -
1672 SourceMgr.getFileOffset(
Range.getBegin());
1674 if (StringRef(SourceMgr.getCharacterData(
Range.getBegin()),
1675 WhitespaceLength) ==
Text) {
1678 auto Err = Replaces.add(tooling::Replacement(
1683 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
1688void WhitespaceManager::appendNewlineText(std::string &
Text,
const Change &
C) {
1689 if (
C.NewlinesBefore <= 0)
1692 StringRef Newline = UseCRLF ?
"\r\n" :
"\n";
1693 Text.append(Newline);
1695 if (
C.Tok->HasFormFeedBefore)
1698 for (
unsigned I = 1; I <
C.NewlinesBefore; ++I)
1699 Text.append(Newline);
1702void WhitespaceManager::appendEscapedNewlineText(
1703 std::string &
Text,
unsigned Newlines,
unsigned PreviousEndOfTokenColumn,
1704 unsigned EscapedNewlineColumn) {
1707 std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
1708 for (
unsigned i = 0; i <
Newlines; ++i) {
1709 Text.append(Spaces,
' ');
1710 Text.append(UseCRLF ?
"\\\r\n" :
"\\\n");
1711 Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
1716void WhitespaceManager::appendIndentText(std::string &
Text,
1718 unsigned WhitespaceStartColumn,
1720 switch (Style.UseTab) {
1721 case FormatStyle::UT_Never:
1722 Text.append(Spaces,
' ');
1724 case FormatStyle::UT_Always: {
1725 if (Style.TabWidth) {
1726 unsigned FirstTabWidth =
1727 Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
1730 if (Spaces < FirstTabWidth || Spaces == 1) {
1731 Text.append(Spaces,
' ');
1735 Spaces -= FirstTabWidth;
1738 Text.append(Spaces / Style.TabWidth,
'\t');
1739 Text.append(Spaces % Style.TabWidth,
' ');
1740 }
else if (Spaces == 1) {
1741 Text.append(Spaces,
' ');
1745 case FormatStyle::UT_ForIndentation:
1746 if (WhitespaceStartColumn == 0) {
1747 unsigned Indentation =
IndentLevel * Style.IndentWidth;
1748 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1750 Text.append(Spaces,
' ');
1752 case FormatStyle::UT_ForContinuationAndIndentation:
1753 if (WhitespaceStartColumn == 0)
1754 Spaces = appendTabIndent(
Text, Spaces, Spaces);
1755 Text.append(Spaces,
' ');
1757 case FormatStyle::UT_AlignWithSpaces:
1758 if (WhitespaceStartColumn == 0) {
1759 unsigned Indentation =
1760 IsAligned ?
IndentLevel * Style.IndentWidth : Spaces;
1761 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1763 Text.append(Spaces,
' ');
1768unsigned WhitespaceManager::appendTabIndent(std::string &
Text,
unsigned Spaces,
1769 unsigned Indentation) {
1772 if (Indentation > Spaces)
1773 Indentation = Spaces;
1774 if (Style.TabWidth) {
1775 unsigned Tabs = Indentation / Style.TabWidth;
1776 Text.append(Tabs,
'\t');
1777 Spaces -= Tabs * Style.TabWidth;
WhitespaceManager class manages whitespace around tokens and their replacements.
__DEVICE__ long long abs(long long __n)
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.
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.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Type
The name was classified as a type.
int const char * function