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.empty() &&
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.empty();
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 &&
473 !CurrentChange.Tok->isOneOf(tok::equal, tok::r_paren,
474 TT_TemplateCloser)) {
475 const bool ReferenceNotRightAligned =
481 assert(Changes[
Previous].Tok->isPointerOrReference());
482 if (Changes[
Previous].Tok->isNot(tok::star)) {
483 if (ReferenceNotRightAligned)
488 Changes[
Previous + 1].Spaces -= Shift;
490 Changes[
Previous].StartOfTokenColumn += Shift;
532 bool RightJustify =
false) {
541 unsigned WidthLeft = 0;
544 unsigned WidthAnchor = 0;
547 unsigned WidthRight = 0;
550 unsigned StartOfSequence = 0;
551 unsigned EndOfSequence = 0;
555 auto IndentAndNestingLevel = StartAt < Changes.size()
556 ? Changes[StartAt].indentAndNestingLevel()
557 : std::tuple<unsigned, unsigned, unsigned>();
562 unsigned CommasBeforeLastMatch = 0;
563 unsigned CommasBeforeMatch = 0;
566 bool FoundMatchOnLine =
false;
569 bool LineIsComment =
true;
578 auto AlignCurrentSequence = [&] {
579 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
581 WidthLeft + WidthAnchor, RightJustify, Matches,
591 unsigned i = StartAt;
592 for (
unsigned e = Changes.size(); i != e; ++i) {
593 auto &CurrentChange = Changes[i];
594 if (CurrentChange.indentAndNestingLevel() < IndentAndNestingLevel)
597 if (CurrentChange.NewlinesBefore != 0) {
598 CommasBeforeMatch = 0;
602 bool EmptyLineBreak =
603 (CurrentChange.NewlinesBefore > 1) && !ACS.AcrossEmptyLines;
608 !FoundMatchOnLine && !(LineIsComment && ACS.AcrossComments);
610 if (EmptyLineBreak || NoMatchBreak)
611 AlignCurrentSequence();
615 if (i == 0 || CurrentChange.Tok->isNot(tok::string_literal) ||
616 Changes[i - 1].Tok->isNot(tok::string_literal)) {
617 FoundMatchOnLine =
false;
619 LineIsComment =
true;
622 if (CurrentChange.Tok->isNot(tok::comment))
623 LineIsComment =
false;
625 if (CurrentChange.Tok->is(tok::comma)) {
627 }
else if (CurrentChange.indentAndNestingLevel() > IndentAndNestingLevel) {
630 AlignTokens(Style, Matches, Changes, i, ACS, RightJustify);
635 if (!Matches(CurrentChange))
640 if (FoundMatchOnLine || CommasBeforeMatch != CommasBeforeLastMatch)
641 AlignCurrentSequence();
643 CommasBeforeLastMatch = CommasBeforeMatch;
644 FoundMatchOnLine =
true;
646 if (StartOfSequence == 0)
649 unsigned ChangeWidthLeft = CurrentChange.StartOfTokenColumn;
650 unsigned ChangeWidthAnchor = 0;
651 unsigned ChangeWidthRight = 0;
653 if (ACS.PadOperators)
654 ChangeWidthAnchor = CurrentChange.TokenLength;
656 ChangeWidthLeft += CurrentChange.TokenLength;
658 ChangeWidthRight = CurrentChange.TokenLength;
659 for (
unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) {
660 ChangeWidthRight += Changes[j].Spaces;
666 if (!Changes[j].IsInsideToken)
667 ChangeWidthRight += Changes[j].TokenLength;
671 unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
672 unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
673 unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
675 if (Style.ColumnLimit != 0 &&
676 Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
677 AlignCurrentSequence();
679 WidthLeft = ChangeWidthLeft;
680 WidthAnchor = ChangeWidthAnchor;
681 WidthRight = ChangeWidthRight;
684 WidthAnchor = NewAnchor;
685 WidthRight = NewRight;
690 AlignCurrentSequence();
702 unsigned &StartOfSequence,
unsigned &EndOfSequence,
unsigned &MinColumn,
705 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
706 bool FoundMatchOnLine =
false;
709 for (
unsigned I = StartOfSequence; I != EndOfSequence; ++I) {
710 if (Changes[I].NewlinesBefore > 0) {
712 FoundMatchOnLine =
false;
718 if (!FoundMatchOnLine && Matches(Changes[I])) {
719 FoundMatchOnLine =
true;
720 Shift = MinColumn - Changes[I].StartOfTokenColumn;
721 Changes[I].Spaces += Shift;
725 Changes[I].StartOfTokenColumn += Shift;
726 if (I + 1 != Changes.size())
727 Changes[I + 1].PreviousEndOfTokenColumn += Shift;
736void WhitespaceManager::alignConsecutiveMacros() {
737 if (!Style.AlignConsecutiveMacros.Enabled)
740 auto AlignMacrosMatches = [](
const Change &
C) {
741 const FormatToken *Current =
C.Tok;
742 unsigned SpacesRequiredBefore = 1;
744 if (Current->SpacesRequiredBefore == 0 || !Current->Previous)
747 Current = Current->Previous;
751 if (Current->is(tok::r_paren) && Current->MatchingParen) {
752 Current = Current->MatchingParen->Previous;
753 SpacesRequiredBefore = 0;
756 if (!Current || Current->isNot(tok::identifier))
759 if (!Current->Previous || Current->Previous->isNot(tok::pp_define))
766 return Current->Next->SpacesRequiredBefore == SpacesRequiredBefore;
769 unsigned MinColumn = 0;
772 unsigned StartOfSequence = 0;
773 unsigned EndOfSequence = 0;
776 bool FoundMatchOnLine =
false;
779 bool LineIsComment =
true;
782 for (
unsigned E = Changes.size(); I !=
E; ++I) {
783 if (Changes[I].NewlinesBefore != 0) {
787 bool EmptyLineBreak = (Changes[I].NewlinesBefore > 1) &&
788 !Style.AlignConsecutiveMacros.AcrossEmptyLines;
794 !(LineIsComment && Style.AlignConsecutiveMacros.AcrossComments);
796 if (EmptyLineBreak || NoMatchBreak) {
798 AlignMacrosMatches, Changes);
802 FoundMatchOnLine =
false;
803 LineIsComment =
true;
806 if (Changes[I].Tok->isNot(tok::comment))
807 LineIsComment =
false;
809 if (!AlignMacrosMatches(Changes[I]))
812 FoundMatchOnLine =
true;
814 if (StartOfSequence == 0)
817 unsigned ChangeMinColumn = Changes[I].StartOfTokenColumn;
818 MinColumn = std::max(MinColumn, ChangeMinColumn);
823 AlignMacrosMatches, Changes);
826void WhitespaceManager::alignConsecutiveAssignments() {
827 if (!Style.AlignConsecutiveAssignments.Enabled)
832 [&](
const Change &
C) {
834 if (
C.NewlinesBefore > 0)
838 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
842 FormatToken *
Previous =
C.Tok->getPreviousNonComment();
846 return Style.AlignConsecutiveAssignments.AlignCompound
848 : (
C.Tok->is(tok::equal) ||
852 (Style.isVerilog() &&
C.Tok->is(tok::lessequal) &&
855 Changes, 0, Style.AlignConsecutiveAssignments,
859void WhitespaceManager::alignConsecutiveBitFields() {
860 alignConsecutiveColons(Style.AlignConsecutiveBitFields, TT_BitFieldColon);
863void WhitespaceManager::alignConsecutiveColons(
864 const FormatStyle::AlignConsecutiveStyle &AlignStyle,
TokenType Type) {
865 if (!AlignStyle.Enabled)
870 [&](Change
const &
C) {
872 if (
C.NewlinesBefore > 0)
876 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
879 return C.Tok->is(Type);
881 Changes, 0, AlignStyle);
884void WhitespaceManager::alignConsecutiveShortCaseStatements(
bool IsExpr) {
885 if (!Style.AlignConsecutiveShortCaseStatements.Enabled ||
886 !(IsExpr ? Style.AllowShortCaseExpressionOnASingleLine
887 : Style.AllowShortCaseLabelsOnASingleLine)) {
891 const auto Type = IsExpr ? TT_CaseLabelArrow : TT_CaseLabelColon;
892 const auto &Option = Style.AlignConsecutiveShortCaseStatements;
893 const bool AlignArrowOrColon =
894 IsExpr ? Option.AlignCaseArrows : Option.AlignCaseColons;
896 auto Matches = [&](
const Change &
C) {
897 if (AlignArrowOrColon)
898 return C.Tok->is(Type);
904 return !
C.IsInsideToken &&
C.Tok->Previous &&
C.Tok->Previous->is(Type);
907 unsigned MinColumn = 0;
912 unsigned MinEmptyCaseColumn = 0;
915 unsigned StartOfSequence = 0;
916 unsigned EndOfSequence = 0;
919 bool FoundMatchOnLine =
false;
921 bool LineIsComment =
true;
922 bool LineIsEmptyCase =
false;
925 for (
unsigned E = Changes.size(); I !=
E; ++I) {
926 if (Changes[I].NewlinesBefore != 0) {
928 bool EmptyLineBreak =
929 (Changes[I].NewlinesBefore > 1) &&
930 !Style.AlignConsecutiveShortCaseStatements.AcrossEmptyLines;
937 Style.AlignConsecutiveShortCaseStatements.AcrossComments) &&
940 if (EmptyLineBreak || NoMatchBreak) {
943 MinEmptyCaseColumn = 0;
947 FoundMatchOnLine =
false;
948 LineIsComment =
true;
949 LineIsEmptyCase =
false;
952 if (Changes[I].Tok->isNot(tok::comment))
953 LineIsComment =
false;
955 if (Changes[I].Tok->is(Type)) {
957 !Changes[I].Tok->Next || Changes[I].Tok->Next->isTrailingComment();
959 if (LineIsEmptyCase) {
960 if (Style.AlignConsecutiveShortCaseStatements.AlignCaseColons) {
962 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn);
965 std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn + 2);
970 if (!Matches(Changes[I]))
976 FoundMatchOnLine =
true;
978 if (StartOfSequence == 0)
981 EndOfSequence = I + 1;
983 MinColumn = std::max(MinColumn, Changes[I].StartOfTokenColumn);
986 MinColumn = std::max(MinColumn, MinEmptyCaseColumn);
993void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() {
994 alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons,
995 TT_TableGenDAGArgListColonToAlign);
998void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() {
999 alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons,
1000 TT_TableGenCondOperatorColon);
1003void WhitespaceManager::alignConsecutiveTableGenDefinitions() {
1004 alignConsecutiveColons(Style.AlignConsecutiveTableGenDefinitionColons,
1005 TT_InheritanceColon);
1008void WhitespaceManager::alignConsecutiveDeclarations() {
1009 if (!Style.AlignConsecutiveDeclarations.Enabled)
1014 [&](Change
const &
C) {
1015 if (
C.Tok->is(TT_FunctionTypeLParen))
1016 return Style.AlignConsecutiveDeclarations.AlignFunctionPointers;
1017 if (
C.Tok->is(TT_FunctionDeclarationName))
1018 return Style.AlignConsecutiveDeclarations.AlignFunctionDeclarations;
1019 if (
C.Tok->isNot(TT_StartOfName))
1021 if (
C.Tok->Previous &&
1022 C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
1025 for (FormatToken *Next =
C.Tok->Next; Next; Next = Next->Next) {
1026 if (Next->is(tok::comment))
1028 if (Next->is(TT_PointerOrReference))
1030 if (!Next->Tok.getIdentifierInfo())
1032 if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
1033 tok::kw_operator)) {
1039 Changes, 0, Style.AlignConsecutiveDeclarations);
1042void WhitespaceManager::alignChainedConditionals() {
1043 if (Style.BreakBeforeTernaryOperators) {
1046 [](Change
const &
C) {
1048 return C.Tok->is(TT_ConditionalExpr) &&
1049 ((
C.Tok->is(tok::question) && !
C.NewlinesBefore) ||
1050 (
C.Tok->is(tok::colon) &&
C.Tok->Next &&
1051 (
C.Tok->Next->FakeLParens.empty() ||
1056 static auto AlignWrappedOperand = [](Change
const &
C) {
1057 FormatToken *
Previous =
C.Tok->getPreviousNonComment();
1060 (
C.Tok->FakeLParens.empty() ||
1066 for (Change &
C : Changes)
1067 if (AlignWrappedOperand(
C))
1068 C.StartOfTokenColumn -= 2;
1071 [
this](Change
const &
C) {
1075 return (
C.Tok->is(TT_ConditionalExpr) &&
C.Tok->is(tok::question) &&
1076 &
C != &Changes.back() && (&
C + 1)->NewlinesBefore == 0 &&
1077 !(&
C + 1)->IsTrailingComment) ||
1078 AlignWrappedOperand(
C);
1084void WhitespaceManager::alignTrailingComments() {
1088 const int Size = Changes.size();
1090 int StartOfSequence = 0;
1091 bool BreakBeforeNext =
false;
1092 int NewLineThreshold = 1;
1094 NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
1096 for (
int I = 0, MaxColumn =
INT_MAX, Newlines = 0; I <
Size; ++I) {
1097 auto &
C = Changes[I];
1098 if (
C.StartOfBlockComment)
1100 Newlines +=
C.NewlinesBefore;
1101 if (!
C.IsTrailingComment)
1105 const int OriginalSpaces =
1106 C.OriginalWhitespaceRange.getEnd().getRawEncoding() -
1107 C.OriginalWhitespaceRange.getBegin().getRawEncoding() -
1108 C.Tok->LastNewlineOffset;
1109 assert(OriginalSpaces >= 0);
1110 const auto RestoredLineLength =
1111 C.StartOfTokenColumn +
C.TokenLength + OriginalSpaces;
1114 if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
1116 C.Spaces =
C.NewlinesBefore > 0 ?
C.Tok->OriginalColumn : OriginalSpaces;
1120 const int ChangeMinColumn =
C.StartOfTokenColumn;
1121 int ChangeMaxColumn;
1125 if (!
C.CreateReplacement)
1126 ChangeMaxColumn = ChangeMinColumn;
1127 else if (Style.ColumnLimit == 0)
1129 else if (Style.ColumnLimit >=
C.TokenLength)
1130 ChangeMaxColumn = Style.ColumnLimit -
C.TokenLength;
1132 ChangeMaxColumn = ChangeMinColumn;
1134 if (I + 1 < Size && Changes[I + 1].ContinuesPPDirective &&
1135 ChangeMaxColumn >= 2) {
1136 ChangeMaxColumn -= 2;
1139 bool WasAlignedWithStartOfNextLine =
false;
1140 if (
C.NewlinesBefore >= 1) {
1141 const auto CommentColumn =
1143 for (
int J = I + 1; J <
Size; ++J) {
1144 if (Changes[J].Tok->is(tok::comment))
1148 Changes[J].OriginalWhitespaceRange.getEnd());
1151 WasAlignedWithStartOfNextLine =
1152 CommentColumn == NextColumn ||
1153 CommentColumn == NextColumn + Style.IndentWidth;
1160 auto DontAlignThisComment = [](
const auto *Tok) {
1161 if (Tok->is(tok::semi)) {
1162 Tok = Tok->getPreviousNonComment();
1166 if (Tok->is(tok::r_paren)) {
1168 Tok = Tok->MatchingParen;
1171 Tok = Tok->getPreviousNonComment();
1174 if (Tok->is(TT_DoWhile)) {
1175 const auto *Prev = Tok->getPreviousNonComment();
1184 if (Tok->isNot(tok::r_brace))
1187 while (Tok->Previous && Tok->Previous->is(tok::r_brace))
1188 Tok = Tok->Previous;
1189 return Tok->NewlinesBefore > 0;
1192 if (I > 0 &&
C.NewlinesBefore == 0 &&
1193 DontAlignThisComment(Changes[I - 1].Tok)) {
1194 alignTrailingComments(StartOfSequence, I, MinColumn);
1199 StartOfSequence = I + 1;
1200 }
else if (BreakBeforeNext || Newlines > NewLineThreshold ||
1201 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
1204 (
C.NewlinesBefore == 1 && I > 0 &&
1205 !Changes[I - 1].IsTrailingComment) ||
1206 WasAlignedWithStartOfNextLine) {
1207 alignTrailingComments(StartOfSequence, I, MinColumn);
1208 MinColumn = ChangeMinColumn;
1209 MaxColumn = ChangeMaxColumn;
1210 StartOfSequence = I;
1212 MinColumn = std::max(MinColumn, ChangeMinColumn);
1213 MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
1215 BreakBeforeNext = (I == 0) || (
C.NewlinesBefore > 1) ||
1218 (
C.NewlinesBefore == 1 && StartOfSequence == I);
1221 alignTrailingComments(StartOfSequence, Size, MinColumn);
1224void WhitespaceManager::alignTrailingComments(
unsigned Start,
unsigned End,
1226 for (
unsigned i = Start; i != End; ++i) {
1228 if (Changes[i].IsTrailingComment)
1230 if (Changes[i].StartOfBlockComment) {
1231 Shift = Changes[i].IndentationOffset +
1232 Changes[i].StartOfBlockComment->StartOfTokenColumn -
1233 Changes[i].StartOfTokenColumn;
1237 Changes[i].Spaces +=
Shift;
1238 if (i + 1 != Changes.size())
1239 Changes[i + 1].PreviousEndOfTokenColumn +=
Shift;
1240 Changes[i].StartOfTokenColumn +=
Shift;
1244void WhitespaceManager::alignEscapedNewlines() {
1245 const auto Align = Style.AlignEscapedNewlines;
1251 const auto MaxColumn = Style.ColumnLimit;
1252 unsigned MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1253 unsigned StartOfMacro = 0;
1254 for (
unsigned i = 1, e = Changes.size(); i < e; ++i) {
1255 Change &
C = Changes[i];
1256 if (
C.NewlinesBefore == 0 && (!WithLastLine ||
C.Tok->isNot(tok::eof)))
1258 const bool InPPDirective =
C.ContinuesPPDirective;
1259 const auto BackslashColumn =
C.PreviousEndOfTokenColumn + 2;
1260 if (InPPDirective ||
1261 (WithLastLine && (MaxColumn == 0 || BackslashColumn <= MaxColumn))) {
1262 MaxEndOfLine = std::max(BackslashColumn, MaxEndOfLine);
1264 if (!InPPDirective) {
1265 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
1266 MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1270 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
1273void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
1275 for (
unsigned i = Start; i < End; ++i) {
1276 Change &
C = Changes[i];
1277 if (
C.NewlinesBefore > 0) {
1278 assert(
C.ContinuesPPDirective);
1279 if (
C.PreviousEndOfTokenColumn + 1 >
Column)
1280 C.EscapedNewlineColumn = 0;
1282 C.EscapedNewlineColumn =
Column;
1287void WhitespaceManager::alignArrayInitializers() {
1291 for (
unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
1292 ChangeIndex < ChangeEnd; ++ChangeIndex) {
1293 auto &
C = Changes[ChangeIndex];
1294 if (
C.Tok->IsArrayInitializer) {
1295 bool FoundComplete =
false;
1296 for (
unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
1298 if (Changes[InsideIndex].Tok ==
C.Tok->MatchingParen) {
1299 alignArrayInitializers(ChangeIndex, InsideIndex + 1);
1300 ChangeIndex = InsideIndex + 1;
1301 FoundComplete =
true;
1306 ChangeIndex = ChangeEnd;
1311void WhitespaceManager::alignArrayInitializers(
unsigned Start,
unsigned End) {
1314 alignArrayInitializersRightJustified(getCells(Start, End));
1316 alignArrayInitializersLeftJustified(getCells(Start, End));
1319void WhitespaceManager::alignArrayInitializersRightJustified(
1320 CellDescriptions &&CellDescs) {
1321 if (!CellDescs.isRectangular())
1324 const int BracePadding = Style.Cpp11BracedListStyle ? 0 : 1;
1325 auto &Cells = CellDescs.Cells;
1327 auto *CellIter = Cells.begin();
1328 for (
auto i = 0
U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {
1329 unsigned NetWidth = 0
U;
1330 if (isSplitCell(*CellIter))
1331 NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1332 auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1334 if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1338 const auto *Next = CellIter;
1340 const FormatToken *
Previous = Changes[Next->Index].Tok->Previous;
1342 Changes[Next->Index].Spaces = BracePadding;
1343 Changes[Next->Index].NewlinesBefore = 0;
1345 Next = Next->NextColumnElement;
1349 if (CellIter != Cells.begin()) {
1351 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1352 auto MaxNetWidth = getMaximumNetWidth(
1353 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1354 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1355 if (ThisNetWidth < MaxNetWidth)
1356 Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1358 auto Offset = std::distance(Cells.begin(), CellIter);
1359 for (
const auto *Next = CellIter->NextColumnElement; Next;
1360 Next = Next->NextColumnElement) {
1361 if (RowCount >= CellDescs.CellCounts.size())
1363 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1364 auto *End = Start + Offset;
1365 ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1366 if (ThisNetWidth < MaxNetWidth)
1367 Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1373 calculateCellWidth(CellIter->Index, CellIter->EndIndex,
true) +
1375 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1376 Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
1377 Changes[CellIter->Index].Spaces += (i > 0) ? 1 : BracePadding;
1379 alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1380 for (
const auto *Next = CellIter->NextColumnElement; Next;
1381 Next = Next->NextColumnElement) {
1383 calculateCellWidth(Next->Index, Next->EndIndex,
true) + NetWidth;
1384 if (Changes[Next->Index].NewlinesBefore == 0) {
1385 Changes[Next->Index].Spaces = (CellWidth - ThisWidth);
1386 Changes[Next->Index].Spaces += (i > 0) ? 1 : BracePadding;
1388 alignToStartOfCell(Next->Index, Next->EndIndex);
1394void WhitespaceManager::alignArrayInitializersLeftJustified(
1395 CellDescriptions &&CellDescs) {
1397 if (!CellDescs.isRectangular())
1400 const int BracePadding = Style.Cpp11BracedListStyle ? 0 : 1;
1401 auto &Cells = CellDescs.Cells;
1403 auto *CellIter = Cells.begin();
1405 for (
const auto *Next = CellIter; Next; Next = Next->NextColumnElement) {
1406 auto &Change = Changes[Next->Index];
1408 Change.NewlinesBefore == 0 ? BracePadding : CellDescs.InitialSpaces;
1411 for (
auto i = 1U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {
1412 auto MaxNetWidth = getMaximumNetWidth(
1413 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1414 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1416 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1417 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1418 Changes[CellIter->Index].Spaces =
1419 MaxNetWidth - ThisNetWidth +
1420 (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1
1424 auto Offset = std::distance(Cells.begin(), CellIter);
1425 for (
const auto *Next = CellIter->NextColumnElement; Next;
1426 Next = Next->NextColumnElement) {
1427 if (RowCount >= CellDescs.CellCounts.size())
1429 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1430 auto *End = Start + Offset;
1431 auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1432 if (Changes[Next->Index].NewlinesBefore == 0) {
1433 Changes[Next->Index].Spaces =
1434 MaxNetWidth - ThisNetWidth +
1435 (Changes[Next->Index].Tok->isNot(tok::r_brace) ? 1 : BracePadding);
1442bool WhitespaceManager::isSplitCell(
const CellDescription &Cell) {
1445 for (
const auto *Next = Cell.NextColumnElement; Next;
1446 Next = Next->NextColumnElement) {
1453WhitespaceManager::CellDescriptions WhitespaceManager::getCells(
unsigned Start,
1458 SmallVector<unsigned> CellCounts;
1459 unsigned InitialSpaces = 0;
1460 unsigned InitialTokenLength = 0;
1461 unsigned EndSpaces = 0;
1462 SmallVector<CellDescription> Cells;
1463 const FormatToken *MatchingParen =
nullptr;
1464 for (
unsigned i = Start; i < End; ++i) {
1465 auto &
C = Changes[i];
1466 if (
C.Tok->is(tok::l_brace))
1468 else if (
C.Tok->is(tok::r_brace))
1471 if (
C.Tok->is(tok::l_brace)) {
1473 MatchingParen =
C.Tok->MatchingParen;
1474 if (InitialSpaces == 0) {
1475 InitialSpaces =
C.Spaces +
C.TokenLength;
1476 InitialTokenLength =
C.TokenLength;
1478 for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
1479 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1480 InitialTokenLength += Changes[j].TokenLength;
1482 if (
C.NewlinesBefore == 0) {
1483 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1484 InitialTokenLength += Changes[j].TokenLength;
1487 }
else if (
C.Tok->is(tok::comma)) {
1489 Cells.back().EndIndex = i;
1490 if (
const auto *Next =
C.Tok->getNextNonComment();
1491 Next && Next->isNot(tok::r_brace)) {
1495 }
else if (Depth == 1) {
1496 if (
C.Tok == MatchingParen) {
1498 Cells.back().EndIndex = i;
1499 Cells.push_back(CellDescription{i, ++Cell, i + 1,
false,
nullptr});
1500 CellCounts.push_back(
C.Tok->Previous->isNot(tok::comma) ? Cell + 1
1503 const auto *NextNonComment =
C.Tok->getNextNonComment();
1504 while (NextNonComment && NextNonComment->is(tok::comma))
1505 NextNonComment = NextNonComment->getNextNonComment();
1507 while (j < End && Changes[j].Tok != NextNonComment)
1509 if (j < End && Changes[j].NewlinesBefore == 0 &&
1510 Changes[j].Tok->isNot(tok::r_brace)) {
1511 Changes[j].NewlinesBefore = 1;
1513 Changes[j].Spaces = InitialSpaces - InitialTokenLength;
1515 }
else if (
C.Tok->is(tok::comment) &&
C.Tok->NewlinesBefore == 0) {
1517 C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 1 : 2;
1518 }
else if (
C.Tok->is(tok::l_brace)) {
1522 for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
1524 EndSpaces = Changes[j].Spaces;
1526 }
else if (Depth == 0 &&
C.Tok->is(tok::r_brace)) {
1527 C.NewlinesBefore = 1;
1528 C.Spaces = EndSpaces;
1530 if (
C.Tok->StartsColumn) {
1533 bool HasSplit =
false;
1534 if (Changes[i].NewlinesBefore > 0) {
1550 if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) &&
1551 Changes[j - 1].NewlinesBefore > 0) {
1553 auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1554 if (LineLimit < Style.ColumnLimit) {
1555 Changes[i].NewlinesBefore = 0;
1556 Changes[i].Spaces = 1;
1560 while (Changes[i].NewlinesBefore > 0 && Changes[i].Tok ==
C.Tok) {
1561 Changes[i].Spaces = InitialSpaces;
1565 if (Changes[i].Tok !=
C.Tok)
1567 Cells.push_back(CellDescription{i, Cell, i, HasSplit,
nullptr});
1571 return linkCells({Cells, CellCounts, InitialSpaces});
1574unsigned WhitespaceManager::calculateCellWidth(
unsigned Start,
unsigned End,
1575 bool WithSpaces)
const {
1576 unsigned CellWidth = 0;
1577 for (
auto i = Start; i < End; i++) {
1578 if (Changes[i].NewlinesBefore > 0)
1580 CellWidth += Changes[i].TokenLength;
1581 CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
1586void WhitespaceManager::alignToStartOfCell(
unsigned Start,
unsigned End) {
1587 if ((End - Start) <= 1)
1591 for (
auto i = Start + 1; i < End; i++)
1592 if (Changes[i].NewlinesBefore > 0)
1593 Changes[i].Spaces = Changes[Start].Spaces;
1596WhitespaceManager::CellDescriptions
1597WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1598 auto &Cells = CellDesc.Cells;
1599 for (
auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
1600 if (!CellIter->NextColumnElement && (CellIter + 1) != Cells.end()) {
1601 for (
auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
1602 if (NextIter->Cell == CellIter->Cell) {
1603 CellIter->NextColumnElement = &(*NextIter);
1609 return std::move(CellDesc);
1612void WhitespaceManager::generateChanges() {
1613 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
1614 const Change &
C = Changes[i];
1616 auto Last = Changes[i - 1].OriginalWhitespaceRange;
1617 auto New = Changes[i].OriginalWhitespaceRange;
1659 if (
Last.getBegin() ==
New.getBegin() &&
1660 (
Last.getEnd() !=
Last.getBegin() ||
1661 New.getEnd() ==
New.getBegin())) {
1665 if (
C.CreateReplacement) {
1666 std::string ReplacementText =
C.PreviousLinePostfix;
1667 if (
C.ContinuesPPDirective) {
1668 appendEscapedNewlineText(ReplacementText,
C.NewlinesBefore,
1669 C.PreviousEndOfTokenColumn,
1670 C.EscapedNewlineColumn);
1672 appendNewlineText(ReplacementText,
C);
1677 ReplacementText,
C.Tok->IndentLevel, std::max(0,
C.Spaces),
1678 std::max((
int)
C.StartOfTokenColumn,
C.Spaces) - std::max(0,
C.Spaces),
1680 ReplacementText.append(
C.CurrentLinePrefix);
1681 storeReplacement(
C.OriginalWhitespaceRange, ReplacementText);
1686void WhitespaceManager::storeReplacement(SourceRange
Range, StringRef
Text) {
1691 WhitespaceLength) ==
Text) {
1694 auto Err = Replaces.
add(tooling::Replacement(
1699 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
1704void WhitespaceManager::appendNewlineText(std::string &
Text,
const Change &
C) {
1705 if (
C.NewlinesBefore <= 0)
1708 StringRef Newline = UseCRLF ?
"\r\n" :
"\n";
1709 Text.append(Newline);
1711 if (
C.Tok->HasFormFeedBefore)
1714 for (
unsigned I = 1; I <
C.NewlinesBefore; ++I)
1715 Text.append(Newline);
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())
int const char * function