https://github.com/seranu created https://github.com/llvm/llvm-project/pull/77918
Extend SeparateDefinitionStyle to support spacing license text, include blocks and to also support two empty lines between blocks. Fixes #42112 . >From 60a5851b40f03fb71b2a3d30972d51ba40244d68 Mon Sep 17 00:00:00 2001 From: Serban Ungureanu <serban.ungure...@randstaddigital.com> Date: Fri, 12 Jan 2024 14:33:32 +0200 Subject: [PATCH] [clang-format] Extend DefinitionBlockSeparatorStyle to separate license text, include blocks and to support two empty lines between blocks --- clang/include/clang/Format/Format.h | 71 ++--- clang/lib/Format/DefinitionBlockSeparator.cpp | 56 +++- clang/lib/Format/Format.cpp | 3 +- clang/lib/Format/TokenAnnotator.h | 6 + .../Format/DefinitionBlockSeparatorTest.cpp | 268 +++++++++++++----- 5 files changed, 292 insertions(+), 112 deletions(-) diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 5ffd63ee73fc36..794817a26879d5 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -3853,46 +3853,51 @@ struct FormatStyle { /// Leave definition blocks as they are. SDS_Leave, /// Insert an empty line between definition blocks. - SDS_Always, + SDS_One, + /// Insert two empty lines between definition blocks. + SDS_Two, /// Remove any empty line between definition blocks. SDS_Never }; /// Specifies the use of empty lines to separate definition blocks, including - /// classes, structs, enums, and functions. + /// license text, includes, classes, structs, enums, and functions. /// \code /// Never v.s. Always - /// #include <cstring> #include <cstring> - /// struct Foo { - /// int a, b, c; struct Foo { - /// }; int a, b, c; - /// namespace Ns { }; - /// class Bar { - /// public: namespace Ns { - /// struct Foobar { class Bar { - /// int a; public: - /// int b; struct Foobar { - /// }; int a; - /// private: int b; - /// int t; }; - /// int method1() { - /// // ... private: - /// } int t; - /// enum List { - /// ITEM1, int method1() { - /// ITEM2 // ... - /// }; } - /// template<typename T> - /// int method2(T x) { enum List { - /// // ... ITEM1, - /// } ITEM2 - /// int i, j, k; }; - /// int method3(int par) { - /// // ... template<typename T> - /// } int method2(T x) { - /// }; // ... - /// class C {}; } - /// } + /// /* License text /* License text + /// End license text */ End license text */ + /// #include <cstring> + /// struct Foo { #include <cstring> + /// int a, b, c; + /// }; struct Foo { + /// namespace Ns { int a, b, c; + /// class Bar { }; + /// public: + /// struct Foobar { namespace Ns { + /// int a; class Bar { + /// int b; public: + /// }; struct Foobar { + /// private: int a; + /// int t; int b; + /// int method1() { }; + /// // ... + /// } private: + /// enum List { int t; + /// ITEM1, + /// ITEM2 int method1() { + /// }; // ... + /// template<typename T> } + /// int method2(T x) { + /// // ... enum List { + /// } ITEM1, + /// int i, j, k; ITEM2 + /// int method3(int par) { }; + /// // ... + /// } template<typename T> + /// }; int method2(T x) { + /// class C {}; // ... + /// } } + /// /// int i, j, k; /// /// int method3(int par) { diff --git a/clang/lib/Format/DefinitionBlockSeparator.cpp b/clang/lib/Format/DefinitionBlockSeparator.cpp index 319236d3bd618c..37d554fb678662 100644 --- a/clang/lib/Format/DefinitionBlockSeparator.cpp +++ b/clang/lib/Format/DefinitionBlockSeparator.cpp @@ -17,6 +17,22 @@ #include "llvm/Support/Debug.h" #define DEBUG_TYPE "definition-block-separator" +namespace { +unsigned getNewlineCount( + clang::format::FormatStyle::SeparateDefinitionStyle separateDefinitions) { + switch (separateDefinitions) { + case clang::format::FormatStyle::SDS_One: + return 2; + case clang::format::FormatStyle::SDS_Two: + return 3; + case clang::format::FormatStyle::SDS_Never: + return 1; + case clang::format::FormatStyle::SDS_Leave: + assert(false); + } + return 1; +} +} // namespace namespace clang { namespace format { std::pair<tooling::Replacements, unsigned> DefinitionBlockSeparator::analyze( @@ -65,8 +81,7 @@ void DefinitionBlockSeparator::separateBlocks( } return false; }; - unsigned NewlineCount = - (Style.SeparateDefinitionBlocks == FormatStyle::SDS_Always ? 1 : 0) + 1; + unsigned NewlineCount = getNewlineCount(Style.SeparateDefinitionBlocks); WhitespaceManager Whitespaces( Env.getSourceManager(), Style, Style.LineEnding > FormatStyle::LE_CRLF @@ -74,9 +89,10 @@ void DefinitionBlockSeparator::separateBlocks( Env.getSourceManager().getBufferData(Env.getFileID()), Style.LineEnding == FormatStyle::LE_DeriveCRLF) : Style.LineEnding == FormatStyle::LE_CRLF); + std::optional<bool> inLicenseText{}; for (unsigned I = 0; I < Lines.size(); ++I) { const auto &CurrentLine = Lines[I]; - if (CurrentLine->InPPDirective) + if (CurrentLine->InMacroBody) continue; FormatToken *TargetToken = nullptr; AnnotatedLine *TargetLine; @@ -93,7 +109,7 @@ void DefinitionBlockSeparator::separateBlocks( if (TargetToken->is(tok::eof)) return; if (IsAccessSpecifierToken(TargetToken) || - (OpeningLineIndex > 0 && + (OpeningLineIndex > 0 && OpeningLineIndex < Lines.size() && IsAccessSpecifierToken(Lines[OpeningLineIndex - 1]->First))) { return; } @@ -171,6 +187,31 @@ void DefinitionBlockSeparator::separateBlocks( return false; }; + // Separate License text. + const bool isComment = Lines[I]->isComment(); + if (!inLicenseText.has_value()) { + inLicenseText = isComment; + if (isComment) { + while (I < Lines.size() && Lines[I]->isComment()) + ++I; + if (I < Lines.size()) { + inLicenseText = false; + TargetLine = Lines[I]; + TargetToken = TargetLine->First; + InsertReplacement(NewlineCount); + continue; + } + } + } + + // Separate includes block. + if (I > 0 && Lines[I - 1]->isInclude() && !Lines[I]->isInclude()) { + TargetLine = Lines[I]; + TargetToken = TargetLine->First; + InsertReplacement(NewlineCount); + continue; + } + if (HasEnumOnLine() && !LikelyDefinition(CurrentLine, /*ExcludeEnum=*/true)) { // We have no scope opening/closing information for enum. @@ -214,8 +255,10 @@ void DefinitionBlockSeparator::separateBlocks( TargetToken = TargetLine->First; if (!FollowingOtherOpening()) { // Avoid duplicated replacement. - if (TargetToken->isNot(tok::l_brace)) + if (TargetToken->isNot(tok::l_brace) && OpeningLineIndex > 0 && + !Lines[OpeningLineIndex - 1]->isInclude()) { InsertReplacement(NewlineCount); + } } else if (IsNeverStyle) { InsertReplacement(OpeningLineIndex != 0); } @@ -238,7 +281,8 @@ void DefinitionBlockSeparator::separateBlocks( ++OpeningLineIndex; } TargetLine = Lines[OpeningLineIndex]; - if (!LikelyDefinition(TargetLine)) { + if (!LikelyDefinition(TargetLine) && OpeningLineIndex > 0 && + !Lines[OpeningLineIndex - 1]->isInclude()) { OpeningLineIndex = I + 1; TargetLine = Lines[I + 1]; TargetToken = TargetLine->First; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index ff5ed6c306f383..4e23fd8ed15e8f 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -586,7 +586,8 @@ template <> struct ScalarEnumerationTraits<FormatStyle::SeparateDefinitionStyle> { static void enumeration(IO &IO, FormatStyle::SeparateDefinitionStyle &Value) { IO.enumCase(Value, "Leave", FormatStyle::SDS_Leave); - IO.enumCase(Value, "Always", FormatStyle::SDS_Always); + IO.enumCase(Value, "One", FormatStyle::SDS_One); + IO.enumCase(Value, "Two", FormatStyle::SDS_Two); IO.enumCase(Value, "Never", FormatStyle::SDS_Never); } }; diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 05a6daa87d8034..cf40eea9026270 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -113,6 +113,12 @@ class AnnotatedLine { return First && First->is(tok::comment) && !First->getNextNonComment(); } + bool isInclude() const { + const auto *nextToken = First->getNextNonComment(); + return First && First->is(tok::hash) && nextToken && + nextToken->is(tok::pp_include); + } + /// \c true if this line starts with the given tokens in order, ignoring /// comments. template <typename... Ts> bool startsWith(Ts... Tokens) const { diff --git a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp index f5489498a93b9e..9f64675d796ada 100644 --- a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp +++ b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp @@ -17,80 +17,97 @@ namespace clang { namespace format { namespace { +std::string +separateDefinitionBlocks(llvm::StringRef Code, + const std::vector<tooling::Range> &Ranges, + const FormatStyle &Style = getLLVMStyle()) { + LLVM_DEBUG(llvm::errs() << "---\n"); + LLVM_DEBUG(llvm::errs() << Code << "\n\n"); + tooling::Replacements Replaces = reformat(Style, Code, Ranges, "<stdin>"); + auto Result = applyAllReplacements(Code, Replaces); + EXPECT_TRUE(static_cast<bool>(Result)); + LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); + return *Result; +} -class DefinitionBlockSeparatorTest : public ::testing::Test { -protected: - static std::string - separateDefinitionBlocks(llvm::StringRef Code, - const std::vector<tooling::Range> &Ranges, - const FormatStyle &Style = getLLVMStyle()) { - LLVM_DEBUG(llvm::errs() << "---\n"); - LLVM_DEBUG(llvm::errs() << Code << "\n\n"); - tooling::Replacements Replaces = reformat(Style, Code, Ranges, "<stdin>"); - auto Result = applyAllReplacements(Code, Replaces); - EXPECT_TRUE(static_cast<bool>(Result)); - LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n"); - return *Result; - } - - static std::string - separateDefinitionBlocks(llvm::StringRef Code, - const FormatStyle &Style = getLLVMStyle()) { - return separateDefinitionBlocks( - Code, - /*Ranges=*/{1, tooling::Range(0, Code.size())}, Style); - } - - static void _verifyFormat(const char *File, int Line, llvm::StringRef Code, - const FormatStyle &Style = getLLVMStyle(), - llvm::StringRef ExpectedCode = "", - bool Inverse = true) { - ::testing::ScopedTrace t(File, Line, ::testing::Message() << Code.str()); - bool HasOriginalCode = true; - if (ExpectedCode == "") { - ExpectedCode = Code; - HasOriginalCode = false; - } +std::string +separateDefinitionBlocks(llvm::StringRef Code, + const FormatStyle &Style = getLLVMStyle()) { + return separateDefinitionBlocks( + Code, + /*Ranges=*/{1, tooling::Range(0, Code.size())}, Style); +} - EXPECT_EQ(ExpectedCode, separateDefinitionBlocks(ExpectedCode, Style)) - << "Expected code is not stable"; - if (Inverse) { - FormatStyle InverseStyle = Style; - if (Style.SeparateDefinitionBlocks == FormatStyle::SDS_Always) - InverseStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Never; - else - InverseStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Always; - EXPECT_NE(ExpectedCode, - separateDefinitionBlocks(ExpectedCode, InverseStyle)) - << "Inverse formatting makes no difference"; +std::string removeEmptyLines(llvm::StringRef Code) { + std::string Result = ""; + for (auto Char : Code.str()) { + if (Result.size()) { + auto LastChar = Result.back(); + if ((Char == '\n' && LastChar == '\n') || + (Char == '\r' && (LastChar == '\r' || LastChar == '\n'))) { + continue; + } } - std::string CodeToFormat = - HasOriginalCode ? Code.str() : removeEmptyLines(Code); - std::string Result = separateDefinitionBlocks(CodeToFormat, Style); - EXPECT_EQ(ExpectedCode, Result) << "Test failed. Formatted:\n" << Result; + Result.push_back(Char); + } + return Result; +} +void _verifyFormat(const char *File, int Line, llvm::StringRef Code, + const FormatStyle &Style = getLLVMStyle(), + llvm::StringRef ExpectedCode = "", bool Inverse = true) { + ::testing::ScopedTrace t(File, Line, ::testing::Message() << Code.str()); + bool HasOriginalCode = true; + if (ExpectedCode == "") { + ExpectedCode = Code; + HasOriginalCode = false; } - static std::string removeEmptyLines(llvm::StringRef Code) { - std::string Result = ""; - for (auto Char : Code.str()) { - if (Result.size()) { - auto LastChar = Result.back(); - if ((Char == '\n' && LastChar == '\n') || - (Char == '\r' && (LastChar == '\r' || LastChar == '\n'))) { - continue; - } - } - Result.push_back(Char); + EXPECT_EQ(ExpectedCode, separateDefinitionBlocks(ExpectedCode, Style)) + << "Expected code is not stable"; + + auto checkInverseStyle = [&](FormatStyle::SeparateDefinitionStyle newStyle) { + FormatStyle InverseStyle = Style; + InverseStyle.SeparateDefinitionBlocks = newStyle; + if (newStyle == FormatStyle::SDS_Two) + InverseStyle.MaxEmptyLinesToKeep = 2; + EXPECT_NE(ExpectedCode, + separateDefinitionBlocks(ExpectedCode, InverseStyle)) + << "Changing formatting makes no difference"; + }; + if (Inverse) { + switch (Style.SeparateDefinitionBlocks) { + case FormatStyle::SDS_Never: + checkInverseStyle(FormatStyle::SDS_One); + checkInverseStyle(FormatStyle::SDS_Two); + break; + case FormatStyle::SDS_One: + checkInverseStyle(FormatStyle::SDS_Never); + checkInverseStyle(FormatStyle::SDS_Two); + break; + case FormatStyle::SDS_Two: + checkInverseStyle(FormatStyle::SDS_Never); + checkInverseStyle(FormatStyle::SDS_One); + break; + case FormatStyle::SDS_Leave: + break; } - return Result; } -}; + std::string CodeToFormat = + HasOriginalCode ? Code.str() : removeEmptyLines(Code); + std::string Result = separateDefinitionBlocks(CodeToFormat, Style); + EXPECT_EQ(ExpectedCode, Result) << "Test failed. Formatted:\n" << Result; +} +class DefinitionBlockSeparatorTest : public ::testing::Test {}; + +class LicenseTest : public ::testing::TestWithParam<std::string> {}; +class IncludesTest : public ::testing::TestWithParam<std::string> {}; +class NoNewLineAtEofTest : public ::testing::TestWithParam<std::string> {}; #define verifyFormat(...) _verifyFormat(__FILE__, __LINE__, __VA_ARGS__) TEST_F(DefinitionBlockSeparatorTest, Basic) { FormatStyle Style = getLLVMStyle(); - Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always; + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; verifyFormat("int foo(int i, int j) {\n" " int r = i + j;\n" " return r;\n" @@ -164,7 +181,7 @@ TEST_F(DefinitionBlockSeparatorTest, Basic) { TEST_F(DefinitionBlockSeparatorTest, FormatConflict) { FormatStyle Style = getLLVMStyle(); - Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always; + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; llvm::StringRef Code = "class Test {\n" "public:\n" " static void foo() {\n" @@ -178,7 +195,7 @@ TEST_F(DefinitionBlockSeparatorTest, FormatConflict) { TEST_F(DefinitionBlockSeparatorTest, CommentBlock) { FormatStyle Style = getLLVMStyle(); - Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always; + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; std::string Prefix = "enum Foo { FOO, BAR };\n" "\n" "/*\n" @@ -248,18 +265,18 @@ TEST_F(DefinitionBlockSeparatorTest, UntouchBlockStartStyle) { }; FormatStyle AlwaysStyle = getLLVMStyle(); - AlwaysStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Always; + AlwaysStyle.SeparateDefinitionBlocks = FormatStyle::SDS_One; FormatStyle NeverStyle = getLLVMStyle(); NeverStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Never; - auto TestKit = MakeUntouchTest("/* FOOBAR */\n" + auto TestKit = MakeUntouchTest("/* FOOBAR */\n\n" "#ifdef FOO\n\n", "\n#elifndef BAR\n\n", "\n#endif\n\n", false); verifyFormat(TestKit.first, AlwaysStyle, TestKit.second); verifyFormat(TestKit.second, NeverStyle, removeEmptyLines(TestKit.second)); - TestKit = MakeUntouchTest("/* FOOBAR */\n" + TestKit = MakeUntouchTest("/* FOOBAR */\n\n" "#ifdef FOO\n", "#elifndef BAR\n", "#endif\n", false); verifyFormat(TestKit.first, AlwaysStyle, TestKit.second); @@ -282,7 +299,7 @@ TEST_F(DefinitionBlockSeparatorTest, UntouchBlockStartStyle) { TEST_F(DefinitionBlockSeparatorTest, Always) { FormatStyle Style = getLLVMStyle(); - Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always; + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; verifyFormat("// clang-format off\n" "template<class T>\n" @@ -400,7 +417,7 @@ TEST_F(DefinitionBlockSeparatorTest, Never) { TEST_F(DefinitionBlockSeparatorTest, OpeningBracketOwnsLine) { FormatStyle Style = getLLVMStyle(); Style.BreakBeforeBraces = FormatStyle::BS_Allman; - Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always; + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; verifyFormat("namespace NS\n" "{\n" "// Enum test1\n" @@ -464,7 +481,7 @@ TEST_F(DefinitionBlockSeparatorTest, OpeningBracketOwnsLine) { TEST_F(DefinitionBlockSeparatorTest, TryBlocks) { FormatStyle Style = getLLVMStyle(); Style.BreakBeforeBraces = FormatStyle::BS_Allman; - Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always; + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; verifyFormat("void FunctionWithInternalTry()\n" "{\n" " try\n" @@ -540,7 +557,7 @@ TEST_F(DefinitionBlockSeparatorTest, Leave) { TEST_F(DefinitionBlockSeparatorTest, CSharp) { FormatStyle Style = getLLVMStyle(FormatStyle::LK_CSharp); - Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always; + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; Style.AllowShortEnumsOnASingleLine = false; verifyFormat("namespace {\r\n" @@ -581,7 +598,7 @@ TEST_F(DefinitionBlockSeparatorTest, CSharp) { TEST_F(DefinitionBlockSeparatorTest, JavaScript) { FormatStyle Style = getLLVMStyle(FormatStyle::LK_JavaScript); - Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always; + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; Style.AllowShortEnumsOnASingleLine = false; verifyFormat("export const enum Foo {\n" @@ -610,6 +627,113 @@ TEST_F(DefinitionBlockSeparatorTest, JavaScript) { "}", Style); } + +TEST_P(LicenseTest, SeparateLicenseFromBlock) { + constexpr StringRef LicenseSingleLineCommentStyle = {"// start license\n" + "// license text\n" + "// more license text\n" + "// end license\n"}; + constexpr StringRef LicenseMultipleLineCommentStyle{"/*\n" + "start license\n" + "license text\n" + "more license text\n" + "end license */\n"}; + + const auto Block = GetParam(); + FormatStyle Style = getLLVMStyle(); + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; + Style.MaxEmptyLinesToKeep = 2; + verifyFormat(LicenseSingleLineCommentStyle.str() + "\n" + Block, Style); + verifyFormat(LicenseMultipleLineCommentStyle.str() + "\n" + Block, Style); + + Style.SeparateDefinitionBlocks = FormatStyle::SDS_Two; + verifyFormat(LicenseSingleLineCommentStyle.str() + "\n\n" + Block, Style); + verifyFormat(LicenseMultipleLineCommentStyle.str() + "\n\n" + Block, Style); +} + +INSTANTIATE_TEST_SUITE_P( + DefinitionSeparator, LicenseTest, + ::testing::Values(std::string{"class Test {};"}, + std::string{"class Test {\n" + "public:\n" + " void test() const {}\n" + "};\n"}, + std::string{"namespace tests {};"}, + std::string{"static int variable = 10;"}, + std::string{"#ifnef __TEST__\n" + "#define __TEST__\n" + "#endif"})); + +TEST_P(IncludesTest, SeparateIncludeFromBlock) { + constexpr StringRef Includes = {"#include <string>\n" + "#include <cstdio>\n"}; + + const auto Block = GetParam(); + FormatStyle Style = getLLVMStyle(); + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; + Style.MaxEmptyLinesToKeep = 2; + verifyFormat(Includes.str() + "\n" + Block, Style); + + Style.SeparateDefinitionBlocks = FormatStyle::SDS_Two; + verifyFormat(Includes.str() + "\n\n" + Block, Style); +} + +INSTANTIATE_TEST_SUITE_P( + DefinitionSeparator, IncludesTest, + ::testing::Values(std::string{"class Test {};"}, + std::string{"class Test {\n" + "public:\n" + " void test() const {}\n" + "};\n"}, + std::string{"namespace tests {};"}, + std::string{"static int variable = 10;"}, + std::string{"#ifnef __TEST__\n" + "#define __TEST__\n" + "#endif"})); + +TEST_P(NoNewLineAtEofTest, NoNewLineAfterBlock) { + FormatStyle Style = getLLVMStyle(); + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; + Style.MaxEmptyLinesToKeep = 2; + const auto Code = GetParam(); + verifyFormat(Code, Style, Code, + /* Inverse = */ false); + + Style.SeparateDefinitionBlocks = FormatStyle::SDS_Two; + verifyFormat(Code, Style, Code, + /* Inverse = */ false); +} + +INSTANTIATE_TEST_SUITE_P(DefinitionSeparator, NoNewLineAtEofTest, + ::testing::Values(std::string{"// start license\n" + "// license text\n" + "// more license text\n" + "// end license\n"}, + std::string{"// start license"}, + std::string{"#include <string>"}, + std::string{"#include <string>\n" + "#include <cstdio>"})); + +TEST_F(DefinitionBlockSeparatorTest, + NoNewLinesWhenThereIsNoCodeAfterLicenseText) { + FormatStyle Style = getLLVMStyle(); + constexpr StringRef Code = {"// start license\n" + "// license text\n" + "// end license"}; + Style.SeparateDefinitionBlocks = FormatStyle::SDS_One; + verifyFormat(Code, Style, + "// start license\n" + "// license text\n" + "// end license", + /* Inverse = */ false); + + Style.SeparateDefinitionBlocks = FormatStyle::SDS_Two; + verifyFormat(Code, Style, + "// start license\n" + "// license text\n" + "// end license", + /* Inverse = */ false); +} } // namespace } // namespace format } // namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits