aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Format/UnwrappedLineFormatter.cpp
diff options
context:
space:
mode:
authorNAKAMURA Takumi <geek4civic@gmail.com>2025-01-09 18:31:57 +0900
committerNAKAMURA Takumi <geek4civic@gmail.com>2025-01-09 18:33:27 +0900
commitdf025ebf872052c0761d44a3ef9b65e9675af8a8 (patch)
tree9b4e94583e2536546d6606270bcdf846c95e1ba2 /clang/lib/Format/UnwrappedLineFormatter.cpp
parent4428c9d0b1344179f85a72e183a44796976521e3 (diff)
parentbdcf47e4bcb92889665825654bb80a8bbe30379e (diff)
downloadllvm-users/chapuni/cov/single/loop.zip
llvm-users/chapuni/cov/single/loop.tar.gz
llvm-users/chapuni/cov/single/loop.tar.bz2
Merge branch 'users/chapuni/cov/single/base' into users/chapuni/cov/single/loopusers/chapuni/cov/single/loop
Conflicts: clang/lib/CodeGen/CoverageMappingGen.cpp
Diffstat (limited to 'clang/lib/Format/UnwrappedLineFormatter.cpp')
-rw-r--r--clang/lib/Format/UnwrappedLineFormatter.cpp168
1 files changed, 137 insertions, 31 deletions
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 1804c14..ec65fea 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -183,9 +183,9 @@ private:
unsigned Indent = 0;
};
-const FormatToken *getMatchingNamespaceToken(
- const AnnotatedLine *Line,
- const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
+const FormatToken *
+getMatchingNamespaceToken(const AnnotatedLine *Line,
+ const ArrayRef<AnnotatedLine *> &AnnotatedLines) {
if (!Line->startsWith(tok::r_brace))
return nullptr;
size_t StartLineIndex = Line->MatchingOpeningBlockLineIndex;
@@ -200,9 +200,9 @@ StringRef getNamespaceTokenText(const AnnotatedLine *Line) {
return NamespaceToken ? NamespaceToken->TokenText : StringRef();
}
-StringRef getMatchingNamespaceTokenText(
- const AnnotatedLine *Line,
- const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
+StringRef
+getMatchingNamespaceTokenText(const AnnotatedLine *Line,
+ const ArrayRef<AnnotatedLine *> &AnnotatedLines) {
const FormatToken *NamespaceToken =
getMatchingNamespaceToken(Line, AnnotatedLines);
return NamespaceToken ? NamespaceToken->TokenText : StringRef();
@@ -241,8 +241,8 @@ private:
/// Calculates how many lines can be merged into 1 starting at \p I.
unsigned
tryFitMultipleLinesInOne(LevelIndentTracker &IndentTracker,
- SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E) {
+ ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E) {
const unsigned Indent = IndentTracker.getIndent();
// Can't join the last line with anything.
@@ -361,9 +361,18 @@ private:
const auto *FirstNonComment = TheLine->getFirstNonComment();
if (!FirstNonComment)
return 0;
+
// FIXME: There are probably cases where we should use FirstNonComment
// instead of TheLine->First.
+ if (Style.AllowShortNamespacesOnASingleLine &&
+ TheLine->First->is(tok::kw_namespace) &&
+ TheLine->Last->is(tok::l_brace)) {
+ const auto result = tryMergeNamespace(I, E, Limit);
+ if (result > 0)
+ return result;
+ }
+
if (Style.CompactNamespaces) {
if (const auto *NSToken = TheLine->First->getNamespaceToken()) {
int J = 1;
@@ -373,7 +382,7 @@ private:
ClosingLineIndex == I[J]->MatchingClosingBlockLineIndex &&
I[J]->Last->TotalLength < Limit;
++J, --ClosingLineIndex) {
- Limit -= I[J]->Last->TotalLength;
+ Limit -= I[J]->Last->TotalLength + 1;
// Reduce indent level for bodies of namespaces which were compacted,
// but only if their content was indented in the first place.
@@ -420,6 +429,7 @@ private:
TheLine->First != LastNonComment) {
return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
}
+
// Try to merge a control statement block with left brace unwrapped.
if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&
FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
@@ -525,7 +535,7 @@ private:
// Try to merge records.
if (TheLine->Last->is(TT_EnumLBrace)) {
ShouldMerge = Style.AllowShortEnumsOnASingleLine;
- } else if (TheLine->Last->is(TT_RequiresExpressionLBrace)) {
+ } else if (TheLine->Last->is(TT_CompoundRequirementLBrace)) {
ShouldMerge = Style.AllowShortCompoundRequirementOnASingleLine;
} else if (TheLine->Last->isOneOf(TT_ClassLBrace, TT_StructLBrace)) {
// NOTE: We use AfterClass (whereas AfterStruct exists) for both classes
@@ -604,8 +614,8 @@ private:
}
unsigned
- tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E,
+ tryMergeSimplePPDirective(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
unsigned Limit) {
if (Limit == 0)
return 0;
@@ -616,9 +626,76 @@ private:
return 1;
}
- unsigned tryMergeSimpleControlStatement(
- SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
+ unsigned tryMergeNamespace(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
+ if (Limit == 0)
+ return 0;
+
+ assert(I[1]);
+ const auto &L1 = *I[1];
+ if (L1.InPPDirective != (*I)->InPPDirective ||
+ (L1.InPPDirective && L1.First->HasUnescapedNewline)) {
+ return 0;
+ }
+
+ if (std::distance(I, E) <= 2)
+ return 0;
+
+ assert(I[2]);
+ const auto &L2 = *I[2];
+ if (L2.Type == LT_Invalid)
+ return 0;
+
+ Limit = limitConsideringMacros(I + 1, E, Limit);
+
+ if (!nextTwoLinesFitInto(I, Limit))
+ return 0;
+
+ // Check if it's a namespace inside a namespace, and call recursively if so.
+ // '3' is the sizes of the whitespace and closing brace for " _inner_ }".
+ if (L1.First->is(tok::kw_namespace)) {
+ if (L1.Last->is(tok::comment) || !Style.CompactNamespaces)
+ return 0;
+
+ assert(Limit >= L1.Last->TotalLength + 3);
+ const auto InnerLimit = Limit - L1.Last->TotalLength - 3;
+ const auto MergedLines = tryMergeNamespace(I + 1, E, InnerLimit);
+ if (MergedLines == 0)
+ return 0;
+ const auto N = MergedLines + 2;
+ // Check if there is even a line after the inner result.
+ if (std::distance(I, E) <= N)
+ return 0;
+ // Check that the line after the inner result starts with a closing brace
+ // which we are permitted to merge into one line.
+ if (I[N]->First->is(tok::r_brace) && !I[N]->First->MustBreakBefore &&
+ I[MergedLines + 1]->Last->isNot(tok::comment) &&
+ nextNLinesFitInto(I, I + N + 1, Limit)) {
+ return N;
+ }
+ return 0;
+ }
+
+ // There's no inner namespace, so we are considering to merge at most one
+ // line.
+
+ // The line which is in the namespace should end with semicolon.
+ if (L1.Last->isNot(tok::semi))
+ return 0;
+
+ // Last, check that the third line starts with a closing brace.
+ if (L2.First->isNot(tok::r_brace) || L2.First->MustBreakBefore)
+ return 0;
+
+ // If so, merge all three lines.
+ return 2;
+ }
+
+ unsigned
+ tryMergeSimpleControlStatement(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
if (Limit == 0)
return 0;
if (Style.BraceWrapping.AfterControlStatement ==
@@ -658,10 +735,9 @@ private:
return 1;
}
- unsigned
- tryMergeShortCaseLabels(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E,
- unsigned Limit) {
+ unsigned tryMergeShortCaseLabels(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
if (Limit == 0 || I + 1 == E ||
I[1]->First->isOneOf(tok::kw_case, tok::kw_default)) {
return 0;
@@ -692,7 +768,7 @@ private:
if (Line->First->is(tok::comment)) {
if (Level != Line->Level)
return 0;
- SmallVectorImpl<AnnotatedLine *>::const_iterator J = I + 2 + NumStmts;
+ const auto *J = I + 2 + NumStmts;
for (; J != E; ++J) {
Line = *J;
if (Line->InPPDirective != InPPDirective)
@@ -713,10 +789,9 @@ private:
return NumStmts;
}
- unsigned
- tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E,
- unsigned Limit) {
+ unsigned tryMergeSimpleBlock(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
// Don't merge with a preprocessor directive.
if (I[1]->Type == LT_PreprocessorDirective)
return 0;
@@ -898,10 +973,9 @@ private:
/// Returns the modified column limit for \p I if it is inside a macro and
/// needs a trailing '\'.
- unsigned
- limitConsideringMacros(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
- SmallVectorImpl<AnnotatedLine *>::const_iterator E,
- unsigned Limit) {
+ unsigned limitConsideringMacros(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
if (I[0]->InPPDirective && I + 1 != E &&
!I[1]->First->HasUnescapedNewline && I[1]->First->isNot(tok::eof)) {
return Limit < 2 ? 0 : Limit - 2;
@@ -909,13 +983,28 @@ private:
return Limit;
}
- bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
+ bool nextTwoLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I,
unsigned Limit) {
if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore)
return false;
return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
}
+ bool nextNLinesFitInto(ArrayRef<AnnotatedLine *>::const_iterator I,
+ ArrayRef<AnnotatedLine *>::const_iterator E,
+ unsigned Limit) {
+ unsigned JoinedLength = 0;
+ for (const auto *J = I + 1; J != E; ++J) {
+ if ((*J)->First->MustBreakBefore)
+ return false;
+
+ JoinedLength += 1 + (*J)->Last->TotalLength;
+ if (JoinedLength > Limit)
+ return false;
+ }
+ return true;
+ }
+
bool containsMustBreak(const AnnotatedLine *Line) {
assert(Line->First);
// Ignore the first token, because in this situation, it applies more to the
@@ -943,9 +1032,9 @@ private:
const FormatStyle &Style;
const AdditionalKeywords &Keywords;
- const SmallVectorImpl<AnnotatedLine *>::const_iterator End;
+ const ArrayRef<AnnotatedLine *>::const_iterator End;
- SmallVectorImpl<AnnotatedLine *>::const_iterator Next;
+ ArrayRef<AnnotatedLine *>::const_iterator Next;
const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines;
};
@@ -1493,6 +1582,23 @@ static auto computeNewlines(const AnnotatedLine &Line,
Newlines = 1;
}
+ if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave) {
+ // Modify empty lines after TT_NamespaceLBrace.
+ if (PreviousLine && PreviousLine->endsWith(TT_NamespaceLBrace)) {
+ if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
+ Newlines = 1;
+ else if (!Line.startsWithNamespace())
+ Newlines = std::max(Newlines, 2u);
+ }
+ // Modify empty lines before TT_NamespaceRBrace.
+ if (Line.startsWith(TT_NamespaceRBrace)) {
+ if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never)
+ Newlines = 1;
+ else if (!PreviousLine->startsWith(TT_NamespaceRBrace))
+ Newlines = std::max(Newlines, 2u);
+ }
+ }
+
// Insert or remove empty line before access specifiers.
if (PreviousLine && RootToken.isAccessSpecifier()) {
switch (Style.EmptyLineBeforeAccessModifier) {