diff options
author | NAKAMURA Takumi <geek4civic@gmail.com> | 2025-01-09 18:49:54 +0900 |
---|---|---|
committer | NAKAMURA Takumi <geek4civic@gmail.com> | 2025-01-09 18:49:54 +0900 |
commit | e2810c9a248f4c7fbfae84bb32b6f7e01027458b (patch) | |
tree | ae0b02a8491b969a1cee94ea16ffe42c559143c5 /clang/lib/Format/UnwrappedLineFormatter.cpp | |
parent | fa04eb4af95c1ca7377279728cb004bcd2324d01 (diff) | |
parent | bdcf47e4bcb92889665825654bb80a8bbe30379e (diff) | |
download | llvm-users/chapuni/cov/single/switch.zip llvm-users/chapuni/cov/single/switch.tar.gz llvm-users/chapuni/cov/single/switch.tar.bz2 |
Merge branch 'users/chapuni/cov/single/base' into users/chapuni/cov/single/switchusers/chapuni/cov/single/switch
Diffstat (limited to 'clang/lib/Format/UnwrappedLineFormatter.cpp')
-rw-r--r-- | clang/lib/Format/UnwrappedLineFormatter.cpp | 168 |
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) { |