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 &&
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 (Style.AlignConsecutiveDeclarations.AlignFunctionPointers) {
1016 for (const auto *Prev = C.Tok->Previous; Prev; Prev = Prev->Previous)
1017 if (Prev->is(tok::equal))
1019 if (C.Tok->is(TT_FunctionTypeLParen))
1022 if (
C.Tok->is(TT_FunctionDeclarationName))
1023 return Style.AlignConsecutiveDeclarations.AlignFunctionDeclarations;
1024 if (
C.Tok->isNot(TT_StartOfName))
1026 if (
C.Tok->Previous &&
1027 C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
1030 for (FormatToken *Next =
C.Tok->Next; Next; Next = Next->Next) {
1031 if (Next->is(tok::comment))
1033 if (Next->is(TT_PointerOrReference))
1035 if (!Next->Tok.getIdentifierInfo())
1037 if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
1038 tok::kw_operator)) {
1044 Changes, 0, Style.AlignConsecutiveDeclarations);
1047void WhitespaceManager::alignChainedConditionals() {
1048 if (Style.BreakBeforeTernaryOperators) {
1051 [](Change
const &
C) {
1053 return C.Tok->is(TT_ConditionalExpr) &&
1054 ((
C.Tok->is(tok::question) && !
C.NewlinesBefore) ||
1055 (
C.Tok->is(tok::colon) &&
C.Tok->Next &&
1056 (
C.Tok->Next->FakeLParens.size() == 0 ||
1061 static auto AlignWrappedOperand = [](Change
const &
C) {
1062 FormatToken *
Previous =
C.Tok->getPreviousNonComment();
1065 (
C.Tok->FakeLParens.size() == 0 ||
1071 for (Change &
C : Changes)
1072 if (AlignWrappedOperand(
C))
1073 C.StartOfTokenColumn -= 2;
1076 [
this](Change
const &
C) {
1080 return (
C.Tok->is(TT_ConditionalExpr) &&
C.Tok->is(tok::question) &&
1081 &
C != &Changes.back() && (&
C + 1)->NewlinesBefore == 0 &&
1082 !(&
C + 1)->IsTrailingComment) ||
1083 AlignWrappedOperand(
C);
1089void WhitespaceManager::alignTrailingComments() {
1093 const int Size = Changes.size();
1095 int StartOfSequence = 0;
1096 bool BreakBeforeNext =
false;
1097 int NewLineThreshold = 1;
1099 NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
1101 for (
int I = 0, MaxColumn =
INT_MAX, Newlines = 0; I <
Size; ++I) {
1102 auto &
C = Changes[I];
1103 if (
C.StartOfBlockComment)
1105 Newlines +=
C.NewlinesBefore;
1106 if (!
C.IsTrailingComment)
1110 const int OriginalSpaces =
1111 C.OriginalWhitespaceRange.getEnd().getRawEncoding() -
1112 C.OriginalWhitespaceRange.getBegin().getRawEncoding() -
1113 C.Tok->LastNewlineOffset;
1114 assert(OriginalSpaces >= 0);
1115 const auto RestoredLineLength =
1116 C.StartOfTokenColumn +
C.TokenLength + OriginalSpaces;
1119 if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
1121 C.Spaces =
C.NewlinesBefore > 0 ?
C.Tok->OriginalColumn : OriginalSpaces;
1125 const int ChangeMinColumn =
C.StartOfTokenColumn;
1126 int ChangeMaxColumn;
1130 if (!
C.CreateReplacement)
1131 ChangeMaxColumn = ChangeMinColumn;
1132 else if (Style.ColumnLimit == 0)
1134 else if (Style.ColumnLimit >=
C.TokenLength)
1135 ChangeMaxColumn = Style.ColumnLimit -
C.TokenLength;
1137 ChangeMaxColumn = ChangeMinColumn;
1139 if (I + 1 < Size && Changes[I + 1].ContinuesPPDirective &&
1140 ChangeMaxColumn >= 2) {
1141 ChangeMaxColumn -= 2;
1144 bool WasAlignedWithStartOfNextLine =
false;
1145 if (
C.NewlinesBefore >= 1) {
1146 const auto CommentColumn =
1148 for (
int J = I + 1; J <
Size; ++J) {
1149 if (Changes[J].Tok->is(tok::comment))
1153 Changes[J].OriginalWhitespaceRange.getEnd());
1156 WasAlignedWithStartOfNextLine =
1157 CommentColumn == NextColumn ||
1158 CommentColumn == NextColumn + Style.IndentWidth;
1165 auto DontAlignThisComment = [](
const auto *Tok) {
1166 if (Tok->is(tok::semi)) {
1167 Tok = Tok->getPreviousNonComment();
1171 if (Tok->is(tok::r_paren)) {
1173 Tok = Tok->MatchingParen;
1176 Tok = Tok->getPreviousNonComment();
1179 if (Tok->is(TT_DoWhile)) {
1180 const auto *Prev = Tok->getPreviousNonComment();
1189 if (Tok->isNot(tok::r_brace))
1192 while (Tok->Previous && Tok->Previous->is(tok::r_brace))
1193 Tok = Tok->Previous;
1194 return Tok->NewlinesBefore > 0;
1197 if (I > 0 &&
C.NewlinesBefore == 0 &&
1198 DontAlignThisComment(Changes[I - 1].Tok)) {
1199 alignTrailingComments(StartOfSequence, I, MinColumn);
1204 StartOfSequence = I + 1;
1205 }
else if (BreakBeforeNext || Newlines > NewLineThreshold ||
1206 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
1209 (
C.NewlinesBefore == 1 && I > 0 &&
1210 !Changes[I - 1].IsTrailingComment) ||
1211 WasAlignedWithStartOfNextLine) {
1212 alignTrailingComments(StartOfSequence, I, MinColumn);
1213 MinColumn = ChangeMinColumn;
1214 MaxColumn = ChangeMaxColumn;
1215 StartOfSequence = I;
1217 MinColumn = std::max(MinColumn, ChangeMinColumn);
1218 MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
1220 BreakBeforeNext = (I == 0) || (
C.NewlinesBefore > 1) ||
1223 (
C.NewlinesBefore == 1 && StartOfSequence == I);
1226 alignTrailingComments(StartOfSequence, Size, MinColumn);
1229void WhitespaceManager::alignTrailingComments(
unsigned Start,
unsigned End,
1231 for (
unsigned i = Start; i != End; ++i) {
1233 if (Changes[i].IsTrailingComment)
1235 if (Changes[i].StartOfBlockComment) {
1236 Shift = Changes[i].IndentationOffset +
1237 Changes[i].StartOfBlockComment->StartOfTokenColumn -
1238 Changes[i].StartOfTokenColumn;
1242 Changes[i].Spaces +=
Shift;
1243 if (i + 1 != Changes.size())
1244 Changes[i + 1].PreviousEndOfTokenColumn +=
Shift;
1245 Changes[i].StartOfTokenColumn +=
Shift;
1249void WhitespaceManager::alignEscapedNewlines() {
1250 const auto Align = Style.AlignEscapedNewlines;
1256 const auto MaxColumn = Style.ColumnLimit;
1257 unsigned MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1258 unsigned StartOfMacro = 0;
1259 for (
unsigned i = 1, e = Changes.size(); i < e; ++i) {
1260 Change &
C = Changes[i];
1261 if (
C.NewlinesBefore == 0 && (!WithLastLine ||
C.Tok->isNot(tok::eof)))
1263 const bool InPPDirective =
C.ContinuesPPDirective;
1264 const auto BackslashColumn =
C.PreviousEndOfTokenColumn + 2;
1265 if (InPPDirective ||
1266 (WithLastLine && (MaxColumn == 0 || BackslashColumn <= MaxColumn))) {
1267 MaxEndOfLine = std::max(BackslashColumn, MaxEndOfLine);
1269 if (!InPPDirective) {
1270 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
1271 MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1275 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
1278void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
1280 for (
unsigned i = Start; i < End; ++i) {
1281 Change &
C = Changes[i];
1282 if (
C.NewlinesBefore > 0) {
1283 assert(
C.ContinuesPPDirective);
1284 if (
C.PreviousEndOfTokenColumn + 1 >
Column)
1285 C.EscapedNewlineColumn = 0;
1287 C.EscapedNewlineColumn =
Column;
1292void WhitespaceManager::alignArrayInitializers() {
1296 for (
unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
1297 ChangeIndex < ChangeEnd; ++ChangeIndex) {
1298 auto &
C = Changes[ChangeIndex];
1299 if (
C.Tok->IsArrayInitializer) {
1300 bool FoundComplete =
false;
1301 for (
unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
1303 if (Changes[InsideIndex].Tok ==
C.Tok->MatchingParen) {
1304 alignArrayInitializers(ChangeIndex, InsideIndex + 1);
1305 ChangeIndex = InsideIndex + 1;
1306 FoundComplete =
true;
1311 ChangeIndex = ChangeEnd;
1316void WhitespaceManager::alignArrayInitializers(
unsigned Start,
unsigned End) {
1319 alignArrayInitializersRightJustified(getCells(Start, End));
1321 alignArrayInitializersLeftJustified(getCells(Start, End));
1324void WhitespaceManager::alignArrayInitializersRightJustified(
1325 CellDescriptions &&CellDescs) {
1326 if (!CellDescs.isRectangular())
1329 const int BracePadding = Style.Cpp11BracedListStyle ? 0 : 1;
1330 auto &Cells = CellDescs.Cells;
1332 auto *CellIter = Cells.begin();
1333 for (
auto i = 0
U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {
1334 unsigned NetWidth = 0
U;
1335 if (isSplitCell(*CellIter))
1336 NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1337 auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1339 if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1343 const auto *Next = CellIter;
1345 const FormatToken *
Previous = Changes[Next->Index].Tok->Previous;
1347 Changes[Next->Index].Spaces = BracePadding;
1348 Changes[Next->Index].NewlinesBefore = 0;
1350 Next = Next->NextColumnElement;
1354 if (CellIter != Cells.begin()) {
1356 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1357 auto MaxNetWidth = getMaximumNetWidth(
1358 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1359 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1360 if (ThisNetWidth < MaxNetWidth)
1361 Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1363 auto Offset = std::distance(Cells.begin(), CellIter);
1364 for (
const auto *Next = CellIter->NextColumnElement; Next;
1365 Next = Next->NextColumnElement) {
1366 if (RowCount >= CellDescs.CellCounts.size())
1368 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1369 auto *End = Start + Offset;
1370 ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1371 if (ThisNetWidth < MaxNetWidth)
1372 Changes[Next->Index].Spaces = (MaxNetWidth - ThisNetWidth);
1378 calculateCellWidth(CellIter->Index, CellIter->EndIndex,
true) +
1380 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1381 Changes[CellIter->Index].Spaces = (CellWidth - (ThisWidth + NetWidth));
1382 Changes[CellIter->Index].Spaces += (i > 0) ? 1 : BracePadding;
1384 alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1385 for (
const auto *Next = CellIter->NextColumnElement; Next;
1386 Next = Next->NextColumnElement) {
1388 calculateCellWidth(Next->Index, Next->EndIndex,
true) + NetWidth;
1389 if (Changes[Next->Index].NewlinesBefore == 0) {
1390 Changes[Next->Index].Spaces = (CellWidth - ThisWidth);
1391 Changes[Next->Index].Spaces += (i > 0) ? 1 : BracePadding;
1393 alignToStartOfCell(Next->Index, Next->EndIndex);
1399void WhitespaceManager::alignArrayInitializersLeftJustified(
1400 CellDescriptions &&CellDescs) {
1402 if (!CellDescs.isRectangular())
1405 const int BracePadding = Style.Cpp11BracedListStyle ? 0 : 1;
1406 auto &Cells = CellDescs.Cells;
1408 auto *CellIter = Cells.begin();
1410 for (
const auto *Next = CellIter; Next; Next = Next->NextColumnElement) {
1411 auto &Change = Changes[Next->Index];
1413 Change.NewlinesBefore == 0 ? BracePadding : CellDescs.InitialSpaces;
1416 for (
auto i = 1U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {
1417 auto MaxNetWidth = getMaximumNetWidth(
1418 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1419 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1421 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1422 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1423 Changes[CellIter->Index].Spaces =
1424 MaxNetWidth - ThisNetWidth +
1425 (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1
1429 auto Offset = std::distance(Cells.begin(), CellIter);
1430 for (
const auto *Next = CellIter->NextColumnElement; Next;
1431 Next = Next->NextColumnElement) {
1432 if (RowCount >= CellDescs.CellCounts.size())
1434 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1435 auto *End = Start + Offset;
1436 auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1437 if (Changes[Next->Index].NewlinesBefore == 0) {
1438 Changes[Next->Index].Spaces =
1439 MaxNetWidth - ThisNetWidth +
1440 (Changes[Next->Index].Tok->isNot(tok::r_brace) ? 1 : BracePadding);
1447bool WhitespaceManager::isSplitCell(
const CellDescription &Cell) {
1450 for (
const auto *Next = Cell.NextColumnElement; Next;
1451 Next = Next->NextColumnElement) {
1458WhitespaceManager::CellDescriptions WhitespaceManager::getCells(
unsigned Start,
1463 SmallVector<unsigned> CellCounts;
1464 unsigned InitialSpaces = 0;
1465 unsigned InitialTokenLength = 0;
1466 unsigned EndSpaces = 0;
1467 SmallVector<CellDescription> Cells;
1468 const FormatToken *MatchingParen =
nullptr;
1469 for (
unsigned i = Start; i < End; ++i) {
1470 auto &
C = Changes[i];
1471 if (
C.Tok->is(tok::l_brace))
1473 else if (
C.Tok->is(tok::r_brace))
1476 if (
C.Tok->is(tok::l_brace)) {
1478 MatchingParen =
C.Tok->MatchingParen;
1479 if (InitialSpaces == 0) {
1480 InitialSpaces =
C.Spaces +
C.TokenLength;
1481 InitialTokenLength =
C.TokenLength;
1483 for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
1484 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1485 InitialTokenLength += Changes[j].TokenLength;
1487 if (
C.NewlinesBefore == 0) {
1488 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1489 InitialTokenLength += Changes[j].TokenLength;
1492 }
else if (
C.Tok->is(tok::comma)) {
1494 Cells.back().EndIndex = i;
1495 if (
const auto *Next =
C.Tok->getNextNonComment();
1496 Next && Next->isNot(tok::r_brace)) {
1500 }
else if (Depth == 1) {
1501 if (
C.Tok == MatchingParen) {
1503 Cells.back().EndIndex = i;
1504 Cells.push_back(CellDescription{i, ++Cell, i + 1,
false,
nullptr});
1505 CellCounts.push_back(
C.Tok->Previous->isNot(tok::comma) ? Cell + 1
1508 const auto *NextNonComment =
C.Tok->getNextNonComment();
1509 while (NextNonComment && NextNonComment->is(tok::comma))
1510 NextNonComment = NextNonComment->getNextNonComment();
1512 while (j < End && Changes[j].Tok != NextNonComment)
1514 if (j < End && Changes[j].NewlinesBefore == 0 &&
1515 Changes[j].Tok->isNot(tok::r_brace)) {
1516 Changes[j].NewlinesBefore = 1;
1518 Changes[j].Spaces = InitialSpaces - InitialTokenLength;
1520 }
else if (
C.Tok->is(tok::comment) &&
C.Tok->NewlinesBefore == 0) {
1522 C.Spaces = Changes[i - 1].Tok->is(tok::comma) ? 1 : 2;
1523 }
else if (
C.Tok->is(tok::l_brace)) {
1527 for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
1529 EndSpaces = Changes[j].Spaces;
1531 }
else if (Depth == 0 &&
C.Tok->is(tok::r_brace)) {
1532 C.NewlinesBefore = 1;
1533 C.Spaces = EndSpaces;
1535 if (
C.Tok->StartsColumn) {
1538 bool HasSplit =
false;
1539 if (Changes[i].NewlinesBefore > 0) {
1555 if ((j - 1) > Start && Changes[j].Tok->is(tok::comma) &&
1556 Changes[j - 1].NewlinesBefore > 0) {
1558 auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1559 if (LineLimit < Style.ColumnLimit) {
1560 Changes[i].NewlinesBefore = 0;
1561 Changes[i].Spaces = 1;
1565 while (Changes[i].NewlinesBefore > 0 && Changes[i].Tok ==
C.Tok) {
1566 Changes[i].Spaces = InitialSpaces;
1570 if (Changes[i].Tok !=
C.Tok)
1572 Cells.push_back(CellDescription{i, Cell, i, HasSplit,
nullptr});
1576 return linkCells({Cells, CellCounts, InitialSpaces});
1579unsigned WhitespaceManager::calculateCellWidth(
unsigned Start,
unsigned End,
1580 bool WithSpaces)
const {
1581 unsigned CellWidth = 0;
1582 for (
auto i = Start; i < End; i++) {
1583 if (Changes[i].NewlinesBefore > 0)
1585 CellWidth += Changes[i].TokenLength;
1586 CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
1591void WhitespaceManager::alignToStartOfCell(
unsigned Start,
unsigned End) {
1592 if ((End - Start) <= 1)
1596 for (
auto i = Start + 1; i < End; i++)
1597 if (Changes[i].NewlinesBefore > 0)
1598 Changes[i].Spaces = Changes[Start].Spaces;
1601WhitespaceManager::CellDescriptions
1602WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1603 auto &Cells = CellDesc.Cells;
1604 for (
auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
1605 if (!CellIter->NextColumnElement && (CellIter + 1) != Cells.end()) {
1606 for (
auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
1607 if (NextIter->Cell == CellIter->Cell) {
1608 CellIter->NextColumnElement = &(*NextIter);
1614 return std::move(CellDesc);
1617void WhitespaceManager::generateChanges() {
1618 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
1619 const Change &
C = Changes[i];
1621 auto Last = Changes[i - 1].OriginalWhitespaceRange;
1622 auto New = Changes[i].OriginalWhitespaceRange;
1664 if (
Last.getBegin() == New.getBegin() &&
1665 (
Last.getEnd() !=
Last.getBegin() ||
1666 New.getEnd() == New.getBegin())) {
1670 if (
C.CreateReplacement) {
1671 std::string ReplacementText =
C.PreviousLinePostfix;
1672 if (
C.ContinuesPPDirective) {
1673 appendEscapedNewlineText(ReplacementText,
C.NewlinesBefore,
1674 C.PreviousEndOfTokenColumn,
1675 C.EscapedNewlineColumn);
1677 appendNewlineText(ReplacementText,
C);
1682 ReplacementText,
C.Tok->IndentLevel, std::max(0,
C.Spaces),
1683 std::max((
int)
C.StartOfTokenColumn,
C.Spaces) - std::max(0,
C.Spaces),
1685 ReplacementText.append(
C.CurrentLinePrefix);
1686 storeReplacement(
C.OriginalWhitespaceRange, ReplacementText);
1691void WhitespaceManager::storeReplacement(SourceRange
Range, StringRef
Text) {
1696 WhitespaceLength) ==
Text) {
1699 auto Err = Replaces.
add(tooling::Replacement(
1704 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
1709void WhitespaceManager::appendNewlineText(std::string &
Text,
const Change &
C) {
1710 if (
C.NewlinesBefore <= 0)
1713 StringRef Newline = UseCRLF ?
"\r\n" :
"\n";
1714 Text.append(Newline);
1716 if (
C.Tok->HasFormFeedBefore)
1719 for (
unsigned I = 1; I <
C.NewlinesBefore; ++I)
1720 Text.append(Newline);
1723void WhitespaceManager::appendEscapedNewlineText(
1724 std::string &
Text,
unsigned Newlines,
unsigned PreviousEndOfTokenColumn,
1725 unsigned EscapedNewlineColumn) {
1728 std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
1729 for (
unsigned i = 0; i < Newlines; ++i) {
1730 Text.append(Spaces,
' ');
1731 Text.append(UseCRLF ?
"\\\r\n" :
"\\\n");
1732 Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
1737void WhitespaceManager::appendIndentText(std::string &
Text,
1738 unsigned IndentLevel,
unsigned Spaces,
1739 unsigned WhitespaceStartColumn,
1741 switch (Style.UseTab) {
1743 Text.append(Spaces,
' ');
1746 if (Style.TabWidth) {
1747 unsigned FirstTabWidth =
1748 Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
1751 if (Spaces < FirstTabWidth || Spaces == 1) {
1752 Text.append(Spaces,
' ');
1756 Spaces -= FirstTabWidth;
1759 Text.append(Spaces / Style.TabWidth,
'\t');
1760 Text.append(Spaces % Style.TabWidth,
' ');
1761 }
else if (Spaces == 1) {
1762 Text.append(Spaces,
' ');
1767 if (WhitespaceStartColumn == 0) {
1768 unsigned Indentation = IndentLevel * Style.IndentWidth;
1769 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1771 Text.append(Spaces,
' ');
1774 if (WhitespaceStartColumn == 0)
1775 Spaces = appendTabIndent(
Text, Spaces, Spaces);
1776 Text.append(Spaces,
' ');
1779 if (WhitespaceStartColumn == 0) {
1780 unsigned Indentation =
1781 IsAligned ? IndentLevel * Style.IndentWidth : Spaces;
1782 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1784 Text.append(Spaces,
' ');
1789unsigned WhitespaceManager::appendTabIndent(std::string &
Text,
unsigned Spaces,
1790 unsigned Indentation) {
1793 if (Indentation > Spaces)
1794 Indentation = Spaces;
1795 if (Style.TabWidth) {
1796 unsigned Tabs = Indentation / Style.TabWidth;
1797 Text.append(Tabs,
'\t');
1798 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())