aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Format/WhitespaceManager.cpp
diff options
context:
space:
mode:
authorOwen Pan <owenpiano@gmail.com>2023-07-24 18:05:51 -0700
committerOwen Pan <owenpiano@gmail.com>2023-07-24 18:16:21 -0700
commit4ba00844174db562d2bd8b15dab6aac605eddf57 (patch)
tree14e1c08dab888bbd493613918cc11ddede083c72 /clang/lib/Format/WhitespaceManager.cpp
parentd25c79dc70008b835312e5cc7ef48b199fda3165 (diff)
downloadllvm-4ba00844174db562d2bd8b15dab6aac605eddf57.zip
llvm-4ba00844174db562d2bd8b15dab6aac605eddf57.tar.gz
llvm-4ba00844174db562d2bd8b15dab6aac605eddf57.tar.bz2
[clang-format] Add AlignConsecutiveShortCaseStatements
This adds a new AlignConsecutiveShortCaseStatements option in line with the existing AlignConsecutive* options , which when AllowShortCaseLabelsOnASingleLine is enabled will align the tokens after the case statement's colon. This also adds a AlignCaseColons option to allow aligning the case label colon itself rather than the token after it. Fixes #55475. Differential Revision: https://reviews.llvm.org/D151761
Diffstat (limited to 'clang/lib/Format/WhitespaceManager.cpp')
-rw-r--r--clang/lib/Format/WhitespaceManager.cpp133
1 files changed, 114 insertions, 19 deletions
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index 03dcc31..668ca38 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -102,6 +102,7 @@ const tooling::Replacements &WhitespaceManager::generateReplacements() {
llvm::sort(Changes, Change::IsBeforeInFile(SourceMgr));
calculateLineBreakInformation();
alignConsecutiveMacros();
+ alignConsecutiveShortCaseStatements();
alignConsecutiveDeclarations();
alignConsecutiveBitFields();
alignConsecutiveAssignments();
@@ -675,14 +676,12 @@ static unsigned AlignTokens(const FormatStyle &Style, F &&Matches,
//
// 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.
-static void AlignMacroSequence(
+static void AlignMatchingTokenSequence(
unsigned &StartOfSequence, unsigned &EndOfSequence, unsigned &MinColumn,
- unsigned &MaxColumn, bool &FoundMatchOnLine,
- std::function<bool(const WhitespaceManager::Change &C)> AlignMacrosMatches,
+ std::function<bool(const WhitespaceManager::Change &C)> Matches,
SmallVector<WhitespaceManager::Change, 16> &Changes) {
if (StartOfSequence > 0 && StartOfSequence < EndOfSequence) {
-
- FoundMatchOnLine = false;
+ bool FoundMatchOnLine = false;
int Shift = 0;
for (unsigned I = StartOfSequence; I != EndOfSequence; ++I) {
@@ -693,8 +692,8 @@ static void AlignMacroSequence(
// If this is the first matching token to be aligned, remember by how many
// spaces it has to be shifted, so the rest of the changes on the line are
- // shifted by the same amount
- if (!FoundMatchOnLine && AlignMacrosMatches(Changes[I])) {
+ // shifted by the same amount.
+ if (!FoundMatchOnLine && Matches(Changes[I])) {
FoundMatchOnLine = true;
Shift = MinColumn - Changes[I].StartOfTokenColumn;
Changes[I].Spaces += Shift;
@@ -708,7 +707,6 @@ static void AlignMacroSequence(
}
MinColumn = 0;
- MaxColumn = UINT_MAX;
StartOfSequence = 0;
EndOfSequence = 0;
}
@@ -747,7 +745,6 @@ void WhitespaceManager::alignConsecutiveMacros() {
};
unsigned MinColumn = 0;
- unsigned MaxColumn = UINT_MAX;
// Start and end of the token sequence we're processing.
unsigned StartOfSequence = 0;
@@ -775,8 +772,8 @@ void WhitespaceManager::alignConsecutiveMacros() {
!(LineIsComment && Style.AlignConsecutiveMacros.AcrossComments);
if (EmptyLineBreak || NoMatchBreak) {
- AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, MaxColumn,
- FoundMatchOnLine, AlignMacrosMatches, Changes);
+ AlignMatchingTokenSequence(StartOfSequence, EndOfSequence, MinColumn,
+ AlignMacrosMatches, Changes);
}
// A new line starts, re-initialize line status tracking bools.
@@ -796,18 +793,12 @@ void WhitespaceManager::alignConsecutiveMacros() {
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;
-
MinColumn = std::max(MinColumn, ChangeMinColumn);
- MaxColumn = std::min(MaxColumn, ChangeMaxColumn);
}
EndOfSequence = I;
- AlignMacroSequence(StartOfSequence, EndOfSequence, MinColumn, MaxColumn,
- FoundMatchOnLine, AlignMacrosMatches, Changes);
+ AlignMatchingTokenSequence(StartOfSequence, EndOfSequence, MinColumn,
+ AlignMacrosMatches, Changes);
}
void WhitespaceManager::alignConsecutiveAssignments() {
@@ -863,6 +854,110 @@ void WhitespaceManager::alignConsecutiveBitFields() {
Changes, /*StartAt=*/0, Style.AlignConsecutiveBitFields);
}
+void WhitespaceManager::alignConsecutiveShortCaseStatements() {
+ if (!Style.AlignConsecutiveShortCaseStatements.Enabled ||
+ !Style.AllowShortCaseLabelsOnASingleLine) {
+ return;
+ }
+
+ auto Matches = [&](const Change &C) {
+ if (Style.AlignConsecutiveShortCaseStatements.AlignCaseColons)
+ return C.Tok->is(TT_CaseLabelColon);
+
+ // Ignore 'IsInsideToken' to allow matching trailing comments which
+ // need to be reflowed as that causes the token to appear in two
+ // different changes, which will cause incorrect alignment as we'll
+ // reflow early due to detecting multiple aligning tokens per line.
+ return !C.IsInsideToken && C.Tok->Previous &&
+ C.Tok->Previous->is(TT_CaseLabelColon);
+ };
+
+ unsigned MinColumn = 0;
+
+ // Empty case statements don't break the alignment, but don't necessarily
+ // match our predicate, so we need to track their column so they can push out
+ // our alignment.
+ unsigned MinEmptyCaseColumn = 0;
+
+ // Start and end of the token sequence we're processing.
+ unsigned StartOfSequence = 0;
+ unsigned EndOfSequence = 0;
+
+ // Whether a matching token has been found on the current line.
+ bool FoundMatchOnLine = false;
+
+ bool LineIsComment = true;
+ bool LineIsEmptyCase = false;
+
+ unsigned I = 0;
+ for (unsigned E = Changes.size(); I != E; ++I) {
+ if (Changes[I].NewlinesBefore != 0) {
+ // Whether to break the alignment sequence because of an empty line.
+ bool EmptyLineBreak =
+ (Changes[I].NewlinesBefore > 1) &&
+ !Style.AlignConsecutiveShortCaseStatements.AcrossEmptyLines;
+
+ // Whether to break the alignment sequence because of a line without a
+ // match.
+ bool NoMatchBreak =
+ !FoundMatchOnLine &&
+ !(LineIsComment &&
+ Style.AlignConsecutiveShortCaseStatements.AcrossComments) &&
+ !LineIsEmptyCase;
+
+ if (EmptyLineBreak || NoMatchBreak) {
+ AlignMatchingTokenSequence(StartOfSequence, EndOfSequence, MinColumn,
+ Matches, Changes);
+ MinEmptyCaseColumn = 0;
+ }
+
+ // A new line starts, re-initialize line status tracking bools.
+ FoundMatchOnLine = false;
+ LineIsComment = true;
+ LineIsEmptyCase = false;
+ }
+
+ if (Changes[I].Tok->isNot(tok::comment))
+ LineIsComment = false;
+
+ if (Changes[I].Tok->is(TT_CaseLabelColon)) {
+ LineIsEmptyCase =
+ !Changes[I].Tok->Next || Changes[I].Tok->Next->isTrailingComment();
+
+ if (LineIsEmptyCase) {
+ if (Style.AlignConsecutiveShortCaseStatements.AlignCaseColons) {
+ MinEmptyCaseColumn =
+ std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn);
+ } else {
+ MinEmptyCaseColumn =
+ std::max(MinEmptyCaseColumn, Changes[I].StartOfTokenColumn + 2);
+ }
+ }
+ }
+
+ if (!Matches(Changes[I]))
+ continue;
+
+ if (LineIsEmptyCase)
+ continue;
+
+ FoundMatchOnLine = true;
+
+ if (StartOfSequence == 0)
+ StartOfSequence = I;
+
+ EndOfSequence = I + 1;
+
+ MinColumn = std::max(MinColumn, Changes[I].StartOfTokenColumn);
+
+ // Allow empty case statements to push out our alignment.
+ MinColumn = std::max(MinColumn, MinEmptyCaseColumn);
+ }
+
+ AlignMatchingTokenSequence(StartOfSequence, EndOfSequence, MinColumn, Matches,
+ Changes);
+}
+
void WhitespaceManager::alignConsecutiveDeclarations() {
if (!Style.AlignConsecutiveDeclarations.Enabled)
return;