summaryrefslogtreecommitdiffstats
path: root/clang/lib/Format
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Format')
-rw-r--r--clang/lib/Format/Format.cpp3
-rw-r--r--clang/lib/Format/WhitespaceManager.cpp143
-rw-r--r--clang/lib/Format/WhitespaceManager.h11
3 files changed, 146 insertions, 11 deletions
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index aa227a1f00a..d8a15e4cdfb 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -201,6 +201,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
IO.mapOptional("AlignConsecutiveAssignments",
Style.AlignConsecutiveAssignments);
+ IO.mapOptional("AlignConsecutiveDeclarations",
+ Style.AlignConsecutiveDeclarations);
IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft);
IO.mapOptional("AlignOperands", Style.AlignOperands);
IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
@@ -416,6 +418,7 @@ FormatStyle getLLVMStyle() {
LLVMStyle.AlignOperands = true;
LLVMStyle.AlignTrailingComments = true;
LLVMStyle.AlignConsecutiveAssignments = false;
+ LLVMStyle.AlignConsecutiveDeclarations = false;
LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
LLVMStyle.AllowShortBlocksOnASingleLine = false;
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;
diff --git a/clang/lib/Format/WhitespaceManager.h b/clang/lib/Format/WhitespaceManager.h
index d9738383298..8e03c6d3fc7 100644
--- a/clang/lib/Format/WhitespaceManager.h
+++ b/clang/lib/Format/WhitespaceManager.h
@@ -110,7 +110,7 @@ private:
unsigned IndentLevel, int Spaces, unsigned StartOfTokenColumn,
unsigned NewlinesBefore, StringRef PreviousLinePostfix,
StringRef CurrentLinePrefix, tok::TokenKind Kind,
- bool ContinuesPPDirective);
+ bool ContinuesPPDirective, bool IsStartOfDeclName);
bool CreateReplacement;
// Changes might be in the middle of a token, so we cannot just keep the
@@ -126,6 +126,7 @@ private:
// the \c BreakableToken is still doing its own alignment.
tok::TokenKind Kind;
bool ContinuesPPDirective;
+ bool IsStartOfDeclName;
// The number of nested blocks the token is in. This is used to add tabs
// only for the indentation, and not for alignment, when
@@ -173,6 +174,14 @@ private:
void alignConsecutiveAssignments(unsigned Start, unsigned End,
unsigned Column);
+ /// \brief Align consecutive declarations over all \c Changes.
+ void alignConsecutiveDeclarations();
+
+ /// \brief Align consecutive declarations from change \p Start to change \p
+ /// End at the specified \p Column.
+ void alignConsecutiveDeclarations(unsigned Start, unsigned End,
+ unsigned Column);
+
/// \brief Align trailing comments over all \c Changes.
void alignTrailingComments();
OpenPOWER on IntegriCloud