summaryrefslogtreecommitdiffstats
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.cpp143
1 files changed, 133 insertions, 10 deletions
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index 3d6040e90cd..18d73b553e6 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -29,13 +29,15 @@ WhitespaceManager::Change::Change(
bool CreateReplacement, const SourceRange &OriginalWhitespaceRange,
unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
unsigned NewlinesBefore, StringRef PreviousLinePostfix,
- StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective)
+ StringRef CurrentLinePrefix, tok::TokenKind Kind, bool ContinuesPPDirective,
+ bool IsStartOfDeclName)
: CreateReplacement(CreateReplacement),
OriginalWhitespaceRange(OriginalWhitespaceRange),
StartOfTokenColumn(StartOfTokenColumn), NewlinesBefore(NewlinesBefore),
PreviousLinePostfix(PreviousLinePostfix),
CurrentLinePrefix(CurrentLinePrefix), Kind(Kind),
- ContinuesPPDirective(ContinuesPPDirective), IndentLevel(IndentLevel),
+ ContinuesPPDirective(ContinuesPPDirective),
+ IsStartOfDeclName(IsStartOfDeclName), IndentLevel(IndentLevel),
Spaces(Spaces), IsTrailingComment(false), TokenLength(0),
PreviousEndOfTokenColumn(0), EscapedNewlineColumn(0),
StartOfBlockComment(nullptr), IndentationOffset(0) {}
@@ -52,19 +54,21 @@ void WhitespaceManager::replaceWhitespace(FormatToken &Tok, unsigned Newlines,
if (Tok.Finalized)
return;
Tok.Decision = (Newlines > 0) ? FD_Break : FD_Continue;
- Changes.push_back(Change(true, Tok.WhitespaceRange, IndentLevel, Spaces,
- StartOfTokenColumn, Newlines, "", "",
- Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst));
+ Changes.push_back(
+ Change(true, Tok.WhitespaceRange, IndentLevel, Spaces, StartOfTokenColumn,
+ Newlines, "", "", Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst,
+ Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName)));
}
void WhitespaceManager::addUntouchableToken(const FormatToken &Tok,
bool InPPDirective) {
if (Tok.Finalized)
return;
- Changes.push_back(Change(false, Tok.WhitespaceRange, /*IndentLevel=*/0,
- /*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore,
- "", "", Tok.Tok.getKind(),
- InPPDirective && !Tok.IsFirst));
+ Changes.push_back(
+ Change(false, Tok.WhitespaceRange, /*IndentLevel=*/0,
+ /*Spaces=*/0, Tok.OriginalColumn, Tok.NewlinesBefore, "", "",
+ Tok.Tok.getKind(), InPPDirective && !Tok.IsFirst,
+ Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName)));
}
void WhitespaceManager::replaceWhitespaceInToken(
@@ -84,7 +88,8 @@ void WhitespaceManager::replaceWhitespaceInToken(
// calculate the new length of the comment and to calculate the changes
// for which to do the alignment when aligning comments.
Tok.is(TT_LineComment) && Newlines > 0 ? tok::comment : tok::unknown,
- InPPDirective && !Tok.IsFirst));
+ InPPDirective && !Tok.IsFirst,
+ Tok.is(TT_StartOfName) || Tok.is(TT_FunctionDeclarationName)));
}
const tooling::Replacements &WhitespaceManager::generateReplacements() {
@@ -93,6 +98,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
std::sort(Changes.begin(), Changes.end(), Change::IsBeforeInFile(SourceMgr));
calculateLineBreakInformation();
+ alignConsecutiveDeclarations();
alignConsecutiveAssignments();
alignTrailingComments();
alignEscapedNewlines();
@@ -152,6 +158,7 @@ void WhitespaceManager::alignConsecutiveAssignments() {
return;
unsigned MinColumn = 0;
+ unsigned MaxColumn = UINT_MAX;
unsigned StartOfSequence = 0;
unsigned EndOfSequence = 0;
bool FoundAssignmentOnLine = false;
@@ -168,6 +175,7 @@ void WhitespaceManager::alignConsecutiveAssignments() {
if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
alignConsecutiveAssignments(StartOfSequence, EndOfSequence, MinColumn);
MinColumn = 0;
+ MaxColumn = UINT_MAX;
StartOfSequence = 0;
EndOfSequence = 0;
};
@@ -207,7 +215,18 @@ void WhitespaceManager::alignConsecutiveAssignments() {
StartOfSequence = i;
unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
+ int LineLengthAfter = -Changes[i].Spaces;
+ for (unsigned j = i; j != e && Changes[j].NewlinesBefore == 0; ++j)
+ LineLengthAfter += Changes[j].Spaces + Changes[j].TokenLength;
+ unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
+
+ if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) {
+ AlignSequence();
+ StartOfSequence = i;
+ }
+
MinColumn = std::max(MinColumn, ChangeMinColumn);
+ MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
}
}
@@ -242,6 +261,110 @@ void WhitespaceManager::alignConsecutiveAssignments(unsigned Start,
}
}
+// Walk through all of the changes and find sequences of declaration names to
+// align. To do so, keep track of the lines and whether or not a name was found
+// on align. If a name is found on a line, extend the current sequence. If the
+// current line cannot be part of a sequence, e.g. because there is an empty
+// line before it or it contains non-declarations, finalize the previous
+// sequence.
+void WhitespaceManager::alignConsecutiveDeclarations() {
+ if (!Style.AlignConsecutiveDeclarations)
+ return;
+
+ unsigned MinColumn = 0;
+ unsigned MaxColumn = UINT_MAX;
+ unsigned StartOfSequence = 0;
+ unsigned EndOfSequence = 0;
+ bool FoundDeclarationOnLine = false;
+ bool FoundLeftBraceOnLine = false;
+ bool FoundLeftParenOnLine = false;
+
+ auto AlignSequence = [&] {
+ if (StartOfSequence > 0 && StartOfSequence < EndOfSequence)
+ alignConsecutiveDeclarations(StartOfSequence, EndOfSequence, MinColumn);
+ MinColumn = 0;
+ MaxColumn = UINT_MAX;
+ StartOfSequence = 0;
+ EndOfSequence = 0;
+ };
+
+ for (unsigned i = 0, e = Changes.size(); i != e; ++i) {
+ if (Changes[i].NewlinesBefore != 0) {
+ EndOfSequence = i;
+ if (Changes[i].NewlinesBefore > 1 || !FoundDeclarationOnLine ||
+ FoundLeftBraceOnLine || FoundLeftParenOnLine)
+ AlignSequence();
+ FoundDeclarationOnLine = false;
+ FoundLeftBraceOnLine = false;
+ FoundLeftParenOnLine = false;
+ }
+
+ if (Changes[i].Kind == tok::r_brace) {
+ if (!FoundLeftBraceOnLine)
+ AlignSequence();
+ FoundLeftBraceOnLine = false;
+ } else if (Changes[i].Kind == tok::l_brace) {
+ FoundLeftBraceOnLine = true;
+ if (!FoundDeclarationOnLine)
+ AlignSequence();
+ } else if (Changes[i].Kind == tok::r_paren) {
+ if (!FoundLeftParenOnLine)
+ AlignSequence();
+ FoundLeftParenOnLine = false;
+ } else if (Changes[i].Kind == tok::l_paren) {
+ FoundLeftParenOnLine = true;
+ if (!FoundDeclarationOnLine)
+ AlignSequence();
+ } else if (!FoundDeclarationOnLine && !FoundLeftBraceOnLine &&
+ !FoundLeftParenOnLine && Changes[i].IsStartOfDeclName) {
+ FoundDeclarationOnLine = true;
+ if (StartOfSequence == 0)
+ StartOfSequence = i;
+
+ unsigned ChangeMinColumn = Changes[i].StartOfTokenColumn;
+ int LineLengthAfter = -Changes[i].Spaces;
+ for (unsigned j = i; j != e && Changes[j].NewlinesBefore == 0; ++j)
+ LineLengthAfter += Changes[j].Spaces + Changes[j].TokenLength;
+ unsigned ChangeMaxColumn = Style.ColumnLimit - LineLengthAfter;
+
+ if (ChangeMinColumn > MaxColumn || ChangeMaxColumn < MinColumn) {
+ AlignSequence();
+ StartOfSequence = i;
+ }
+
+ MinColumn = std::max(MinColumn, ChangeMinColumn);
+ MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
+ }
+ }
+
+ EndOfSequence = Changes.size();
+ AlignSequence();
+}
+
+void WhitespaceManager::alignConsecutiveDeclarations(unsigned Start,
+ unsigned End,
+ unsigned Column) {
+ bool FoundDeclarationOnLine = false;
+ int Shift = 0;
+ for (unsigned i = Start; i != End; ++i) {
+ if (Changes[i].NewlinesBefore != 0) {
+ FoundDeclarationOnLine = false;
+ Shift = 0;
+ }
+
+ if (!FoundDeclarationOnLine && Changes[i].IsStartOfDeclName) {
+ FoundDeclarationOnLine = true;
+ Shift = Column - Changes[i].StartOfTokenColumn;
+ Changes[i].Spaces += Shift;
+ }
+
+ assert(Shift >= 0);
+ Changes[i].StartOfTokenColumn += Shift;
+ if (i + 1 != Changes.size())
+ Changes[i + 1].PreviousEndOfTokenColumn += Shift;
+ }
+}
+
void WhitespaceManager::alignTrailingComments() {
unsigned MinColumn = 0;
unsigned MaxColumn = UINT_MAX;
OpenPOWER on IntegriCloud