15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallVector.h"
24 return SourceMgr.isBeforeInTranslationUnit(
29 SourceMgr.isBeforeInTranslationUnit(
55 unsigned StartOfTokenColumn,
56 bool IsAligned,
bool InPPDirective) {
61 Spaces, StartOfTokenColumn,
Newlines,
"",
"",
62 IsAligned, InPPDirective && !
Tok.IsFirst,
71 Tok.WhitespaceRange, 0,
72 Tok.OriginalColumn,
Tok.NewlinesBefore,
"",
"",
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;
90 StringRef PreviousPostfix, StringRef CurrentPrefix,
bool InPPDirective,
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();
115 if (Style.isTableGen()) {
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 =
141 SourceMgr.getFileOffset(OriginalWhitespaceStart);
142 unsigned PreviousOriginalWhitespaceEndOffset =
143 SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd);
144 assert(PreviousOriginalWhitespaceEndOffset <=
145 OriginalWhitespaceStartOffset);
146 const char *
const PreviousOriginalWhitespaceEndData =
147 SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd);
148 StringRef
Text(PreviousOriginalWhitespaceEndData,
149 SourceMgr.getCharacterData(OriginalWhitespaceStart) -
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) {
244 LastBlockComment = &
Change;
251 LastBlockComment =
nullptr;
259 SmallVector<bool, 16> ScopeStack;
260 int ConditionalsLevel = 0;
261 for (
auto &
Change : Changes) {
263 bool isNestedConditional =
268 if (isNestedConditional)
270 ScopeStack.push_back(isNestedConditional);
276 if (ScopeStack.pop_back_val())
287 unsigned Column,
bool RightJustify,
293 bool LineShifted =
false;
320 for (
unsigned i = Start; i != End; ++i) {
321 auto &CurrentChange = Changes[i];
322 if (!Matches.empty() && Matches[0] < i)
323 Matches.consume_front();
324 assert(Matches.empty() || Matches[0] >= i);
325 while (!ScopeStack.empty() &&
326 CurrentChange.indentAndNestingLevel() < ScopeStack.back()) {
327 ScopeStack.pop_back();
331 if (ScopeStack.size() == 1u && CurrentChange.NewlinesBefore != 0u &&
332 CurrentChange.indentAndNestingLevel() > ScopeStack[0] &&
333 !CurrentChange.IsAligned) {
334 ScopeStack.push_back(CurrentChange.indentAndNestingLevel());
337 bool InsideNestedScope =
338 !ScopeStack.empty() &&
339 CurrentChange.indentAndNestingLevel() > ScopeStack[0];
340 bool ContinuedStringLiteral = i > Start &&
341 CurrentChange.Tok->is(tok::string_literal) &&
342 Changes[i - 1].Tok->is(tok::string_literal);
343 bool SkipMatchCheck = InsideNestedScope || ContinuedStringLiteral;
345 if (CurrentChange.NewlinesBefore > 0) {
354 if (!Matches.empty() && Matches[0] == i) {
355 Shift =
Column - (RightJustify ? CurrentChange.TokenLength : 0) -
356 CurrentChange.StartOfTokenColumn;
357 ScopeStack = {CurrentChange.indentAndNestingLevel()};
366 if ((!Matches.empty() && Matches[0] == i) ||
367 (ScopeStack.size() == 1u && CurrentChange.NewlinesBefore > 0 &&
368 (ContinuedStringLiteral || InsideNestedScope))) {
370 CurrentChange.Spaces += Shift;
375 CurrentChange.Spaces >=
376 static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
377 CurrentChange.Tok->is(tok::eof));
380 CurrentChange.StartOfTokenColumn += Shift;
381 if (i + 1 != Changes.size())
382 Changes[i + 1].PreviousEndOfTokenColumn += Shift;
387 if ((Style.PointerAlignment == FormatStyle::PAS_Right ||
388 Style.ReferenceAlignment == FormatStyle::RAS_Right) &&
389 CurrentChange.Spaces != 0 &&
390 CurrentChange.Tok->isNoneOf(tok::equal, tok::r_paren,
391 TT_TemplateCloser)) {
392 const bool ReferenceNotRightAligned =
393 Style.ReferenceAlignment != FormatStyle::RAS_Right &&
394 Style.ReferenceAlignment != FormatStyle::RAS_Pointer;
398 assert(Changes[
Previous].
Tok->isPointerOrReference());
400 if (ReferenceNotRightAligned)
402 }
else if (Style.PointerAlignment != FormatStyle::PAS_Right) {
405 Changes[
Previous + 1].Spaces -= Shift;
407 Changes[
Previous].StartOfTokenColumn += Shift;
448template <
typename F,
bool SimpleCheck = false>
452 const FormatStyle::AlignConsecutiveStyle &ACS = {},
453 bool RightJustify =
false) {
464 unsigned WidthLeft = 0;
467 unsigned WidthAnchor = 0;
470 unsigned WidthRight = 0;
473 unsigned StartOfSequence = 0;
474 unsigned EndOfSequence = 0;
481 const auto IndentAndNestingLevel =
482 StartAt < Changes.size() ? Changes[StartAt].indentAndNestingLevel()
483 : std::tuple<unsigned, unsigned, unsigned>();
488 unsigned CommasBeforeLastMatch = 0;
489 unsigned CommasBeforeMatch = 0;
492 bool FoundMatchOnLine =
false;
495 bool LineIsComment =
true;
504 auto AlignCurrentSequence = [&] {
505 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
507 WidthLeft + WidthAnchor, RightJustify, MatchedIndices,
515 MatchedIndices.clear();
518 unsigned I = StartAt;
519 for (
unsigned E = Changes.size(); I != E; ++I) {
520 auto &CurrentChange = Changes[I];
521 if (CurrentChange.indentAndNestingLevel() < IndentAndNestingLevel)
524 if (CurrentChange.NewlinesBefore != 0) {
525 CommasBeforeMatch = 0;
529 bool EmptyLineBreak =
530 (CurrentChange.NewlinesBefore > 1) && !ACS.AcrossEmptyLines;
535 !FoundMatchOnLine && !(LineIsComment && ACS.AcrossComments);
537 if (EmptyLineBreak || NoMatchBreak)
538 AlignCurrentSequence();
542 if (I == 0 || CurrentChange.Tok->isNot(tok::string_literal) ||
543 Changes[I - 1].Tok->isNot(tok::string_literal)) {
544 FoundMatchOnLine =
false;
546 LineIsComment =
true;
549 if (CurrentChange.Tok->isNot(tok::comment))
550 LineIsComment =
false;
553 if (CurrentChange.Tok->is(tok::comma)) {
555 }
else if (CurrentChange.indentAndNestingLevel() >
556 IndentAndNestingLevel) {
558 const auto StoppedAt =
559 AlignTokens(Style, Matches, Changes, I, ACS, RightJustify);
565 if (!Matches(CurrentChange))
570 if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch) {
571 MatchedIndices.push_back(I);
572 AlignCurrentSequence();
575 CommasBeforeLastMatch = CommasBeforeMatch;
576 FoundMatchOnLine =
true;
578 if (StartOfSequence == 0)
581 unsigned ChangeWidthLeft = CurrentChange.StartOfTokenColumn;
582 unsigned ChangeWidthAnchor = 0;
583 unsigned ChangeWidthRight = 0;
584 unsigned CurrentChangeWidthRight = 0;
586 if (ACS.PadOperators)
587 ChangeWidthAnchor = CurrentChange.TokenLength;
589 ChangeWidthLeft += CurrentChange.TokenLength;
591 CurrentChangeWidthRight = CurrentChange.TokenLength;
592 const FormatToken *MatchingParenToEncounter =
nullptr;
593 for (
unsigned J = I + 1;
594 J != E && (Changes[J].NewlinesBefore == 0 ||
595 MatchingParenToEncounter || Changes[J].IsAligned);
597 const auto &
Change = Changes[J];
600 if (
Tok->MatchingParen) {
601 if (
Tok->isOneOf(tok::l_paren, tok::l_brace, tok::l_square,
602 TT_TemplateOpener) &&
603 !MatchingParenToEncounter) {
608 MatchingParenToEncounter =
Tok->MatchingParen;
609 }
else if (MatchingParenToEncounter ==
Tok->MatchingParen) {
610 MatchingParenToEncounter =
nullptr;
615 ChangeWidthRight = std::max(ChangeWidthRight, CurrentChangeWidthRight);
616 const auto ChangeWidthStart = ChangeWidthLeft + ChangeWidthAnchor;
625 if (
static_cast<unsigned>(
Change.
Spaces) < ChangeWidthStart)
627 CurrentChangeWidthRight =
Change.
Spaces - ChangeWidthStart;
641 ChangeWidthRight = std::max(ChangeWidthRight, CurrentChangeWidthRight);
644 unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
645 unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
646 unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
648 if (Style.ColumnLimit != 0 &&
649 Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
650 AlignCurrentSequence();
652 WidthLeft = ChangeWidthLeft;
653 WidthAnchor = ChangeWidthAnchor;
654 WidthRight = ChangeWidthRight;
657 WidthAnchor = NewAnchor;
658 WidthRight = NewRight;
660 MatchedIndices.push_back(I);
664 AlignCurrentSequence();
676 unsigned &StartOfSequence,
unsigned &EndOfSequence,
unsigned &MinColumn,
679 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
680 bool FoundMatchOnLine =
false;
683 for (
unsigned I = StartOfSequence; I != EndOfSequence; ++I) {
686 FoundMatchOnLine =
false;
692 if (!FoundMatchOnLine && Matches(Changes[I])) {
693 FoundMatchOnLine =
true;
694 Shift = MinColumn - Changes[I].StartOfTokenColumn;
695 Changes[I].Spaces += Shift;
699 Changes[I].StartOfTokenColumn += Shift;
700 if (I + 1 != Changes.size())
701 Changes[I + 1].PreviousEndOfTokenColumn += Shift;
710void WhitespaceManager::alignConsecutiveMacros() {
711 if (!Style.AlignConsecutiveMacros.Enabled)
714 auto AlignMacrosMatches = [](
const Change &
C) {
718 if (Current->SpacesRequiredBefore == 0 || !Current->Previous)
721 Current = Current->Previous;
725 if (Current->is(tok::r_paren)) {
734 }
else if (Current->Next->SpacesRequiredBefore != 1) {
740 return Current->endsSequence(tok::identifier, tok::pp_define);
744 Style, AlignMacrosMatches, Changes, 0, Style.AlignConsecutiveMacros);
747void WhitespaceManager::alignConsecutiveAssignments() {
748 if (!Style.AlignConsecutiveAssignments.Enabled)
755 if (
C.NewlinesBefore > 0)
759 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
767 return Style.AlignConsecutiveAssignments.AlignCompound
769 : (
C.Tok->is(tok::equal) ||
773 (Style.isVerilog() &&
C.Tok->is(tok::lessequal) &&
776 Changes, 0, Style.AlignConsecutiveAssignments,
780void WhitespaceManager::alignConsecutiveBitFields() {
781 alignConsecutiveColons(Style.AlignConsecutiveBitFields, TT_BitFieldColon);
784void WhitespaceManager::alignConsecutiveColons(
785 const FormatStyle::AlignConsecutiveStyle &AlignStyle,
TokenType Type) {
786 if (!AlignStyle.Enabled)
793 if (
C.NewlinesBefore > 0)
797 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
800 return C.Tok->is(
Type);
802 Changes, 0, AlignStyle);
805void WhitespaceManager::alignConsecutiveShortCaseStatements(
bool IsExpr) {
806 if (!Style.AlignConsecutiveShortCaseStatements.Enabled ||
807 !(IsExpr ? Style.AllowShortCaseExpressionOnASingleLine
808 : Style.AllowShortCaseLabelsOnASingleLine)) {
812 const auto Type = IsExpr ? TT_CaseLabelArrow : TT_CaseLabelColon;
813 const auto &Option = Style.AlignConsecutiveShortCaseStatements;
814 const bool AlignArrowOrColon =
815 IsExpr ? Option.AlignCaseArrows : Option.AlignCaseColons;
817 auto Matches = [&](
const Change &
C) {
818 if (AlignArrowOrColon)
819 return C.Tok->is(
Type);
825 return !
C.IsInsideToken &&
C.Tok->Previous &&
C.Tok->Previous->is(
Type);
828 unsigned MinColumn = 0;
833 unsigned MinEmptyCaseColumn = 0;
836 unsigned StartOfSequence = 0;
837 unsigned EndOfSequence = 0;
840 bool FoundMatchOnLine =
false;
842 bool LineIsComment =
true;
843 bool LineIsEmptyCase =
false;
846 for (
unsigned E = Changes.size(); I != E; ++I) {
849 bool EmptyLineBreak =
850 (Changes[I].NewlinesBefore > 1) &&
851 !Style.AlignConsecutiveShortCaseStatements.AcrossEmptyLines;
858 Style.AlignConsecutiveShortCaseStatements.AcrossComments) &&
861 if (EmptyLineBreak || NoMatchBreak) {
864 MinEmptyCaseColumn = 0;
868 FoundMatchOnLine =
false;
869 LineIsComment =
true;
870 LineIsEmptyCase =
false;
873 if (Changes[I].
Tok->isNot(tok::comment))
874 LineIsComment =
false;
876 if (Changes[I].
Tok->is(
Type)) {
878 !Changes[I].Tok->Next || Changes[I].Tok->Next->isTrailingComment();
880 if (LineIsEmptyCase) {
881 if (Style.AlignConsecutiveShortCaseStatements.AlignCaseColons) {
883 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn);
886 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn + 2);
891 if (!Matches(Changes[I]))
897 FoundMatchOnLine =
true;
899 if (StartOfSequence == 0)
902 EndOfSequence = I + 1;
904 MinColumn = std::max(MinColumn, Changes[I].StartOfTokenColumn);
907 MinColumn = std::max(MinColumn, MinEmptyCaseColumn);
914void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() {
915 alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons,
916 TT_TableGenDAGArgListColonToAlign);
919void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() {
920 alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons,
921 TT_TableGenCondOperatorColon);
924void WhitespaceManager::alignConsecutiveTableGenDefinitions() {
925 alignConsecutiveColons(Style.AlignConsecutiveTableGenDefinitionColons,
926 TT_InheritanceColon);
929void WhitespaceManager::alignConsecutiveDeclarations() {
930 if (!Style.AlignConsecutiveDeclarations.Enabled)
936 if (
C.Tok->is(TT_FunctionTypeLParen))
937 return Style.AlignConsecutiveDeclarations.AlignFunctionPointers;
938 if (
C.Tok->is(TT_FunctionDeclarationName))
939 return Style.AlignConsecutiveDeclarations.AlignFunctionDeclarations;
940 if (
C.Tok->isNot(TT_StartOfName))
942 if (
C.Tok->Previous &&
943 C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
947 if (
Next->is(tok::comment))
949 if (
Next->is(TT_PointerOrReference))
951 if (!
Next->Tok.getIdentifierInfo())
953 if (
Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
960 Changes, 0, Style.AlignConsecutiveDeclarations);
963void WhitespaceManager::alignChainedConditionals() {
964 if (Style.BreakBeforeTernaryOperators) {
969 return C.Tok->is(TT_ConditionalExpr) &&
970 ((
C.Tok->is(tok::question) && !
C.NewlinesBefore) ||
971 (
C.Tok->is(tok::colon) &&
C.Tok->Next &&
972 (
C.Tok->Next->FakeLParens.empty() ||
977 static auto AlignWrappedOperand = [](
Change const &
C) {
981 (
C.Tok->FakeLParens.empty() ||
988 if (AlignWrappedOperand(
C))
989 C.StartOfTokenColumn -= 2;
996 return (
C.Tok->is(TT_ConditionalExpr) &&
C.Tok->is(tok::question) &&
997 &
C != &Changes.back() && (&
C + 1)->NewlinesBefore == 0 &&
998 !(&
C + 1)->IsTrailingComment) ||
999 AlignWrappedOperand(
C);
1005void WhitespaceManager::alignTrailingComments() {
1006 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Never)
1009 const int Size = Changes.size();
1011 int StartOfSequence = 0;
1012 bool BreakBeforeNext =
false;
1013 int NewLineThreshold = 1;
1014 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always)
1015 NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
1018 auto &
C = Changes[I];
1019 if (
C.StartOfBlockComment)
1022 if (!
C.IsTrailingComment)
1025 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Leave) {
1026 const int OriginalSpaces =
1027 C.OriginalWhitespaceRange.getEnd().getRawEncoding() -
1028 C.OriginalWhitespaceRange.getBegin().getRawEncoding() -
1029 C.Tok->LastNewlineOffset;
1030 assert(OriginalSpaces >= 0);
1031 const auto RestoredLineLength =
1032 C.StartOfTokenColumn +
C.TokenLength + OriginalSpaces;
1035 if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
1037 C.Spaces =
C.NewlinesBefore > 0 ?
C.Tok->OriginalColumn : OriginalSpaces;
1041 const int ChangeMinColumn =
C.StartOfTokenColumn;
1042 int ChangeMaxColumn;
1046 if (!
C.CreateReplacement)
1047 ChangeMaxColumn = ChangeMinColumn;
1048 else if (Style.ColumnLimit == 0)
1050 else if (Style.ColumnLimit >=
C.TokenLength)
1051 ChangeMaxColumn = Style.ColumnLimit -
C.TokenLength;
1053 ChangeMaxColumn = ChangeMinColumn;
1055 if (I + 1 < Size && Changes[I + 1].ContinuesPPDirective &&
1056 ChangeMaxColumn >= 2) {
1057 ChangeMaxColumn -= 2;
1060 bool WasAlignedWithStartOfNextLine =
false;
1061 if (
C.NewlinesBefore >= 1) {
1062 const auto CommentColumn =
1063 SourceMgr.getSpellingColumnNumber(
C.OriginalWhitespaceRange.getEnd());
1064 for (
int J = I + 1; J <
Size; ++J) {
1065 if (Changes[J].
Tok->is(tok::comment))
1068 const auto NextColumn = SourceMgr.getSpellingColumnNumber(
1069 Changes[J].OriginalWhitespaceRange.getEnd());
1072 WasAlignedWithStartOfNextLine =
1073 CommentColumn == NextColumn ||
1074 CommentColumn == NextColumn + Style.IndentWidth;
1081 auto DontAlignThisComment = [](
const auto *
Tok) {
1082 if (
Tok->is(tok::semi)) {
1083 Tok =
Tok->getPreviousNonComment();
1087 if (
Tok->is(tok::r_paren)) {
1089 Tok =
Tok->MatchingParen;
1092 Tok =
Tok->getPreviousNonComment();
1095 if (
Tok->is(TT_DoWhile)) {
1096 const auto *Prev =
Tok->getPreviousNonComment();
1105 if (
Tok->isNot(tok::r_brace))
1108 while (
Tok->Previous &&
Tok->Previous->is(tok::r_brace))
1110 return Tok->NewlinesBefore > 0;
1113 if (I > 0 &&
C.NewlinesBefore == 0 &&
1114 DontAlignThisComment(Changes[I - 1].
Tok)) {
1115 alignTrailingComments(StartOfSequence, I, MinColumn);
1120 StartOfSequence = I + 1;
1121 }
else if (BreakBeforeNext ||
Newlines > NewLineThreshold ||
1122 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
1125 (
C.NewlinesBefore == 1 && I > 0 &&
1126 !Changes[I - 1].IsTrailingComment) ||
1127 WasAlignedWithStartOfNextLine) {
1128 alignTrailingComments(StartOfSequence, I, MinColumn);
1129 MinColumn = ChangeMinColumn;
1130 MaxColumn = ChangeMaxColumn;
1131 StartOfSequence = I;
1133 MinColumn = std::max(MinColumn, ChangeMinColumn);
1134 MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
1136 BreakBeforeNext = (I == 0) || (
C.NewlinesBefore > 1) ||
1139 (
C.NewlinesBefore == 1 && StartOfSequence == I);
1142 alignTrailingComments(StartOfSequence, Size, MinColumn);
1145void WhitespaceManager::alignTrailingComments(
unsigned Start,
unsigned End,
1147 for (
unsigned i = Start; i != End; ++i) {
1149 if (Changes[i].IsTrailingComment)
1151 if (Changes[i].StartOfBlockComment) {
1152 Shift = Changes[i].IndentationOffset +
1153 Changes[i].StartOfBlockComment->StartOfTokenColumn -
1154 Changes[i].StartOfTokenColumn;
1158 Changes[i].Spaces +=
Shift;
1159 if (i + 1 != Changes.size())
1160 Changes[i + 1].PreviousEndOfTokenColumn +=
Shift;
1161 Changes[i].StartOfTokenColumn +=
Shift;
1165void WhitespaceManager::alignEscapedNewlines() {
1166 const auto Align = Style.AlignEscapedNewlines;
1167 if (Align == FormatStyle::ENAS_DontAlign)
1170 const bool WithLastLine = Align == FormatStyle::ENAS_LeftWithLastLine;
1171 const bool AlignLeft = Align == FormatStyle::ENAS_Left || WithLastLine;
1172 const auto MaxColumn = Style.ColumnLimit;
1173 unsigned MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1174 unsigned StartOfMacro = 0;
1175 for (
unsigned i = 1, e = Changes.size(); i < e; ++i) {
1177 if (
C.NewlinesBefore == 0 && (!WithLastLine ||
C.Tok->isNot(tok::eof)))
1180 const auto BackslashColumn =
C.PreviousEndOfTokenColumn + 2;
1181 if (InPPDirective ||
1182 (WithLastLine && (MaxColumn == 0 || BackslashColumn <= MaxColumn))) {
1183 MaxEndOfLine = std::max(BackslashColumn, MaxEndOfLine);
1185 if (!InPPDirective) {
1186 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
1187 MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1191 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
1194void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
1196 for (
unsigned i = Start; i < End; ++i) {
1198 if (
C.NewlinesBefore > 0) {
1199 assert(
C.ContinuesPPDirective);
1200 if (
C.PreviousEndOfTokenColumn + 1 >
Column)
1201 C.EscapedNewlineColumn = 0;
1203 C.EscapedNewlineColumn =
Column;
1208void WhitespaceManager::alignArrayInitializers() {
1209 if (Style.AlignArrayOfStructures == FormatStyle::AIAS_None)
1212 for (
unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
1213 ChangeIndex < ChangeEnd; ++ChangeIndex) {
1214 auto &
C = Changes[ChangeIndex];
1215 if (
C.Tok->IsArrayInitializer) {
1216 bool FoundComplete =
false;
1217 for (
unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
1219 if (Changes[InsideIndex].
Tok ==
C.Tok->MatchingParen) {
1220 alignArrayInitializers(ChangeIndex, InsideIndex + 1);
1221 ChangeIndex = InsideIndex + 1;
1222 FoundComplete =
true;
1227 ChangeIndex = ChangeEnd;
1232void WhitespaceManager::alignArrayInitializers(
unsigned Start,
unsigned End) {
1234 if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Right)
1235 alignArrayInitializersRightJustified(getCells(Start, End));
1236 else if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Left)
1237 alignArrayInitializersLeftJustified(getCells(Start, End));
1240void WhitespaceManager::alignArrayInitializersRightJustified(
1241 CellDescriptions &&CellDescs) {
1242 if (!CellDescs.isRectangular())
1245 const int BracePadding =
1246 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? 0 : 1;
1247 auto &Cells = CellDescs.Cells;
1249 auto *CellIter = Cells.begin();
1250 for (
auto i = 0U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {
1251 unsigned NetWidth = 0U;
1252 if (isSplitCell(*CellIter))
1253 NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1254 auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1256 if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1260 const auto *
Next = CellIter;
1264 Changes[
Next->Index].Spaces = BracePadding;
1265 Changes[
Next->Index].NewlinesBefore = 0;
1271 if (CellIter != Cells.begin()) {
1273 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1274 auto MaxNetWidth = getMaximumNetWidth(
1275 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1276 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1277 if (ThisNetWidth < MaxNetWidth)
1278 Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1280 auto Offset = std::distance(Cells.begin(), CellIter);
1281 for (
const auto *
Next = CellIter->NextColumnElement;
Next;
1283 if (RowCount >= CellDescs.CellCounts.size())
1285 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1286 auto *End = Start + Offset;
1287 ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1288 if (ThisNetWidth < MaxNetWidth)
1289 Changes[
Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1295 calculateCellWidth(CellIter->Index, CellIter->EndIndex,
true) +
1297 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1298 Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
1299 Changes[CellIter->Index].Spaces += (i > 0) ? 1 : BracePadding;
1301 alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1302 for (
const auto *
Next = CellIter->NextColumnElement;
Next;
1305 calculateCellWidth(
Next->Index,
Next->EndIndex,
true) + NetWidth;
1306 if (Changes[
Next->Index].NewlinesBefore == 0) {
1307 Changes[
Next->Index].Spaces = (CellWidth - ThisWidth);
1308 Changes[
Next->Index].Spaces += (i > 0) ? 1 : BracePadding;
1310 alignToStartOfCell(
Next->Index,
Next->EndIndex);
1316void WhitespaceManager::alignArrayInitializersLeftJustified(
1317 CellDescriptions &&CellDescs) {
1319 if (!CellDescs.isRectangular())
1322 const int BracePadding =
1323 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? 0 : 1;
1324 auto &Cells = CellDescs.Cells;
1326 auto *CellIter = Cells.begin();
1334 for (
auto i = 1U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {
1335 auto MaxNetWidth = getMaximumNetWidth(
1336 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1337 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1339 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1340 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1341 Changes[CellIter->Index].Spaces =
1342 MaxNetWidth - ThisNetWidth +
1343 (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1
1347 auto Offset = std::distance(Cells.begin(), CellIter);
1348 for (
const auto *
Next = CellIter->NextColumnElement;
Next;
1350 if (RowCount >= CellDescs.CellCounts.size())
1352 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1353 auto *End = Start + Offset;
1354 auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1355 if (Changes[
Next->Index].NewlinesBefore == 0) {
1356 Changes[
Next->Index].Spaces =
1357 MaxNetWidth - ThisNetWidth +
1358 (Changes[
Next->Index].Tok->isNot(tok::r_brace) ? 1 : BracePadding);
1365bool WhitespaceManager::isSplitCell(
const CellDescription &Cell) {
1368 for (
const auto *
Next = Cell.NextColumnElement;
Next;
1376WhitespaceManager::CellDescriptions WhitespaceManager::getCells(
unsigned Start,
1381 SmallVector<unsigned> CellCounts;
1382 unsigned InitialSpaces = 0;
1383 unsigned InitialTokenLength = 0;
1384 unsigned EndSpaces = 0;
1385 SmallVector<CellDescription> Cells;
1387 for (
unsigned i = Start; i < End; ++i) {
1388 auto &
C = Changes[i];
1389 if (
C.Tok->is(tok::l_brace))
1391 else if (
C.Tok->is(tok::r_brace))
1394 if (
C.Tok->is(tok::l_brace)) {
1397 if (InitialSpaces == 0) {
1398 InitialSpaces =
C.Spaces +
C.TokenLength;
1399 InitialTokenLength =
C.TokenLength;
1401 for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
1402 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1403 InitialTokenLength += Changes[j].TokenLength;
1405 if (
C.NewlinesBefore == 0) {
1406 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1407 InitialTokenLength += Changes[j].TokenLength;
1410 }
else if (
C.Tok->is(tok::comma)) {
1412 Cells.back().EndIndex = i;
1413 if (
const auto *
Next =
C.Tok->getNextNonComment();
1414 Next &&
Next->isNot(tok::r_brace)) {
1418 }
else if (Depth == 1) {
1421 Cells.back().EndIndex = i;
1422 Cells.push_back(CellDescription{i, ++Cell, i + 1,
false,
nullptr});
1423 CellCounts.push_back(
C.Tok->Previous->isNot(tok::comma) ? Cell + 1
1426 const auto *NextNonComment =
C.Tok->getNextNonComment();
1427 while (NextNonComment && NextNonComment->is(tok::comma))
1428 NextNonComment = NextNonComment->getNextNonComment();
1430 while (j < End && Changes[j].
Tok != NextNonComment)
1433 Changes[j].
Tok->isNot(tok::r_brace)) {
1434 Changes[j].NewlinesBefore = 1;
1436 Changes[j].Spaces = InitialSpaces - InitialTokenLength;
1438 }
else if (
C.Tok->is(tok::comment) &&
C.Tok->NewlinesBefore == 0) {
1440 C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 1 : 2;
1441 }
else if (
C.Tok->is(tok::l_brace)) {
1445 for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
1447 EndSpaces = Changes[j].Spaces;
1449 }
else if (Depth == 0 &&
C.Tok->is(tok::r_brace)) {
1450 C.NewlinesBefore = 1;
1451 C.Spaces = EndSpaces;
1453 if (
C.Tok->StartsColumn) {
1456 bool HasSplit =
false;
1473 if ((j - 1) > Start && Changes[j].
Tok->is(tok::comma) &&
1474 Changes[j - 1].NewlinesBefore > 0) {
1476 auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1477 if (LineLimit < Style.ColumnLimit) {
1478 Changes[i].NewlinesBefore = 0;
1479 Changes[i].Spaces = 1;
1484 Changes[i].Spaces = InitialSpaces;
1488 if (Changes[i].
Tok !=
C.Tok)
1490 Cells.push_back(CellDescription{i, Cell, i, HasSplit,
nullptr});
1494 return linkCells({Cells, CellCounts, InitialSpaces});
1497unsigned WhitespaceManager::calculateCellWidth(
unsigned Start,
unsigned End,
1498 bool WithSpaces)
const {
1499 unsigned CellWidth = 0;
1500 for (
auto i = Start; i < End; i++) {
1503 CellWidth += Changes[i].TokenLength;
1504 CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
1509void WhitespaceManager::alignToStartOfCell(
unsigned Start,
unsigned End) {
1510 if ((End - Start) <= 1)
1514 for (
auto i = Start + 1; i < End; i++)
1516 Changes[i].Spaces = Changes[Start].Spaces;
1519WhitespaceManager::CellDescriptions
1520WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1521 auto &Cells = CellDesc.Cells;
1522 for (
auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
1523 if (!CellIter->NextColumnElement && (CellIter + 1) != Cells.end()) {
1524 for (
auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
1525 if (NextIter->Cell == CellIter->Cell) {
1526 CellIter->NextColumnElement = &(*NextIter);
1532 return std::move(CellDesc);
1535void WhitespaceManager::generateChanges() {
1536 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
1539 auto Last = Changes[i - 1].OriginalWhitespaceRange;
1540 auto New = Changes[i].OriginalWhitespaceRange;
1582 if (
Last.getBegin() ==
New.getBegin() &&
1583 (
Last.getEnd() !=
Last.getBegin() ||
1584 New.getEnd() ==
New.getBegin())) {
1588 if (
C.CreateReplacement) {
1589 std::string ReplacementText =
C.PreviousLinePostfix;
1590 if (
C.ContinuesPPDirective) {
1591 appendEscapedNewlineText(ReplacementText,
C.NewlinesBefore,
1592 C.PreviousEndOfTokenColumn,
1593 C.EscapedNewlineColumn);
1595 appendNewlineText(ReplacementText,
C);
1600 ReplacementText,
C.Tok->IndentLevel, std::max(0,
C.Spaces),
1601 std::max((
int)
C.StartOfTokenColumn,
C.Spaces) - std::max(0,
C.Spaces),
1603 ReplacementText.append(
C.CurrentLinePrefix);
1604 storeReplacement(
C.OriginalWhitespaceRange, ReplacementText);
1609void WhitespaceManager::storeReplacement(SourceRange Range, StringRef
Text) {
1610 unsigned WhitespaceLength = SourceMgr.getFileOffset(
Range.getEnd()) -
1611 SourceMgr.getFileOffset(
Range.getBegin());
1613 if (StringRef(SourceMgr.getCharacterData(
Range.getBegin()),
1614 WhitespaceLength) ==
Text) {
1617 auto Err = Replaces.add(tooling::Replacement(
1622 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
1627void WhitespaceManager::appendNewlineText(std::string &
Text,
const Change &
C) {
1628 if (
C.NewlinesBefore <= 0)
1631 StringRef Newline = UseCRLF ?
"\r\n" :
"\n";
1632 Text.append(Newline);
1634 if (
C.Tok->HasFormFeedBefore)
1637 for (
unsigned I = 1; I <
C.NewlinesBefore; ++I)
1638 Text.append(Newline);
1641void WhitespaceManager::appendEscapedNewlineText(
1642 std::string &
Text,
unsigned Newlines,
unsigned PreviousEndOfTokenColumn,
1643 unsigned EscapedNewlineColumn) {
1646 std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
1647 for (
unsigned i = 0; i <
Newlines; ++i) {
1648 Text.append(Spaces,
' ');
1649 Text.append(UseCRLF ?
"\\\r\n" :
"\\\n");
1650 Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
1655void WhitespaceManager::appendIndentText(std::string &
Text,
1657 unsigned WhitespaceStartColumn,
1659 switch (Style.UseTab) {
1660 case FormatStyle::UT_Never:
1661 Text.append(Spaces,
' ');
1663 case FormatStyle::UT_Always: {
1664 if (Style.TabWidth) {
1665 unsigned FirstTabWidth =
1666 Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
1669 if (Spaces < FirstTabWidth || Spaces == 1) {
1670 Text.append(Spaces,
' ');
1674 Spaces -= FirstTabWidth;
1677 Text.append(Spaces / Style.TabWidth,
'\t');
1678 Text.append(Spaces % Style.TabWidth,
' ');
1679 }
else if (Spaces == 1) {
1680 Text.append(Spaces,
' ');
1684 case FormatStyle::UT_ForIndentation:
1685 if (WhitespaceStartColumn == 0) {
1686 unsigned Indentation =
IndentLevel * Style.IndentWidth;
1687 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1689 Text.append(Spaces,
' ');
1691 case FormatStyle::UT_ForContinuationAndIndentation:
1692 if (WhitespaceStartColumn == 0)
1693 Spaces = appendTabIndent(
Text, Spaces, Spaces);
1694 Text.append(Spaces,
' ');
1696 case FormatStyle::UT_AlignWithSpaces:
1697 if (WhitespaceStartColumn == 0) {
1698 unsigned Indentation =
1699 IsAligned ?
IndentLevel * Style.IndentWidth : Spaces;
1700 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1702 Text.append(Spaces,
' ');
1707unsigned WhitespaceManager::appendTabIndent(std::string &
Text,
unsigned Spaces,
1708 unsigned Indentation) {
1711 if (Indentation > Spaces)
1712 Indentation = Spaces;
1713 if (Style.TabWidth) {
1714 unsigned Tabs = Indentation / Style.TabWidth;
1715 Text.append(Tabs,
'\t');
1716 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.
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