15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallVector.h"
26 return SourceMgr.isBeforeInTranslationUnit(
31 SourceMgr.isBeforeInTranslationUnit(
59 unsigned StartOfTokenColumn,
60 bool IsAligned,
bool InPPDirective,
61 unsigned IndentedFromColumn) {
66 Spaces, StartOfTokenColumn, IndentedFromColumn,
68 InPPDirective && !
Tok.IsFirst,
77 Tok,
false,
Tok.WhitespaceRange, 0,
78 Tok.OriginalColumn, 0,
Tok.NewlinesBefore,
"",
"",
79 false, InPPDirective && !
Tok.IsFirst,
85 return Replaces.add(Replacement);
89 size_t LF =
Text.count(
'\n');
90 size_t CR =
Text.count(
'\r') * 2;
91 return LF == CR ? DefaultToCRLF : CR > LF;
96 StringRef PreviousPostfix, StringRef CurrentPrefix,
bool InPPDirective,
105 PreviousPostfix, CurrentPrefix,
106 true, InPPDirective && !
Tok.IsFirst,
115 calculateLineBreakInformation();
116 alignConsecutiveMacros();
117 alignConsecutiveShortCaseStatements(
true);
118 alignConsecutiveShortCaseStatements(
false);
119 alignConsecutiveDeclarations();
120 alignConsecutiveBitFields();
121 alignConsecutiveAssignments();
122 if (Style.isTableGen()) {
123 alignConsecutiveTableGenBreakingDAGArgColons();
124 alignConsecutiveTableGenCondOperatorColons();
125 alignConsecutiveTableGenDefinitions();
127 alignChainedConditionals();
128 alignTrailingComments();
129 alignEscapedNewlines();
130 alignArrayInitializers();
136void WhitespaceManager::calculateLineBreakInformation() {
137 Changes[0].PreviousEndOfTokenColumn = 0;
138 Change *LastOutsideTokenChange = &Changes[0];
139 for (
unsigned I = 1, e = Changes.size(); I != e; ++I) {
140 auto &
C = Changes[I];
141 auto &P = Changes[I - 1];
142 auto &PrevTokLength = P.TokenLength;
144 C.OriginalWhitespaceRange.getBegin();
146 P.OriginalWhitespaceRange.getEnd();
147 unsigned OriginalWhitespaceStartOffset =
148 SourceMgr.getFileOffset(OriginalWhitespaceStart);
149 unsigned PreviousOriginalWhitespaceEndOffset =
150 SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd);
151 assert(PreviousOriginalWhitespaceEndOffset <=
152 OriginalWhitespaceStartOffset);
153 const char *
const PreviousOriginalWhitespaceEndData =
154 SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd);
155 StringRef
Text(PreviousOriginalWhitespaceEndData,
156 SourceMgr.getCharacterData(OriginalWhitespaceStart) -
157 PreviousOriginalWhitespaceEndData);
179 auto NewlinePos =
Text.find_first_of(
'\n');
180 if (NewlinePos == StringRef::npos) {
181 PrevTokLength = OriginalWhitespaceStartOffset -
182 PreviousOriginalWhitespaceEndOffset +
183 C.PreviousLinePostfix.size() + P.CurrentLinePrefix.size();
184 if (!P.IsInsideToken)
185 PrevTokLength = std::min(PrevTokLength, P.Tok->ColumnWidth);
187 PrevTokLength = NewlinePos + P.CurrentLinePrefix.size();
192 if (P.IsInsideToken && P.NewlinesBefore == 0)
193 LastOutsideTokenChange->TokenLength += PrevTokLength + P.Spaces;
195 LastOutsideTokenChange = &P;
197 C.PreviousEndOfTokenColumn = P.StartOfTokenColumn + PrevTokLength;
199 P.IsTrailingComment =
200 (
C.NewlinesBefore > 0 ||
C.Tok->is(tok::eof) ||
201 (
C.IsInsideToken &&
C.Tok->is(tok::comment))) &&
202 P.Tok->is(tok::comment) &&
233 OriginalWhitespaceStart != PreviousOriginalWhitespaceEnd;
237 Changes.back().TokenLength = 0;
238 Changes.back().IsTrailingComment = Changes.back().Tok->is(tok::comment);
240 const WhitespaceManager::Change *LastBlockComment =
nullptr;
241 for (
auto &
Change : Changes) {
251 LastBlockComment = &
Change;
258 LastBlockComment =
nullptr;
266 SmallVector<bool, 16> ScopeStack;
267 int ConditionalsLevel = 0;
268 for (
auto &
Change : Changes) {
270 bool isNestedConditional =
275 if (isNestedConditional)
277 ScopeStack.push_back(isNestedConditional);
283 if (ScopeStack.pop_back_val())
294 auto &FirstChange = Changes[Start];
295 const int ColumnChange = Spaces - FirstChange.Spaces;
297 if (ColumnChange == 0)
300 FirstChange.Spaces += ColumnChange;
301 FirstChange.StartOfTokenColumn += ColumnChange;
303 for (
auto I = Start + 1; I < Changes.size(); I++) {
304 auto &Change = Changes[I];
306 Change.PreviousEndOfTokenColumn += ColumnChange;
308 if (Change.NewlinesBefore > 0)
311 Change.StartOfTokenColumn += ColumnChange;
321 assert(Delta > 0 || (
abs(Delta) <= Changes[Start].Spaces));
331 unsigned Column,
bool RightJustify,
334 unsigned OriginalMatchColumn = 0;
362 for (
unsigned i = Start; i != End; ++i) {
363 auto &CurrentChange = Changes[i];
364 if (!Matches.empty() && Matches[0] < i)
365 Matches.consume_front();
366 assert(Matches.empty() || Matches[0] >= i);
367 while (!ScopeStack.empty() &&
368 CurrentChange.indentAndNestingLevel() < ScopeStack.back()) {
369 ScopeStack.pop_back();
373 if (ScopeStack.size() == 1u && CurrentChange.NewlinesBefore != 0u &&
374 CurrentChange.indentAndNestingLevel() > ScopeStack[0] &&
375 CurrentChange.IndentedFromColumn < OriginalMatchColumn) {
376 ScopeStack.push_back(CurrentChange.indentAndNestingLevel());
379 bool InsideNestedScope =
380 !ScopeStack.empty() &&
381 (CurrentChange.indentAndNestingLevel() > ScopeStack[0] ||
382 (CurrentChange.indentAndNestingLevel() == ScopeStack[0] &&
383 CurrentChange.IndentedFromColumn >= OriginalMatchColumn));
385 if (CurrentChange.NewlinesBefore > 0 && !InsideNestedScope)
391 if (!Matches.empty() && Matches[0] == i) {
392 OriginalMatchColumn = CurrentChange.StartOfTokenColumn;
393 Shift =
Column - (RightJustify ? CurrentChange.TokenLength : 0) -
394 CurrentChange.StartOfTokenColumn;
395 ScopeStack = {CurrentChange.indentAndNestingLevel()};
404 if ((!Matches.empty() && Matches[0] == i) ||
405 (ScopeStack.size() == 1u && CurrentChange.NewlinesBefore > 0 &&
406 InsideNestedScope)) {
407 CurrentChange.IndentedFromColumn += Shift;
413 CurrentChange.Spaces >=
414 static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
415 CurrentChange.Tok->is(tok::eof));
419 if ((Style.PointerAlignment == FormatStyle::PAS_Right ||
420 Style.ReferenceAlignment == FormatStyle::RAS_Right) &&
421 CurrentChange.Spaces != 0 &&
422 CurrentChange.Tok->isNoneOf(tok::equal, tok::r_paren,
423 TT_TemplateCloser)) {
424 const bool ReferenceNotRightAligned =
425 Style.ReferenceAlignment != FormatStyle::RAS_Right &&
426 Style.ReferenceAlignment != FormatStyle::RAS_Pointer;
430 assert(Changes[
Previous].
Tok->isPointerOrReference());
432 if (ReferenceNotRightAligned)
434 }
else if (Style.PointerAlignment != FormatStyle::PAS_Right) {
446enum class AlignStrategy {
Normal,
Macro, CaseBody, CaseColon };
489template <
typename F, AlignStrategy Strategy = AlignStrategy::Normal>
493 const FormatStyle::AlignConsecutiveStyle &ACS = {},
494 bool RightJustify =
false) {
505 unsigned WidthLeft = 0;
508 unsigned WidthAnchor = 0;
511 unsigned WidthRight = 0;
514 unsigned StartOfSequence = 0;
515 unsigned EndOfSequence = 0;
522 const auto IndentAndNestingLevel =
523 StartAt < Changes.size() ? Changes[StartAt].indentAndNestingLevel()
524 : std::tuple<unsigned, unsigned, unsigned>();
529 unsigned CommasBeforeLastMatch = 0;
530 unsigned CommasBeforeMatch = 0;
533 std::optional<unsigned> MatchingColumn;
536 bool LineIsComment =
true;
545 auto AlignCurrentSequence = [&] {
546 if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
548 WidthLeft + WidthAnchor, RightJustify, MatchedIndices,
556 MatchedIndices.clear();
559 unsigned I = StartAt;
560 const auto E = Changes.size();
561 for (
const auto LoopEnd = Strategy == AlignStrategy::CaseBody ? E - 1 : E;
563 auto &CurrentChange = Changes[I];
564 if (CurrentChange.indentAndNestingLevel() < IndentAndNestingLevel)
567 if (CurrentChange.NewlinesBefore != 0) {
568 CommasBeforeMatch = 0;
572 bool EmptyLineBreak =
573 (CurrentChange.NewlinesBefore > 1) && !ACS.AcrossEmptyLines;
578 !MatchingColumn && !(LineIsComment && ACS.AcrossComments);
580 if (EmptyLineBreak || NoMatchBreak)
581 AlignCurrentSequence();
585 if (MatchingColumn && CurrentChange.IndentedFromColumn < *MatchingColumn)
586 MatchingColumn.reset();
587 LineIsComment =
true;
590 if (CurrentChange.Tok->isNot(tok::comment))
591 LineIsComment =
false;
593 if constexpr (Strategy == AlignStrategy::Normal) {
594 if (CurrentChange.Tok->is(tok::comma)) {
596 }
else if (CurrentChange.indentAndNestingLevel() >
597 IndentAndNestingLevel) {
600 Style, Matches, Changes, I, ACS, RightJustify);
606 if (!Matches(CurrentChange))
609 const auto IndexToAlign = Strategy == AlignStrategy::CaseBody ? I + 1 : I;
610 const auto &ChangeToAlign = Changes[IndexToAlign];
611 const auto [AlignTheToken,
612 ShiftAlignment] = [&]() -> std::pair<bool, bool> {
614 case AlignStrategy::CaseBody: {
615 if (ChangeToAlign.NewlinesBefore == 0)
616 return {
true,
false};
617 const auto *
Tok = ChangeToAlign.Tok;
618 if (
Tok->is(tok::comment) && ACS.AcrossComments)
619 Tok =
Tok->getNextNonComment();
620 return {
false,
Tok &&
Tok->isOneOf(tok::kw_case, tok::kw_default)};
622 case AlignStrategy::CaseColon: {
623 if (I + 1 == LoopEnd)
624 return {
true,
false};
625 const auto &NextChange = Changes[I + 1];
626 if (NextChange.NewlinesBefore == 0 ||
627 (CurrentChange.Tok->Next &&
628 CurrentChange.Tok->Next->isTrailingComment())) {
629 return {
true,
false};
631 const auto *
Tok = NextChange.Tok;
632 if (
Tok->is(tok::comment) && ACS.AcrossComments)
633 Tok =
Tok->getNextNonComment();
634 return {
Tok &&
Tok->isOneOf(tok::kw_case, tok::kw_default),
false};
637 return {
true,
false};
641 if (!AlignTheToken && !ShiftAlignment)
646 if ((ChangeToAlign.NewlinesBefore == 0U && MatchingColumn) ||
647 CommasBeforeMatch != CommasBeforeLastMatch) {
648 MatchedIndices.push_back(IndexToAlign);
649 AlignCurrentSequence();
652 CommasBeforeLastMatch = CommasBeforeMatch;
653 MatchingColumn = AlignTheToken ? ChangeToAlign.StartOfTokenColumn
654 : std::numeric_limits<unsigned>::max();
656 if (StartOfSequence == 0 && AlignTheToken)
657 StartOfSequence = IndexToAlign;
659 unsigned ChangeWidthLeft = ChangeToAlign.StartOfTokenColumn;
660 unsigned ChangeWidthAnchor = 0;
661 unsigned ChangeWidthRight = 0;
662 unsigned CurrentChangeWidthRight = 0;
663 if (!AlignTheToken) {
667 ChangeWidthLeft = CurrentChange.StartOfTokenColumn +
668 CurrentChange.TokenLength +
672 if (ACS.PadOperators)
673 ChangeWidthAnchor = ChangeToAlign.TokenLength;
675 ChangeWidthLeft += ChangeToAlign.TokenLength;
677 CurrentChangeWidthRight = ChangeToAlign.TokenLength;
678 const FormatToken *MatchingParenToEncounter =
nullptr;
679 for (
unsigned J = IndexToAlign + 1;
680 J != E && (Changes[J].NewlinesBefore == 0 ||
681 MatchingParenToEncounter || Changes[J].IsAligned);
683 const auto &
Change = Changes[J];
686 if (
Tok->MatchingParen) {
687 if (
Tok->isOneOf(tok::l_paren, tok::l_brace, tok::l_square,
688 TT_TemplateOpener) &&
689 !MatchingParenToEncounter) {
694 MatchingParenToEncounter =
Tok->MatchingParen;
695 }
else if (MatchingParenToEncounter ==
Tok->MatchingParen) {
696 MatchingParenToEncounter =
nullptr;
702 std::max(ChangeWidthRight, CurrentChangeWidthRight);
703 const auto ChangeWidthStart = ChangeWidthLeft + ChangeWidthAnchor;
714 CurrentChangeWidthRight =
Change.
Spaces - ChangeWidthStart;
728 ChangeWidthRight = std::max(ChangeWidthRight, CurrentChangeWidthRight);
732 unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
733 unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
734 unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
736 if (Style.ColumnLimit != 0 &&
737 Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
738 AlignCurrentSequence();
739 StartOfSequence = AlignTheToken ? IndexToAlign : 0;
740 WidthLeft = ChangeWidthLeft;
741 WidthAnchor = ChangeWidthAnchor;
742 WidthRight = ChangeWidthRight;
745 WidthAnchor = NewAnchor;
746 WidthRight = NewRight;
749 MatchedIndices.push_back(IndexToAlign);
754 for (EndOfSequence = I;
755 EndOfSequence < E && Changes[EndOfSequence].NewlinesBefore == 0;
758 AlignCurrentSequence();
764void WhitespaceManager::alignConsecutiveMacros() {
765 if (!Style.AlignConsecutiveMacros.Enabled)
768 auto AlignMacrosMatches = [](
const Change &
C) {
772 if (Current->SpacesRequiredBefore == 0 || !Current->Previous)
775 Current = Current->Previous;
779 if (Current->is(tok::r_paren)) {
788 }
else if (Current->Next->SpacesRequiredBefore != 1) {
794 return Current->endsSequence(tok::identifier, tok::pp_define);
798 Style, AlignMacrosMatches, Changes, 0, Style.AlignConsecutiveMacros);
801void WhitespaceManager::alignConsecutiveAssignments() {
802 if (!Style.AlignConsecutiveAssignments.Enabled)
809 if (
C.NewlinesBefore > 0)
813 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
821 return Style.AlignConsecutiveAssignments.AlignCompound
823 : (
C.Tok->is(tok::equal) ||
827 (Style.isVerilog() &&
C.Tok->is(tok::lessequal) &&
830 Changes, 0, Style.AlignConsecutiveAssignments,
834void WhitespaceManager::alignConsecutiveBitFields() {
835 alignConsecutiveColons(Style.AlignConsecutiveBitFields, TT_BitFieldColon);
838void WhitespaceManager::alignConsecutiveColons(
839 const FormatStyle::AlignConsecutiveStyle &AlignStyle,
TokenType Type) {
840 if (!AlignStyle.Enabled)
847 if (
C.NewlinesBefore > 0)
851 if (&
C != &Changes.back() && (&
C + 1)->NewlinesBefore > 0)
854 return C.Tok->is(
Type);
856 Changes, 0, AlignStyle);
859void WhitespaceManager::alignConsecutiveShortCaseStatements(
bool IsExpr) {
860 if (!Style.AlignConsecutiveShortCaseStatements.Enabled ||
861 !(IsExpr ? Style.AllowShortCaseExpressionOnASingleLine
862 : Style.AllowShortCaseLabelsOnASingleLine)) {
866 const auto Type = IsExpr ? TT_CaseLabelArrow : TT_CaseLabelColon;
867 const auto &Option = Style.AlignConsecutiveShortCaseStatements;
868 const bool AlignArrowOrColon =
869 IsExpr ? Option.AlignCaseArrows : Option.AlignCaseColons;
871 FormatStyle::AlignConsecutiveStyle AlignStyle{};
872 AlignStyle.AcrossComments = Option.AcrossComments;
873 AlignStyle.AcrossEmptyLines = Option.AcrossEmptyLines;
876 if (AlignArrowOrColon) {
878 Style, Matches, Changes, 0, AlignStyle);
881 Style, Matches, Changes, 0, AlignStyle);
885void WhitespaceManager::alignConsecutiveTableGenBreakingDAGArgColons() {
886 alignConsecutiveColons(Style.AlignConsecutiveTableGenBreakingDAGArgColons,
887 TT_TableGenDAGArgListColonToAlign);
890void WhitespaceManager::alignConsecutiveTableGenCondOperatorColons() {
891 alignConsecutiveColons(Style.AlignConsecutiveTableGenCondOperatorColons,
892 TT_TableGenCondOperatorColon);
895void WhitespaceManager::alignConsecutiveTableGenDefinitions() {
896 alignConsecutiveColons(Style.AlignConsecutiveTableGenDefinitionColons,
897 TT_InheritanceColon);
900void WhitespaceManager::alignConsecutiveDeclarations() {
901 if (!Style.AlignConsecutiveDeclarations.Enabled)
907 if (
C.Tok->is(TT_FunctionTypeLParen))
908 return Style.AlignConsecutiveDeclarations.AlignFunctionPointers;
909 if (
C.Tok->is(TT_FunctionDeclarationName))
910 return Style.AlignConsecutiveDeclarations.AlignFunctionDeclarations;
911 if (
C.Tok->isNot(TT_StartOfName))
913 if (
C.Tok->Previous &&
914 C.Tok->Previous->is(TT_StatementAttributeLikeMacro))
918 if (
Next->is(tok::comment))
920 if (
Next->is(TT_PointerOrReference))
922 if (!
Next->Tok.getIdentifierInfo())
924 if (
Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
931 Changes, 0, Style.AlignConsecutiveDeclarations);
934void WhitespaceManager::alignChainedConditionals() {
935 if (Style.BreakBeforeTernaryOperators) {
940 return C.Tok->is(TT_ConditionalExpr) &&
941 ((
C.Tok->is(tok::question) && !
C.NewlinesBefore) ||
942 (
C.Tok->is(tok::colon) &&
C.Tok->Next &&
943 (
C.Tok->Next->FakeLParens.empty() ||
948 static auto AlignWrappedOperand = [](
Change const &
C) {
952 (
C.Tok->FakeLParens.empty() ||
959 if (AlignWrappedOperand(
C))
960 C.StartOfTokenColumn -= 2;
967 return (
C.Tok->is(TT_ConditionalExpr) &&
C.Tok->is(tok::question) &&
968 &
C != &Changes.back() && (&
C + 1)->NewlinesBefore == 0 &&
969 !(&
C + 1)->IsTrailingComment) ||
970 AlignWrappedOperand(
C);
976void WhitespaceManager::alignTrailingComments() {
977 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Never)
980 const int Size = Changes.size();
985 int StartOfSequence = 0;
986 bool BreakBeforeNext =
false;
987 bool IsInPP = Changes.front().Tok->Tok.is(tok::hash);
988 int NewLineThreshold = 1;
989 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Always)
990 NewLineThreshold = Style.AlignTrailingComments.OverEmptyLines + 1;
993 auto &
C = Changes[I];
994 if (
C.StartOfBlockComment)
996 if (
C.NewlinesBefore != 0) {
998 const bool WasInPP = std::exchange(
999 IsInPP,
C.Tok->Tok.is(tok::hash) || (IsInPP &&
C.IsTrailingComment) ||
1000 C.ContinuesPPDirective);
1001 if (IsInPP != WasInPP && !Style.AlignTrailingComments.AlignPPAndNotPP) {
1002 alignTrailingComments(StartOfSequence, I, MinColumn);
1005 StartOfSequence = I;
1009 if (!
C.IsTrailingComment)
1012 if (Style.AlignTrailingComments.Kind == FormatStyle::TCAS_Leave) {
1013 const int OriginalSpaces =
1014 C.OriginalWhitespaceRange.getEnd().getRawEncoding() -
1015 C.OriginalWhitespaceRange.getBegin().getRawEncoding() -
1016 C.Tok->LastNewlineOffset;
1017 assert(OriginalSpaces >= 0);
1018 const auto RestoredLineLength =
1019 C.StartOfTokenColumn +
C.TokenLength + OriginalSpaces;
1022 if (RestoredLineLength >= Style.ColumnLimit && Style.ColumnLimit > 0)
1026 C.NewlinesBefore > 0 ?
C.Tok->OriginalColumn : OriginalSpaces;
1027 setChangeSpaces(I, Spaces);
1031 const int ChangeMinColumn =
C.StartOfTokenColumn;
1032 int ChangeMaxColumn;
1036 if (!
C.CreateReplacement)
1037 ChangeMaxColumn = ChangeMinColumn;
1038 else if (Style.ColumnLimit == 0)
1040 else if (Style.ColumnLimit >=
C.TokenLength)
1041 ChangeMaxColumn = Style.ColumnLimit -
C.TokenLength;
1043 ChangeMaxColumn = ChangeMinColumn;
1045 if (I + 1 < Size && Changes[I + 1].ContinuesPPDirective &&
1046 ChangeMaxColumn >= 2) {
1047 ChangeMaxColumn -= 2;
1050 bool WasAlignedWithStartOfNextLine =
false;
1051 if (
C.NewlinesBefore >= 1) {
1052 const auto CommentColumn =
1053 SourceMgr.getSpellingColumnNumber(
C.OriginalWhitespaceRange.getEnd());
1054 for (
int J = I + 1; J <
Size; ++J) {
1055 if (Changes[J].
Tok->is(tok::comment))
1058 const auto NextColumn = SourceMgr.getSpellingColumnNumber(
1059 Changes[J].OriginalWhitespaceRange.getEnd());
1062 WasAlignedWithStartOfNextLine =
1063 CommentColumn == NextColumn ||
1064 CommentColumn == NextColumn + Style.IndentWidth;
1071 auto DontAlignThisComment = [](
const auto *
Tok) {
1072 if (
Tok->is(tok::semi)) {
1073 Tok =
Tok->getPreviousNonComment();
1077 if (
Tok->is(tok::r_paren)) {
1079 Tok =
Tok->MatchingParen;
1082 Tok =
Tok->getPreviousNonComment();
1085 if (
Tok->is(TT_DoWhile)) {
1086 const auto *Prev =
Tok->getPreviousNonComment();
1095 if (
Tok->isNot(tok::r_brace))
1098 while (
Tok->Previous &&
Tok->Previous->is(tok::r_brace))
1100 return Tok->NewlinesBefore > 0;
1103 if (I > 0 &&
C.NewlinesBefore == 0 &&
1104 DontAlignThisComment(Changes[I - 1].
Tok)) {
1105 alignTrailingComments(StartOfSequence, I, MinColumn);
1110 StartOfSequence = I + 1;
1111 }
else if (BreakBeforeNext ||
Newlines > NewLineThreshold ||
1112 (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) ||
1115 (
C.NewlinesBefore == 1 && I > 0 &&
1116 !Changes[I - 1].IsTrailingComment) ||
1117 WasAlignedWithStartOfNextLine) {
1118 alignTrailingComments(StartOfSequence, I, MinColumn);
1119 MinColumn = ChangeMinColumn;
1120 MaxColumn = ChangeMaxColumn;
1121 StartOfSequence = I;
1123 MinColumn = std::max(MinColumn, ChangeMinColumn);
1124 MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
1126 BreakBeforeNext = (I == 0) || (
C.NewlinesBefore > 1) ||
1129 (
C.NewlinesBefore == 1 && StartOfSequence == I);
1132 alignTrailingComments(StartOfSequence, Size, MinColumn);
1135void WhitespaceManager::alignTrailingComments(
unsigned Start,
unsigned End,
1137 for (
unsigned i = Start; i != End; ++i) {
1139 if (Changes[i].IsTrailingComment)
1141 if (Changes[i].StartOfBlockComment) {
1142 Shift = Changes[i].IndentationOffset +
1143 Changes[i].StartOfBlockComment->StartOfTokenColumn -
1144 Changes[i].StartOfTokenColumn;
1149 setChangeSpaces(i, Changes[i].Spaces + Shift);
1153void WhitespaceManager::alignEscapedNewlines() {
1154 const auto Align = Style.AlignEscapedNewlines;
1155 if (Align == FormatStyle::ENAS_DontAlign)
1158 const bool WithLastLine = Align == FormatStyle::ENAS_LeftWithLastLine;
1159 const bool AlignLeft = Align == FormatStyle::ENAS_Left || WithLastLine;
1160 const auto MaxColumn = Style.ColumnLimit;
1161 unsigned MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1162 unsigned StartOfMacro = 0;
1163 for (
unsigned i = 1, e = Changes.size(); i < e; ++i) {
1165 if (
C.NewlinesBefore == 0 && (!WithLastLine ||
C.Tok->isNot(tok::eof)))
1168 const auto BackslashColumn =
C.PreviousEndOfTokenColumn + 2;
1169 if (InPPDirective ||
1170 (WithLastLine && (MaxColumn == 0 || BackslashColumn <= MaxColumn))) {
1171 MaxEndOfLine = std::max(BackslashColumn, MaxEndOfLine);
1173 if (!InPPDirective) {
1174 alignEscapedNewlines(StartOfMacro + 1, i, MaxEndOfLine);
1175 MaxEndOfLine = AlignLeft ? 0 : MaxColumn;
1179 alignEscapedNewlines(StartOfMacro + 1, Changes.size(), MaxEndOfLine);
1182void WhitespaceManager::alignEscapedNewlines(
unsigned Start,
unsigned End,
1184 for (
unsigned i = Start; i < End; ++i) {
1186 if (
C.NewlinesBefore > 0) {
1187 assert(
C.ContinuesPPDirective);
1188 if (
C.PreviousEndOfTokenColumn + 1 >
Column)
1189 C.EscapedNewlineColumn = 0;
1191 C.EscapedNewlineColumn =
Column;
1196void WhitespaceManager::alignArrayInitializers() {
1197 if (Style.AlignArrayOfStructures == FormatStyle::AIAS_None)
1200 for (
unsigned ChangeIndex = 1U, ChangeEnd = Changes.size();
1201 ChangeIndex < ChangeEnd; ++ChangeIndex) {
1202 auto &
C = Changes[ChangeIndex];
1203 if (
C.Tok->IsArrayInitializer) {
1204 bool FoundComplete =
false;
1205 for (
unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
1207 const auto *
Tok = Changes[InsideIndex].Tok;
1208 if (
Tok->is(tok::pp_define))
1210 if (
Tok ==
C.Tok->MatchingParen) {
1211 alignArrayInitializers(ChangeIndex, InsideIndex + 1);
1212 ChangeIndex = InsideIndex + 1;
1213 FoundComplete =
true;
1218 ChangeIndex = ChangeEnd;
1223void WhitespaceManager::alignArrayInitializers(
unsigned Start,
unsigned End) {
1225 if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Right)
1226 alignArrayInitializersRightJustified(getCells(Start, End));
1227 else if (Style.AlignArrayOfStructures == FormatStyle::AIAS_Left)
1228 alignArrayInitializersLeftJustified(getCells(Start, End));
1231void WhitespaceManager::alignArrayInitializersRightJustified(
1232 CellDescriptions &&CellDescs) {
1233 if (!CellDescs.isRectangular())
1236 const int BracePadding =
1237 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? 0 : 1;
1238 auto &Cells = CellDescs.Cells;
1240 auto *CellIter = Cells.begin();
1241 for (
auto i = 0U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {
1242 unsigned NetWidth = 0U;
1243 if (isSplitCell(*CellIter))
1244 NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1245 auto CellWidth = getMaximumCellWidth(CellIter, NetWidth);
1247 if (Changes[CellIter->Index].Tok->is(tok::r_brace)) {
1251 const auto *
Next = CellIter;
1255 Changes[
Next->Index].NewlinesBefore = 0;
1256 setChangeSpaces(
Next->Index, BracePadding);
1262 if (CellIter != Cells.begin()) {
1264 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1265 auto MaxNetWidth = getMaximumNetWidth(
1266 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1267 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1268 if (ThisNetWidth < MaxNetWidth)
1269 setChangeSpaces(CellIter->Index, MaxNetWidth - ThisNetWidth);
1271 auto Offset = std::distance(Cells.begin(), CellIter);
1272 for (
const auto *
Next = CellIter->NextColumnElement;
Next;
1274 if (RowCount >= CellDescs.CellCounts.size())
1276 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1277 auto *End = Start + Offset;
1278 ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1279 if (ThisNetWidth < MaxNetWidth)
1280 setChangeSpaces(
Next->Index, MaxNetWidth - ThisNetWidth);
1286 calculateCellWidth(CellIter->Index, CellIter->EndIndex,
true) +
1288 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1289 int Spaces = (CellWidth - (ThisWidth + NetWidth));
1290 Spaces += (i > 0) ? 1 : BracePadding;
1292 setChangeSpaces(CellIter->Index, Spaces);
1294 alignToStartOfCell(CellIter->Index, CellIter->EndIndex);
1295 for (
const auto *
Next = CellIter->NextColumnElement;
Next;
1298 calculateCellWidth(
Next->Index,
Next->EndIndex,
true) + NetWidth;
1299 if (Changes[
Next->Index].NewlinesBefore == 0) {
1300 int Spaces = (CellWidth - ThisWidth);
1301 Spaces += (i > 0) ? 1 : BracePadding;
1303 setChangeSpaces(
Next->Index, Spaces);
1305 alignToStartOfCell(
Next->Index,
Next->EndIndex);
1311void WhitespaceManager::alignArrayInitializersLeftJustified(
1312 CellDescriptions &&CellDescs) {
1314 if (!CellDescs.isRectangular())
1317 const int BracePadding =
1318 Style.Cpp11BracedListStyle != FormatStyle::BLS_Block ? 0 : 1;
1319 auto &Cells = CellDescs.Cells;
1321 auto *CellIter = Cells.begin();
1327 setChangeSpaces(
Next->Index, Spaces);
1330 for (
auto i = 1U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {
1331 auto MaxNetWidth = getMaximumNetWidth(
1332 Cells.begin(), CellIter, CellDescs.InitialSpaces,
1333 CellDescs.CellCounts[0], CellDescs.CellCounts.size());
1335 getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
1336 if (Changes[CellIter->Index].NewlinesBefore == 0) {
1338 MaxNetWidth - ThisNetWidth +
1339 (Changes[CellIter->Index].Tok->isNot(tok::r_brace) ? 1
1341 setChangeSpaces(CellIter->Index, Spaces);
1344 auto Offset = std::distance(Cells.begin(), CellIter);
1345 for (
const auto *
Next = CellIter->NextColumnElement;
Next;
1347 if (RowCount >= CellDescs.CellCounts.size())
1349 auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
1350 auto *End = Start + Offset;
1351 auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
1352 if (Changes[
Next->Index].NewlinesBefore == 0) {
1354 MaxNetWidth - ThisNetWidth +
1355 (Changes[
Next->Index].Tok->isNot(tok::r_brace) ? 1 : BracePadding);
1356 setChangeSpaces(
Next->Index, Spaces);
1363bool WhitespaceManager::isSplitCell(
const CellDescription &Cell) {
1366 for (
const auto *
Next = Cell.NextColumnElement;
Next;
1374WhitespaceManager::CellDescriptions WhitespaceManager::getCells(
unsigned Start,
1379 SmallVector<unsigned> CellCounts;
1380 unsigned InitialSpaces = 0;
1381 unsigned InitialTokenLength = 0;
1382 unsigned EndSpaces = 0;
1383 SmallVector<CellDescription> Cells;
1385 for (
unsigned i = Start; i < End; ++i) {
1386 auto &
C = Changes[i];
1387 if (
C.Tok->is(tok::l_brace))
1389 else if (
C.Tok->is(tok::r_brace))
1392 if (
C.Tok->is(tok::l_brace)) {
1395 if (InitialSpaces == 0) {
1396 InitialSpaces =
C.Spaces +
C.TokenLength;
1397 InitialTokenLength =
C.TokenLength;
1399 for (; Changes[j].NewlinesBefore == 0 && j > Start; --j) {
1400 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1401 InitialTokenLength += Changes[j].TokenLength;
1403 if (
C.NewlinesBefore == 0) {
1404 InitialSpaces += Changes[j].Spaces + Changes[j].TokenLength;
1405 InitialTokenLength += Changes[j].TokenLength;
1408 }
else if (
C.Tok->is(tok::comma)) {
1410 Cells.back().EndIndex = i;
1411 if (
const auto *
Next =
C.Tok->getNextNonComment();
1412 Next &&
Next->isNot(tok::r_brace)) {
1416 }
else if (Depth == 1) {
1419 Cells.back().EndIndex = i;
1420 Cells.push_back(CellDescription{i, ++Cell, i + 1,
false,
nullptr});
1421 CellCounts.push_back(
C.Tok->Previous->isNot(tok::comma) ? Cell + 1
1424 const auto *NextNonComment =
C.Tok->getNextNonComment();
1425 while (NextNonComment && NextNonComment->is(tok::comma))
1426 NextNonComment = NextNonComment->getNextNonComment();
1428 while (j < End && Changes[j].
Tok != NextNonComment)
1431 Changes[j].
Tok->isNot(tok::r_brace)) {
1432 Changes[j].NewlinesBefore = 1;
1434 setChangeSpaces(j, InitialSpaces - InitialTokenLength);
1436 }
else if (
C.Tok->is(tok::comment) &&
C.Tok->NewlinesBefore == 0) {
1438 setChangeSpaces(i, Changes[i - 1].
Tok->is(tok::comma) ? 1 : 2);
1439 }
else if (
C.Tok->is(tok::l_brace)) {
1443 for (; j > 0 && !Changes[j].Tok->ArrayInitializerLineStart; --j)
1445 EndSpaces = Changes[j].Spaces;
1447 }
else if (Depth == 0 &&
C.Tok->is(tok::r_brace)) {
1448 C.NewlinesBefore = 1;
1449 setChangeSpaces(i, EndSpaces);
1451 if (
C.Tok->StartsColumn) {
1454 bool HasSplit =
false;
1471 if ((j - 1) > Start && Changes[j].
Tok->is(tok::comma) &&
1472 Changes[j - 1].NewlinesBefore > 0) {
1474 auto LineLimit = Changes[j].Spaces + Changes[j].TokenLength;
1475 if (LineLimit < Style.ColumnLimit) {
1476 Changes[i].NewlinesBefore = 0;
1477 setChangeSpaces(i, 1);
1482 setChangeSpaces(i, InitialSpaces);
1486 if (Changes[i].
Tok !=
C.Tok)
1488 Cells.push_back(CellDescription{i, Cell, i, HasSplit,
nullptr});
1492 return linkCells({Cells, CellCounts, InitialSpaces});
1495unsigned WhitespaceManager::calculateCellWidth(
unsigned Start,
unsigned End,
1496 bool WithSpaces)
const {
1497 unsigned CellWidth = 0;
1498 for (
auto i = Start; i < End; i++) {
1501 CellWidth += Changes[i].TokenLength;
1502 CellWidth += (WithSpaces ? Changes[i].Spaces : 0);
1507void WhitespaceManager::alignToStartOfCell(
unsigned Start,
unsigned End) {
1508 if ((End - Start) <= 1)
1512 for (
auto i = Start + 1; i < End; i++)
1514 setChangeSpaces(i, Changes[Start].Spaces);
1517WhitespaceManager::CellDescriptions
1518WhitespaceManager::linkCells(CellDescriptions &&CellDesc) {
1519 auto &Cells = CellDesc.Cells;
1520 for (
auto *CellIter = Cells.begin(); CellIter != Cells.end(); ++CellIter) {
1521 if (!CellIter->NextColumnElement && (CellIter + 1) != Cells.end()) {
1522 for (
auto *NextIter = CellIter + 1; NextIter != Cells.end(); ++NextIter) {
1523 if (NextIter->Cell == CellIter->Cell) {
1524 CellIter->NextColumnElement = &(*NextIter);
1530 return std::move(CellDesc);
1533void WhitespaceManager::setChangeSpaces(
unsigned Start,
unsigned Spaces) {
1537void WhitespaceManager::generateChanges() {
1538 for (
unsigned i = 0, e = Changes.size(); i != e; ++i) {
1541 auto Last = Changes[i - 1].OriginalWhitespaceRange;
1542 auto New = Changes[i].OriginalWhitespaceRange;
1584 if (
Last.getBegin() ==
New.getBegin() &&
1585 (
Last.getEnd() !=
Last.getBegin() ||
1586 New.getEnd() ==
New.getBegin())) {
1590 if (
C.CreateReplacement) {
1591 std::string ReplacementText =
C.PreviousLinePostfix;
1592 if (
C.ContinuesPPDirective) {
1593 appendEscapedNewlineText(ReplacementText,
C.NewlinesBefore,
1594 C.PreviousEndOfTokenColumn,
1595 C.EscapedNewlineColumn);
1597 appendNewlineText(ReplacementText,
C);
1602 ReplacementText,
C.Tok->IndentLevel, std::max(0,
C.Spaces),
1603 std::max((
int)
C.StartOfTokenColumn,
C.Spaces) - std::max(0,
C.Spaces),
1605 ReplacementText.append(
C.CurrentLinePrefix);
1606 storeReplacement(
C.OriginalWhitespaceRange, ReplacementText);
1611void WhitespaceManager::storeReplacement(SourceRange Range, StringRef
Text) {
1612 unsigned WhitespaceLength = SourceMgr.getFileOffset(
Range.getEnd()) -
1613 SourceMgr.getFileOffset(
Range.getBegin());
1615 if (StringRef(SourceMgr.getCharacterData(
Range.getBegin()),
1616 WhitespaceLength) ==
Text) {
1619 auto Err = Replaces.add(tooling::Replacement(
1624 llvm::errs() << llvm::toString(std::move(Err)) <<
"\n";
1629void WhitespaceManager::appendNewlineText(std::string &
Text,
const Change &
C) {
1630 if (
C.NewlinesBefore <= 0)
1633 StringRef Newline = UseCRLF ?
"\r\n" :
"\n";
1634 Text.append(Newline);
1636 if (
C.Tok->HasFormFeedBefore)
1639 for (
unsigned I = 1; I <
C.NewlinesBefore; ++I)
1640 Text.append(Newline);
1643void WhitespaceManager::appendEscapedNewlineText(
1644 std::string &
Text,
unsigned Newlines,
unsigned PreviousEndOfTokenColumn,
1645 unsigned EscapedNewlineColumn) {
1648 std::max<int>(1, EscapedNewlineColumn - PreviousEndOfTokenColumn - 1);
1649 for (
unsigned i = 0; i <
Newlines; ++i) {
1650 Text.append(Spaces,
' ');
1651 Text.append(UseCRLF ?
"\\\r\n" :
"\\\n");
1652 Spaces = std::max<int>(0, EscapedNewlineColumn - 1);
1657void WhitespaceManager::appendIndentText(std::string &
Text,
1659 unsigned WhitespaceStartColumn,
1661 switch (Style.UseTab) {
1662 case FormatStyle::UT_Never:
1663 Text.append(Spaces,
' ');
1665 case FormatStyle::UT_Always: {
1666 if (Style.TabWidth) {
1667 unsigned FirstTabWidth =
1668 Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
1671 if (Spaces < FirstTabWidth || Spaces == 1) {
1672 Text.append(Spaces,
' ');
1676 Spaces -= FirstTabWidth;
1679 Text.append(Spaces / Style.TabWidth,
'\t');
1680 Text.append(Spaces % Style.TabWidth,
' ');
1681 }
else if (Spaces == 1) {
1682 Text.append(Spaces,
' ');
1686 case FormatStyle::UT_ForIndentation:
1687 if (WhitespaceStartColumn == 0) {
1688 unsigned Indentation =
IndentLevel * Style.IndentWidth;
1689 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1691 Text.append(Spaces,
' ');
1693 case FormatStyle::UT_ForContinuationAndIndentation:
1694 if (WhitespaceStartColumn == 0)
1695 Spaces = appendTabIndent(
Text, Spaces, Spaces);
1696 Text.append(Spaces,
' ');
1698 case FormatStyle::UT_AlignWithSpaces:
1699 if (WhitespaceStartColumn == 0) {
1700 unsigned Indentation =
1701 IsAligned ?
IndentLevel * Style.IndentWidth : Spaces;
1702 Spaces = appendTabIndent(
Text, Spaces, Indentation);
1704 Text.append(Spaces,
' ');
1709unsigned WhitespaceManager::appendTabIndent(std::string &
Text,
unsigned Spaces,
1710 unsigned Indentation) {
1713 if (Indentation > Spaces)
1714 Indentation = Spaces;
1715 if (Style.TabWidth) {
1716 unsigned Tabs = Indentation / Style.TabWidth;
1717 Text.append(Tabs,
'\t');
1718 Spaces -= Tabs * Style.TabWidth;
WhitespaceManager class manages whitespace around tokens and their replacements.
__DEVICE__ long long abs(long long __n)
static CharSourceRange getCharRange(SourceRange R)
Encodes a location in the source.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
The JSON file list parser is used to communicate input to InstallAPI.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Type
The name was classified as a type.