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 =
C.NewlinesBefore > 0 ?
C.Tok->OriginalColumn : 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() {
1248 const auto Align = Style.AlignEscapedNewlines;
1254 const auto MaxColumn = Style.ColumnLimit;
1255 unsigned MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1256 unsigned StartOfMacro = 0;
1257 for (
unsigned i = 1, e = Changes.size(); i < e; ++i) {
1258 Change &
C = Changes[i];
1259 if (
C.NewlinesBefore == 0 && (!WithLastLine ||
C.Tok->isNot(tok::eof)))
1261 const bool InPPDirective =
C.ContinuesPPDirective;
1262 const auto BackslashColumn =
C.PreviousEndOfTokenColumn + 2;
1263 if (InPPDirective ||
1264 (WithLastLine && (MaxColumn == 0 || BackslashColumn <= MaxColumn))) {
1265 MaxEndOfLine = std::max(BackslashColumn, MaxEndOfLine);
1267 if (!InPPDirective) {
1268 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
1269 MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1273 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
1276void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
1278 for (
unsigned i = Start; i < End; ++i) {
1279 Change &
C = Changes[i];
1280 if (
C.NewlinesBefore > 0) {
1281 assert(
C.ContinuesPPDirective);
1282 if (
C.PreviousEndOfTokenColumn + 1 >
Column)
1283 C.EscapedNewlineColumn = 0;
1285 C.EscapedNewlineColumn =
Column;
1290void WhitespaceManager::alignArrayInitializers() {
1294 for (
unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
1295 ChangeIndex < ChangeEnd; ++ChangeIndex) {
1296 auto &
C = Changes[ChangeIndex];
1297 if (
C.Tok->IsArrayInitializer) {
1298 bool FoundComplete =
false;
1299 for (
unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
1301 if (Changes[InsideIndex].Tok ==
C.Tok->MatchingParen) {
1302 alignArrayInitializers(ChangeIndex, InsideIndex + 1);
1303 ChangeIndex = InsideIndex + 1;
1304 FoundComplete =
true;
1309 ChangeIndex = ChangeEnd;
1314void WhitespaceManager::alignArrayInitializers(
unsigned Start,
unsigned End) {
1317 alignArrayInitializersRightJustified(getCells(Start, End));
1319 alignArrayInitializersLeftJustified(getCells(Start, End));
1322void WhitespaceManager::alignArrayInitializersRightJustified(
1323 CellDescriptions &&CellDescs) {
1324 if (!CellDescs.isRectangular())
1327 const int BracePadding = Style.Cpp11BracedListStyle ? 0 : 1;
1328 auto &Cells = CellDescs.Cells;
1330 auto *CellIter = Cells.begin();
1331 for (
auto i = 0
U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {
1332 unsigned NetWidth = 0
U;
1333 if (isSplitCell(*CellIter))
1334 NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1335 auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1337 if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1341 const auto *Next = CellIter;
1343 const FormatToken *
Previous = Changes[Next->Index].Tok->Previous;
1345 Changes[Next->Index].Spaces = BracePadding;
1346 Changes[Next->Index].NewlinesBefore = 0;
1348 Next = Next->NextColumnElement;
1352 if (CellIter != Cells.begin()) {
1354 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1355 auto MaxNetWidth = getMaximumNetWidth(
1356 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1357 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1358 if (ThisNetWidth < MaxNetWidth)
1359 Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1361 auto Offset = std::distance(Cells.begin(), CellIter);
1362 for (
const auto *Next = CellIter->NextColumnElement; Next;
1363 Next = Next->NextColumnElement) {
1364 if (RowCount >= CellDescs.CellCounts.size())
1366 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1367 auto *End = Start + Offset;
1368 ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1369 if (ThisNetWidth < MaxNetWidth)
1370 Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1376 calculateCellWidth(CellIter->Index, CellIter->EndIndex,
true) +
1378 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1379 Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
1380 Changes[CellIter->Index].Spaces += (i > 0) ? 1 : BracePadding;
1382 alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1383 for (
const auto *Next = CellIter->NextColumnElement; Next;
1384 Next = Next->NextColumnElement) {
1386 calculateCellWidth(Next->Index, Next->EndIndex,
true) + NetWidth;
1387 if (Changes[Next->Index].NewlinesBefore == 0) {
1388 Changes[Next->Index].Spaces = (CellWidth - ThisWidth);
1389 Changes[Next->Index].Spaces += (i > 0) ? 1 : BracePadding;
1391 alignToStartOfCell(Next->Index, Next->EndIndex);
1397void WhitespaceManager::alignArrayInitializersLeftJustified(
1398 CellDescriptions &&CellDescs) {
1400 if (!CellDescs.isRectangular())
1403 const int BracePadding = Style.Cpp11BracedListStyle ? 0 : 1;
1404 auto &Cells = CellDescs.Cells;
1406 auto *CellIter = Cells.begin();
1408 for (
const auto *Next = CellIter; Next; Next = Next->NextColumnElement) {
1409 auto &Change = Changes[Next->Index];
1411 Change.NewlinesBefore == 0 ? BracePadding : CellDescs.InitialSpaces;
1414 for (
auto i = 1U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {
1415 auto MaxNetWidth = getMaximumNetWidth(
1416 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1417 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1419 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1420 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1421 Changes[CellIter->Index].Spaces =
1422 MaxNetWidth - ThisNetWidth +
1423 (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1
1427 auto Offset = std::distance(Cells.begin(), CellIter);
1428 for (
const auto *Next = CellIter->NextColumnElement; Next;
1429 Next = Next->NextColumnElement) {
1430 if (RowCount >= CellDescs.CellCounts.size())
1432 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1433 auto *End = Start + Offset;
1434 auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1435 if (Changes[Next->Index].NewlinesBefore == 0) {
1436 Changes[Next->Index].Spaces =
1437 MaxNetWidth - ThisNetWidth +
1438 (Changes[Next->Index].Tok->isNot(tok::r_brace) ? 1 : BracePadding);
1445bool WhitespaceManager::isSplitCell(
const CellDescription &Cell) {
1448 for (
const auto *Next = Cell.NextColumnElement; Next;
1449 Next = Next->NextColumnElement) {
1456WhitespaceManager::CellDescriptions WhitespaceManager::getCells(
unsigned Start,
1461 SmallVector<unsigned> CellCounts;
1462 unsigned InitialSpaces = 0;
1463 unsigned InitialTokenLength = 0;
1464 unsigned EndSpaces = 0;
1465 SmallVector<CellDescription> Cells;
1466 const FormatToken *MatchingParen =
nullptr;
1467 for (
unsigned i = Start; i < End; ++i) {
1468 auto &
C = Changes[i];
1469 if (
C.Tok->is(tok::l_brace))
1471 else if (
C.Tok->is(tok::r_brace))
1474 if (
C.Tok->is(tok::l_brace)) {
1476 MatchingParen =
C.Tok->MatchingParen;
1477 if (InitialSpaces == 0) {
1478 InitialSpaces =
C.Spaces +
C.TokenLength;
1479 InitialTokenLength =
C.TokenLength;
1481 for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
1482 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1483 InitialTokenLength += Changes[j].TokenLength;
1485 if (
C.NewlinesBefore == 0) {
1486 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1487 InitialTokenLength += Changes[j].TokenLength;
1490 }
else if (
C.Tok->is(tok::comma)) {
1492 Cells.back().EndIndex = i;
1493 if (
const auto *Next =
C.Tok->getNextNonComment();
1494 Next && Next->isNot(tok::r_brace)) {
1498 }
else if (Depth == 1) {
1499 if (
C.Tok == MatchingParen) {
1501 Cells.back().EndIndex = i;
1502 Cells.push_back(CellDescription{i, ++Cell, i + 1,
false,
nullptr});
1503 CellCounts.push_back(
C.Tok->Previous->isNot(tok::comma) ? Cell + 1
1506 const auto *NextNonComment =
C.Tok->getNextNonComment();
1507 while (NextNonComment && NextNonComment->is(tok::comma))
1508 NextNonComment = NextNonComment->getNextNonComment();
1510 while (j < End && Changes[j].Tok != NextNonComment)
1512 if (j < End && Changes[j].NewlinesBefore == 0 &&
1513 Changes[j].Tok->isNot(tok::r_brace)) {
1514 Changes[j].NewlinesBefore = 1;
1516 Changes[j].Spaces = InitialSpaces - InitialTokenLength;
1518 }
else if (
C.Tok->is(tok::comment) &&
C.Tok->NewlinesBefore == 0) {
1520 C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 1 : 2;
1521 }
else if (
C.Tok->is(tok::l_brace)) {
1525 for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
1527 EndSpaces = Changes[j].Spaces;
1529 }
else if (Depth == 0 &&
C.Tok->is(tok::r_brace)) {
1530 C.NewlinesBefore = 1;
1531 C.Spaces = EndSpaces;
1533 if (
C.Tok->StartsColumn) {
1536 bool HasSplit =
false;
1537 if (Changes[i].NewlinesBefore > 0) {
1553 if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) &&
1554 Changes[j - 1].NewlinesBefore > 0) {
1556 auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1557 if (LineLimit < Style.ColumnLimit) {
1558 Changes[i].NewlinesBefore = 0;
1559 Changes[i].Spaces = 1;
1563 while (Changes[i].NewlinesBefore > 0 && Changes[i].Tok ==
C.Tok) {
1564 Changes[i].Spaces = InitialSpaces;
1568 if (Changes[i].Tok !=
C.Tok)
1570 Cells.push_back(CellDescription{i, Cell, i, HasSplit,
nullptr});
1574 return linkCells({Cells, CellCounts, InitialSpaces});
1577unsigned WhitespaceManager::calculateCellWidth(
unsigned Start,
unsigned End,
1578 bool WithSpaces)
const {
1579 unsigned CellWidth = 0;
1580 for (
auto i = Start; i < End; i++) {
1581 if (Changes[i].NewlinesBefore > 0)
1583 CellWidth += Changes[i].TokenLength;
1584 CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
1589void WhitespaceManager::alignToStartOfCell(
unsigned Start,
unsigned End) {
1590 if ((End - Start) <= 1)
1594 for (
auto i = Start + 1; i < End; i++)
1595 if (Changes[i].NewlinesBefore > 0)
1596 Changes[i].Spaces = Changes[Start].Spaces;
1599WhitespaceManager::CellDescriptions
1600WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1601 auto &Cells = CellDesc.Cells;
1602 for (
auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
1603 if (!CellIter->NextColumnElement && (CellIter + 1) != Cells.end()) {
1604 for (
auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
1605 if (NextIter->Cell == CellIter->Cell) {
1606 CellIter->NextColumnElement = &(*NextIter);
1612 return std::move(CellDesc);
1615void WhitespaceManager::generateChanges() {
1616 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
1617 const Change &
C = Changes[i];
1619 auto Last = Changes[i - 1].OriginalWhitespaceRange;
1620 auto New = Changes[i].OriginalWhitespaceRange;
1662 if (
Last.getBegin() == New.getBegin() &&
1663 (
Last.getEnd() !=
Last.getBegin() ||
1664 New.getEnd() == New.getBegin())) {
1668 if (
C.CreateReplacement) {
1669 std::string ReplacementText =
C.PreviousLinePostfix;
1670 if (
C.ContinuesPPDirective) {
1671 appendEscapedNewlineText(ReplacementText,
C.NewlinesBefore,
1672 C.PreviousEndOfTokenColumn,
1673 C.EscapedNewlineColumn);
1675 appendNewlineText(ReplacementText,
C.NewlinesBefore);
1680 ReplacementText,
C.Tok->IndentLevel, std::max(0,
C.Spaces),
1681 std::max((
int)
C.StartOfTokenColumn,
C.Spaces) - std::max(0,
C.Spaces),
1683 ReplacementText.append(
C.CurrentLinePrefix);
1684 storeReplacement(
C.OriginalWhitespaceRange, ReplacementText);
1689void WhitespaceManager::storeReplacement(SourceRange
Range, StringRef
Text) {
1694 WhitespaceLength) ==
Text) {
1697 auto Err = Replaces.
add(tooling::Replacement(
1702 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
1707void WhitespaceManager::appendNewlineText(std::string &
Text,
1708 unsigned Newlines) {
1710 Text.reserve(
Text.size() + 2 * Newlines);
1711 for (
unsigned i = 0; i < Newlines; ++i)
1712 Text.append(
"\r\n");
1714 Text.append(Newlines,
'\n');
1718void WhitespaceManager::appendEscapedNewlineText(
1719 std::string &
Text,
unsigned Newlines,
unsigned PreviousEndOfTokenColumn,
1720 unsigned EscapedNewlineColumn) {
1723 std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
1724 for (
unsigned i = 0; i < Newlines; ++i) {
1725 Text.append(Spaces,
' ');
1726 Text.append(UseCRLF ?
"\\\r\n" :
"\\\n");
1727 Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
1732void WhitespaceManager::appendIndentText(std::string &
Text,
1733 unsigned IndentLevel,
unsigned Spaces,
1734 unsigned WhitespaceStartColumn,
1736 switch (Style.UseTab) {
1738 Text.append(Spaces,
' ');
1741 if (Style.TabWidth) {
1742 unsigned FirstTabWidth =
1743 Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
1746 if (Spaces < FirstTabWidth || Spaces == 1) {
1747 Text.append(Spaces,
' ');
1751 Spaces -= FirstTabWidth;
1754 Text.append(Spaces / Style.TabWidth,
'\t');
1755 Text.append(Spaces % Style.TabWidth,
' ');
1756 }
else if (Spaces == 1) {
1757 Text.append(Spaces,
' ');
1762 if (WhitespaceStartColumn == 0) {
1763 unsigned Indentation = IndentLevel * Style.IndentWidth;
1764 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1766 Text.append(Spaces,
' ');
1769 if (WhitespaceStartColumn == 0)
1770 Spaces = appendTabIndent(
Text, Spaces, Spaces);
1771 Text.append(Spaces,
' ');
1774 if (WhitespaceStartColumn == 0) {
1775 unsigned Indentation =
1776 IsAligned ? IndentLevel * Style.IndentWidth : Spaces;
1777 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1779 Text.append(Spaces,
' ');
1784unsigned WhitespaceManager::appendTabIndent(std::string &
Text,
unsigned Spaces,
1785 unsigned Indentation) {
1788 if (Indentation > Spaces)
1789 Indentation = Spaces;
1790 if (Style.TabWidth) {
1791 unsigned Tabs = Indentation / Style.TabWidth;
1792 Text.append(Tabs,
'\t');
1793 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())