aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Format/WhitespaceManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Format/WhitespaceManager.cpp')
-rw-r--r--clang/lib/Format/WhitespaceManager.cpp277
1 files changed, 178 insertions, 99 deletions
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index 4c130abd83c3..6ec788ad23c6 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -167,11 +167,12 @@ void WhitespaceManager::calculateLineBreakInformation() {
// If there are multiple changes in this token, sum up all the changes until
// the end of the line.
- if (Changes[i - 1].IsInsideToken && Changes[i - 1].NewlinesBefore == 0)
+ if (Changes[i - 1].IsInsideToken && Changes[i - 1].NewlinesBefore == 0) {
LastOutsideTokenChange->TokenLength +=
Changes[i - 1].TokenLength + Changes[i - 1].Spaces;
- else
+ } else {
LastOutsideTokenChange = &Changes[i - 1];
+ }
Changes[i].PreviousEndOfTokenColumn =
Changes[i - 1].StartOfTokenColumn + Changes[i - 1].TokenLength;
@@ -227,13 +228,12 @@ void WhitespaceManager::calculateLineBreakInformation() {
Change.StartOfBlockComment = nullptr;
Change.IndentationOffset = 0;
if (Change.Tok->is(tok::comment)) {
- if (Change.Tok->is(TT_LineComment) || !Change.IsInsideToken)
+ if (Change.Tok->is(TT_LineComment) || !Change.IsInsideToken) {
LastBlockComment = &Change;
- else {
- if ((Change.StartOfBlockComment = LastBlockComment))
- Change.IndentationOffset =
- Change.StartOfTokenColumn -
- Change.StartOfBlockComment->StartOfTokenColumn;
+ } else if ((Change.StartOfBlockComment = LastBlockComment)) {
+ Change.IndentationOffset =
+ Change.StartOfTokenColumn -
+ Change.StartOfBlockComment->StartOfTokenColumn;
}
} else {
LastBlockComment = nullptr;
@@ -260,19 +260,20 @@ void WhitespaceManager::calculateLineBreakInformation() {
Change.ConditionalsLevel = ConditionalsLevel;
- for (unsigned i = Change.Tok->FakeRParens; i > 0 && ScopeStack.size();
- --i) {
+ for (unsigned i = Change.Tok->FakeRParens; i > 0 && ScopeStack.size(); --i)
if (ScopeStack.pop_back_val())
--ConditionalsLevel;
- }
}
}
// Align a single sequence of tokens, see AlignTokens below.
+// Column - The token for which Matches returns true is moved to this column.
+// RightJustify - Whether it is the token's right end or left end that gets
+// moved to that column.
template <typename F>
static void
AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
- unsigned Column, F &&Matches,
+ unsigned Column, bool RightJustify, F &&Matches,
SmallVector<WhitespaceManager::Change, 16> &Changes) {
bool FoundMatchOnLine = false;
int Shift = 0;
@@ -302,18 +303,21 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
for (unsigned i = Start; i != End; ++i) {
if (ScopeStack.size() != 0 &&
Changes[i].indentAndNestingLevel() <
- Changes[ScopeStack.back()].indentAndNestingLevel())
+ Changes[ScopeStack.back()].indentAndNestingLevel()) {
ScopeStack.pop_back();
+ }
// Compare current token to previous non-comment token to ensure whether
// it is in a deeper scope or not.
unsigned PreviousNonComment = i - 1;
while (PreviousNonComment > Start &&
- Changes[PreviousNonComment].Tok->is(tok::comment))
+ Changes[PreviousNonComment].Tok->is(tok::comment)) {
--PreviousNonComment;
+ }
if (i != Start && Changes[i].indentAndNestingLevel() >
- Changes[PreviousNonComment].indentAndNestingLevel())
+ Changes[PreviousNonComment].indentAndNestingLevel()) {
ScopeStack.push_back(i);
+ }
bool InsideNestedScope = ScopeStack.size() != 0;
bool ContinuedStringLiteral = i > Start &&
@@ -331,8 +335,16 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
// shifted by the same amount
if (!FoundMatchOnLine && !SkipMatchCheck && Matches(Changes[i])) {
FoundMatchOnLine = true;
- Shift = Column - Changes[i].StartOfTokenColumn;
+ Shift = Column - (RightJustify ? Changes[i].TokenLength : 0) -
+ Changes[i].StartOfTokenColumn;
Changes[i].Spaces += Shift;
+ // FIXME: This is a workaround that should be removed when we fix
+ // http://llvm.org/PR53699. An assertion later below verifies this.
+ if (Changes[i].NewlinesBefore == 0) {
+ Changes[i].Spaces =
+ std::max(Changes[i].Spaces,
+ static_cast<int>(Changes[i].Tok->SpacesRequiredBefore));
+ }
}
// This is for function parameters that are split across multiple lines,
@@ -350,8 +362,9 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
// Continued function declaration
if (ScopeStart > Start + 1 &&
- Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName))
+ Changes[ScopeStart - 2].Tok->is(TT_FunctionDeclarationName)) {
return true;
+ }
// Continued function call
if (ScopeStart > Start + 1 &&
@@ -359,8 +372,15 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
Changes[ScopeStart - 1].Tok->is(tok::l_paren) &&
Changes[ScopeStart].Tok->isNot(TT_LambdaLSquare)) {
if (Changes[i].Tok->MatchingParen &&
- Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace))
+ Changes[i].Tok->MatchingParen->is(TT_LambdaLBrace)) {
+ return false;
+ }
+ if (Changes[ScopeStart].NewlinesBefore > 0)
return false;
+ if (Changes[i].Tok->is(tok::l_brace) &&
+ Changes[i].Tok->is(BK_BracedInit)) {
+ return true;
+ }
return Style.BinPackArguments;
}
@@ -374,8 +394,18 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
// Continued ternary operator
if (Changes[i].Tok->Previous &&
- Changes[i].Tok->Previous->is(TT_ConditionalExpr))
+ Changes[i].Tok->Previous->is(TT_ConditionalExpr)) {
return true;
+ }
+
+ // Continued direct-list-initialization using braced list.
+ if (ScopeStart > Start + 1 &&
+ Changes[ScopeStart - 2].Tok->is(tok::identifier) &&
+ Changes[ScopeStart - 1].Tok->is(tok::l_brace) &&
+ Changes[i].Tok->is(tok::l_brace) &&
+ Changes[i].Tok->is(BK_BracedInit)) {
+ return true;
+ }
// Continued braced list.
if (ScopeStart > Start + 1 &&
@@ -385,9 +415,12 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
for (unsigned OuterScopeStart : llvm::reverse(ScopeStack)) {
// Lambda.
if (OuterScopeStart > Start &&
- Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace))
+ Changes[OuterScopeStart - 1].Tok->is(TT_LambdaLBrace)) {
return false;
+ }
}
+ if (Changes[ScopeStart].NewlinesBefore > 0)
+ return false;
return true;
}
@@ -401,6 +434,12 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
if (ContinuedStringLiteral)
Changes[i].Spaces += Shift;
+ // We should not remove required spaces unless we break the line before.
+ assert(Shift >= 0 || Changes[i].NewlinesBefore > 0 ||
+ Changes[i].Spaces >=
+ static_cast<int>(Changes[i].Tok->SpacesRequiredBefore) ||
+ Changes[i].Tok->is(tok::eof));
+
Changes[i].StartOfTokenColumn += Shift;
if (i + 1 != Changes.size())
Changes[i + 1].PreviousEndOfTokenColumn += Shift;
@@ -414,6 +453,7 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
--Previous) {
Changes[Previous + 1].Spaces -= Shift;
Changes[Previous].Spaces += Shift;
+ Changes[Previous].StartOfTokenColumn += Shift;
}
}
}
@@ -446,13 +486,31 @@ AlignTokenSequence(const FormatStyle &Style, unsigned Start, unsigned End,
// However, the special exception is that we do NOT skip function parameters
// that are split across multiple lines. See the test case in FormatTest.cpp
// that mentions "split function parameter alignment" for an example of this.
+// When the parameter RightJustify is true, the operator will be
+// right-justified. It is used to align compound assignments like `+=` and `=`.
+// When RightJustify and ACS.PadOperators are true, operators in each block to
+// be aligned will be padded on the left to the same length before aligning.
template <typename F>
-static unsigned AlignTokens(
- const FormatStyle &Style, F &&Matches,
- SmallVector<WhitespaceManager::Change, 16> &Changes, unsigned StartAt,
- const FormatStyle::AlignConsecutiveStyle &ACS = FormatStyle::ACS_None) {
- unsigned MinColumn = 0;
- unsigned MaxColumn = UINT_MAX;
+static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
+ SmallVector<WhitespaceManager::Change, 16> &Changes,
+ unsigned StartAt,
+ const FormatStyle::AlignConsecutiveStyle &ACS = {},
+ bool RightJustify = false) {
+ // We arrange each line in 3 parts. The operator to be aligned (the anchor),
+ // and text to its left and right. In the aligned text the width of each part
+ // will be the maximum of that over the block that has been aligned. Maximum
+ // widths of each part so far. When RightJustify is true and ACS.PadOperators
+ // is false, the part from start of line to the right end of the anchor.
+ // Otherwise, only the part to the left of the anchor. Including the space
+ // that exists on its left from the start. Not including the padding added on
+ // the left to right-justify the anchor.
+ unsigned WidthLeft = 0;
+ // The operator to be aligned when RightJustify is true and ACS.PadOperators
+ // is false. 0 otherwise.
+ unsigned WidthAnchor = 0;
+ // Width to the right of the anchor. Plus width of the anchor when
+ // RightJustify is false.
+ unsigned WidthRight = 0;
// Line number of the start and the end of the current token sequence.
unsigned StartOfSequence = 0;
@@ -484,11 +542,14 @@ static unsigned AlignTokens(
// We need to adjust the StartOfTokenColumn of each Change that is on a line
// containing any matching token to be aligned and located after such token.
auto AlignCurrentSequence = [&] {
- if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
- AlignTokenSequence(Style, StartOfSequence, EndOfSequence, MinColumn,
- Matches, Changes);
- MinColumn = 0;
- MaxColumn = UINT_MAX;
+ if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
+ AlignTokenSequence(Style, StartOfSequence, EndOfSequence,
+ WidthLeft + WidthAnchor, RightJustify, Matches,
+ Changes);
+ }
+ WidthLeft = 0;
+ WidthAnchor = 0;
+ WidthRight = 0;
StartOfSequence = 0;
EndOfSequence = 0;
};
@@ -504,17 +565,12 @@ static unsigned AlignTokens(
// Whether to break the alignment sequence because of an empty line.
bool EmptyLineBreak =
- (Changes[i].NewlinesBefore > 1) &&
- (ACS != FormatStyle::ACS_AcrossEmptyLines) &&
- (ACS != FormatStyle::ACS_AcrossEmptyLinesAndComments);
+ (Changes[i].NewlinesBefore > 1) && !ACS.AcrossEmptyLines;
// Whether to break the alignment sequence because of a line without a
// match.
bool NoMatchBreak =
- !FoundMatchOnLine &&
- !(LineIsComment &&
- ((ACS == FormatStyle::ACS_AcrossComments) ||
- (ACS == FormatStyle::ACS_AcrossEmptyLinesAndComments)));
+ !FoundMatchOnLine && !(LineIsComment && ACS.AcrossComments);
if (EmptyLineBreak || NoMatchBreak)
AlignCurrentSequence();
@@ -522,14 +578,14 @@ static unsigned AlignTokens(
// A new line starts, re-initialize line status tracking bools.
// Keep the match state if a string literal is continued on this line.
if (i == 0 || !Changes[i].Tok->is(tok::string_literal) ||
- !Changes[i - 1].Tok->is(tok::string_literal))
+ !Changes[i - 1].Tok->is(tok::string_literal)) {
FoundMatchOnLine = false;
+ }
LineIsComment = true;
}
- if (!Changes[i].Tok->is(tok::comment)) {
+ if (!Changes[i].Tok->is(tok::comment))
LineIsComment = false;
- }
if (Changes[i].Tok->is(tok::comma)) {
++CommasBeforeMatch;
@@ -554,29 +610,44 @@ static unsigned AlignTokens(
if (StartOfSequence == 0)
StartOfSequence = i;
- unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
- int LineLengthAfter = Changes[i].TokenLength;
+ unsigned ChangeWidthLeft = Changes[i].StartOfTokenColumn;
+ unsigned ChangeWidthAnchor = 0;
+ unsigned ChangeWidthRight = 0;
+ if (RightJustify)
+ if (ACS.PadOperators)
+ ChangeWidthAnchor = Changes[i].TokenLength;
+ else
+ ChangeWidthLeft += Changes[i].TokenLength;
+ else
+ ChangeWidthRight = Changes[i].TokenLength;
for (unsigned j = i + 1; j != e && Changes[j].NewlinesBefore == 0; ++j) {
- LineLengthAfter += Changes[j].Spaces;
+ ChangeWidthRight += Changes[j].Spaces;
// Changes are generally 1:1 with the tokens, but a change could also be
// inside of a token, in which case it's counted more than once: once for
// the whitespace surrounding the token (!IsInsideToken) and once for
// each whitespace change within it (IsInsideToken).
// Therefore, changes inside of a token should only count the space.
if (!Changes[j].IsInsideToken)
- LineLengthAfter += Changes[j].TokenLength;
+ ChangeWidthRight += Changes[j].TokenLength;
}
- unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
// If we are restricted by the maximum column width, end the sequence.
- if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn ||
- CommasBeforeLastMatch != CommasBeforeMatch) {
+ unsigned NewLeft = std::max(ChangeWidthLeft, WidthLeft);
+ unsigned NewAnchor = std::max(ChangeWidthAnchor, WidthAnchor);
+ unsigned NewRight = std::max(ChangeWidthRight, WidthRight);
+ // `ColumnLimit == 0` means there is no column limit.
+ if (Style.ColumnLimit != 0 &&
+ Style.ColumnLimit < NewLeft + NewAnchor + NewRight) {
AlignCurrentSequence();
StartOfSequence = i;
+ WidthLeft = ChangeWidthLeft;
+ WidthAnchor = ChangeWidthAnchor;
+ WidthRight = ChangeWidthRight;
+ } else {
+ WidthLeft = NewLeft;
+ WidthAnchor = NewAnchor;
+ WidthRight = NewRight;
}
-
- MinColumn = std::max(MinColumn, ChangeMinColumn);
- MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
}
EndOfSequence = i;
@@ -630,7 +701,7 @@ static void AlignMacroSequence(
}
void WhitespaceManager::alignConsecutiveMacros() {
- if (Style.AlignConsecutiveMacros == FormatStyle::ACS_None)
+ if (!Style.AlignConsecutiveMacros.Enabled)
return;
auto AlignMacrosMatches = [](const Change &C) {
@@ -681,33 +752,27 @@ void WhitespaceManager::alignConsecutiveMacros() {
EndOfSequence = I;
// Whether to break the alignment sequence because of an empty line.
- bool EmptyLineBreak =
- (Changes[I].NewlinesBefore > 1) &&
- (Style.AlignConsecutiveMacros != FormatStyle::ACS_AcrossEmptyLines) &&
- (Style.AlignConsecutiveMacros !=
- FormatStyle::ACS_AcrossEmptyLinesAndComments);
+ bool EmptyLineBreak = (Changes[I].NewlinesBefore > 1) &&
+ !Style.AlignConsecutiveMacros.AcrossEmptyLines;
// Whether to break the alignment sequence because of a line without a
// match.
bool NoMatchBreak =
!FoundMatchOnLine &&
- !(LineIsComment && ((Style.AlignConsecutiveMacros ==
- FormatStyle::ACS_AcrossComments) ||
- (Style.AlignConsecutiveMacros ==
- FormatStyle::ACS_AcrossEmptyLinesAndComments)));
+ !(LineIsComment && Style.AlignConsecutiveMacros.AcrossComments);
- if (EmptyLineBreak || NoMatchBreak)
+ if (EmptyLineBreak || NoMatchBreak) {
AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, MaxColumn,
FoundMatchOnLine, AlignMacrosMatches, Changes);
+ }
// A new line starts, re-initialize line status tracking bools.
FoundMatchOnLine = false;
LineIsComment = true;
}
- if (!Changes[I].Tok->is(tok::comment)) {
+ if (!Changes[I].Tok->is(tok::comment))
LineIsComment = false;
- }
if (!AlignMacrosMatches(Changes[I]))
continue;
@@ -733,7 +798,7 @@ void WhitespaceManager::alignConsecutiveMacros() {
}
void WhitespaceManager::alignConsecutiveAssignments() {
- if (Style.AlignConsecutiveAssignments == FormatStyle::ACS_None)
+ if (!Style.AlignConsecutiveAssignments.Enabled)
return;
AlignTokens(
@@ -752,13 +817,16 @@ void WhitespaceManager::alignConsecutiveAssignments() {
if (Previous && Previous->is(tok::kw_operator))
return false;
- return C.Tok->is(tok::equal);
+ return Style.AlignConsecutiveAssignments.AlignCompound
+ ? C.Tok->getPrecedence() == prec::Assignment
+ : C.Tok->is(tok::equal);
},
- Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments);
+ Changes, /*StartAt=*/0, Style.AlignConsecutiveAssignments,
+ /*RightJustify=*/true);
}
void WhitespaceManager::alignConsecutiveBitFields() {
- if (Style.AlignConsecutiveBitFields == FormatStyle::ACS_None)
+ if (!Style.AlignConsecutiveBitFields.Enabled)
return;
AlignTokens(
@@ -778,7 +846,7 @@ void WhitespaceManager::alignConsecutiveBitFields() {
}
void WhitespaceManager::alignConsecutiveDeclarations() {
- if (Style.AlignConsecutiveDeclarations == FormatStyle::ACS_None)
+ if (!Style.AlignConsecutiveDeclarations.Enabled)
return;
AlignTokens(
@@ -802,8 +870,9 @@ void WhitespaceManager::alignConsecutiveDeclarations() {
if (!Next->Tok.getIdentifierInfo())
break;
if (Next->isOneOf(TT_StartOfName, TT_FunctionDeclarationName,
- tok::kw_operator))
+ tok::kw_operator)) {
return false;
+ }
}
return true;
},
@@ -834,10 +903,9 @@ void WhitespaceManager::alignChainedConditionals() {
// Ensure we keep alignment of wrapped operands with non-wrapped operands
// Since we actually align the operators, the wrapped operands need the
// extra offset to be properly aligned.
- for (Change &C : Changes) {
+ for (Change &C : Changes)
if (AlignWrappedOperand(C))
C.StartOfTokenColumn -= 2;
- }
AlignTokens(
Style,
[this](Change const &C) {
@@ -939,9 +1007,8 @@ void WhitespaceManager::alignTrailingComments(unsigned Start, unsigned End,
unsigned Column) {
for (unsigned i = Start; i != End; ++i) {
int Shift = 0;
- if (Changes[i].IsTrailingComment) {
+ if (Changes[i].IsTrailingComment)
Shift = Column - Changes[i].StartOfTokenColumn;
- }
if (Changes[i].StartOfBlockComment) {
Shift = Changes[i].IndentationOffset +
Changes[i].StartOfBlockComment->StartOfTokenColumn -
@@ -1026,11 +1093,13 @@ void WhitespaceManager::alignArrayInitializers(unsigned Start, unsigned End) {
void WhitespaceManager::alignArrayInitializersRightJustified(
CellDescriptions &&CellDescs) {
- auto &Cells = CellDescs.Cells;
+ if (!CellDescs.isRectangular())
+ return;
+ auto &Cells = CellDescs.Cells;
// Now go through and fixup the spaces.
auto *CellIter = Cells.begin();
- for (auto i = 0U; i < CellDescs.CellCount; ++i, ++CellIter) {
+ for (auto i = 0U; i < CellDescs.CellCounts[0]; ++i, ++CellIter) {
unsigned NetWidth = 0U;
if (isSplitCell(*CellIter))
NetWidth = getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
@@ -1040,28 +1109,30 @@ void WhitespaceManager::alignArrayInitializersRightJustified(
// So in here we want to see if there is a brace that falls
// on a line that was split. If so on that line we make sure that
// the spaces in front of the brace are enough.
- Changes[CellIter->Index].NewlinesBefore = 0;
- Changes[CellIter->Index].Spaces = 0;
- for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
- Next = Next->NextColumnElement) {
- Changes[Next->Index].Spaces = 0;
- Changes[Next->Index].NewlinesBefore = 0;
- }
+ const auto *Next = CellIter;
+ do {
+ const FormatToken *Previous = Changes[Next->Index].Tok->Previous;
+ if (Previous && Previous->isNot(TT_LineComment)) {
+ Changes[Next->Index].Spaces = 0;
+ Changes[Next->Index].NewlinesBefore = 0;
+ }
+ Next = Next->NextColumnElement;
+ } while (Next);
// Unless the array is empty, we need the position of all the
// immediately adjacent cells
if (CellIter != Cells.begin()) {
auto ThisNetWidth =
getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
- auto MaxNetWidth =
- getMaximumNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces,
- CellDescs.CellCount);
+ auto MaxNetWidth = getMaximumNetWidth(
+ Cells.begin(), CellIter, CellDescs.InitialSpaces,
+ CellDescs.CellCounts[0], CellDescs.CellCounts.size());
if (ThisNetWidth < MaxNetWidth)
Changes[CellIter->Index].Spaces = (MaxNetWidth - ThisNetWidth);
auto RowCount = 1U;
auto Offset = std::distance(Cells.begin(), CellIter);
for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
Next = Next->NextColumnElement) {
- auto *Start = (Cells.begin() + RowCount * CellDescs.CellCount);
+ auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
auto *End = Start + Offset;
ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
if (ThisNetWidth < MaxNetWidth)
@@ -1094,8 +1165,11 @@ void WhitespaceManager::alignArrayInitializersRightJustified(
void WhitespaceManager::alignArrayInitializersLeftJustified(
CellDescriptions &&CellDescs) {
- auto &Cells = CellDescs.Cells;
+ if (!CellDescs.isRectangular())
+ return;
+
+ auto &Cells = CellDescs.Cells;
// Now go through and fixup the spaces.
auto *CellIter = Cells.begin();
// The first cell needs to be against the left brace.
@@ -1104,9 +1178,10 @@ void WhitespaceManager::alignArrayInitializersLeftJustified(
else
Changes[CellIter->Index].Spaces = CellDescs.InitialSpaces;
++CellIter;
- for (auto i = 1U; i < CellDescs.CellCount; i++, ++CellIter) {
+ for (auto i = 1U; i < CellDescs.CellCounts[0]; i++, ++CellIter) {
auto MaxNetWidth = getMaximumNetWidth(
- Cells.begin(), CellIter, CellDescs.InitialSpaces, CellDescs.CellCount);
+ Cells.begin(), CellIter, CellDescs.InitialSpaces,
+ CellDescs.CellCounts[0], CellDescs.CellCounts.size());
auto ThisNetWidth =
getNetWidth(Cells.begin(), CellIter, CellDescs.InitialSpaces);
if (Changes[CellIter->Index].NewlinesBefore == 0) {
@@ -1118,7 +1193,9 @@ void WhitespaceManager::alignArrayInitializersLeftJustified(
auto Offset = std::distance(Cells.begin(), CellIter);
for (const auto *Next = CellIter->NextColumnElement; Next != nullptr;
Next = Next->NextColumnElement) {
- auto *Start = (Cells.begin() + RowCount * CellDescs.CellCount);
+ if (RowCount > CellDescs.CellCounts.size())
+ break;
+ auto *Start = (Cells.begin() + RowCount * CellDescs.CellCounts[0]);
auto *End = Start + Offset;
auto ThisNetWidth = getNetWidth(Start, End, CellDescs.InitialSpaces);
if (Changes[Next->Index].NewlinesBefore == 0) {
@@ -1147,7 +1224,7 @@ WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start,
unsigned Depth = 0;
unsigned Cell = 0;
- unsigned CellCount = 0;
+ SmallVector<unsigned> CellCounts;
unsigned InitialSpaces = 0;
unsigned InitialTokenLength = 0;
unsigned EndSpaces = 0;
@@ -1187,7 +1264,8 @@ WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start,
if (!Cells.empty())
Cells.back().EndIndex = i;
Cells.push_back(CellDescription{i, ++Cell, i + 1, false, nullptr});
- CellCount = C.Tok->Previous->isNot(tok::comma) ? Cell + 1 : Cell;
+ CellCounts.push_back(C.Tok->Previous->isNot(tok::comma) ? Cell + 1
+ : Cell);
// Go to the next non-comment and ensure there is a break in front
const auto *NextNonComment = C.Tok->getNextNonComment();
while (NextNonComment->is(tok::comma))
@@ -1257,7 +1335,7 @@ WhitespaceManager::CellDescriptions WhitespaceManager::getCells(unsigned Start,
}
}
- return linkCells({Cells, CellCount, InitialSpaces});
+ return linkCells({Cells, CellCounts, InitialSpaces});
}
unsigned WhitespaceManager::calculateCellWidth(unsigned Start, unsigned End,
@@ -1277,10 +1355,9 @@ void WhitespaceManager::alignToStartOfCell(unsigned Start, unsigned End) {
return;
// If the line is broken anywhere in there make sure everything
// is aligned to the parent
- for (auto i = Start + 1; i < End; i++) {
+ for (auto i = Start + 1; i < End; i++)
if (Changes[i].NewlinesBefore > 0)
Changes[i].Spaces = Changes[Start].Spaces;
- }
}
WhitespaceManager::CellDescriptions
@@ -1310,12 +1387,13 @@ void WhitespaceManager::generateChanges() {
}
if (C.CreateReplacement) {
std::string ReplacementText = C.PreviousLinePostfix;
- if (C.ContinuesPPDirective)
+ if (C.ContinuesPPDirective) {
appendEscapedNewlineText(ReplacementText, C.NewlinesBefore,
C.PreviousEndOfTokenColumn,
C.EscapedNewlineColumn);
- else
+ } else {
appendNewlineText(ReplacementText, C.NewlinesBefore);
+ }
// FIXME: This assert should hold if we computed the column correctly.
// assert((int)C.StartOfTokenColumn >= C.Spaces);
appendIndentText(
@@ -1333,8 +1411,9 @@ void WhitespaceManager::storeReplacement(SourceRange Range, StringRef Text) {
SourceMgr.getFileOffset(Range.getBegin());
// Don't create a replacement, if it does not change anything.
if (StringRef(SourceMgr.getCharacterData(Range.getBegin()),
- WhitespaceLength) == Text)
+ WhitespaceLength) == Text) {
return;
+ }
auto Err = Replaces.add(tooling::Replacement(
SourceMgr, CharSourceRange::getCharRange(Range), Text));
// FIXME: better error handling. For now, just print an error message in the