diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2421,6 +2421,17 @@ f(MyMap[{composite, key}]); f(MyMap[{ composite, key }]); new int[3]{1, 2, 3}; new int[3]{ 1, 2, 3 }; +**DefinitionBlockSpacing** (``Unsigned``) :versionbadge:`clang-format 16` + The number of empty lines to use when separating definition blocks. + Defaults to 1. + + This determines the number of empty lines to use when + SeparateDefinitionBlocks == SeparateDefinitionStyle::SDS_Always. + + Note: if MaxEmptyLinesToKeep < DefinitionBlockSpacing, then additional + lines will be removed. MaxEmptyLinesToKeep should be greater than or equal + to DefinitionBlockSpacing. + **DeriveLineEnding** (``Boolean``) :versionbadge:`clang-format 10` Analyze the formatted file for the most used line ending (``\r\n`` or ``\n``). ``UseCRLF`` is only used as a fallback if none can be derived. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1927,6 +1927,18 @@ /// \version 3.4 bool Cpp11BracedListStyle; + /// The number of empty lines to use when separating definition blocks. + /// Defaults to 1. + /// + /// This determines the number of empty lines to use when + /// SeparateDefinitionBlocks == SeparateDefinitionStyle::SDS_Always. + /// + /// Note: if MaxEmptyLinesToKeep < DefinitionBlockSpacing, then additional + /// lines will be removed. MaxEmptyLinesToKeep should be greater than or equal + /// to DefinitionBlockSpacing. + /// \version 16 + unsigned DefinitionBlockSpacing; + /// \brief Analyze the formatted file for the most used line ending (``\r\n`` /// or ``\n``). ``UseCRLF`` is only used as a fallback if none can be derived. /// \version 10 @@ -3892,6 +3904,7 @@ R.ConstructorInitializerIndentWidth && ContinuationIndentWidth == R.ContinuationIndentWidth && Cpp11BracedListStyle == R.Cpp11BracedListStyle && + DefinitionBlockSpacing == R.DefinitionBlockSpacing && DeriveLineEnding == R.DeriveLineEnding && DerivePointerAlignment == R.DerivePointerAlignment && DisableFormat == R.DisableFormat && diff --git a/clang/lib/Format/DefinitionBlockSeparator.cpp b/clang/lib/Format/DefinitionBlockSeparator.cpp --- a/clang/lib/Format/DefinitionBlockSeparator.cpp +++ b/clang/lib/Format/DefinitionBlockSeparator.cpp @@ -66,7 +66,9 @@ return false; }; unsigned NewlineCount = - (Style.SeparateDefinitionBlocks == FormatStyle::SDS_Always ? 1 : 0) + 1; + 1 + (Style.SeparateDefinitionBlocks == FormatStyle::SDS_Always + ? Style.DefinitionBlockSpacing + : 0); WhitespaceManager Whitespaces( Env.getSourceManager(), Style, Style.DeriveLineEnding diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -746,6 +746,7 @@ Style.ConstructorInitializerIndentWidth); IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth); IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle); + IO.mapOptional("DefinitionBlockSpacing", Style.DefinitionBlockSpacing); IO.mapOptional("DeriveLineEnding", Style.DeriveLineEnding); IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment); IO.mapOptional("DisableFormat", Style.DisableFormat); @@ -1244,6 +1245,7 @@ // Off by default Qualifier ordering LLVMStyle.QualifierAlignment = FormatStyle::QAS_Leave; + LLVMStyle.DefinitionBlockSpacing = 1; LLVMStyle.DeriveLineEnding = true; LLVMStyle.DerivePointerAlignment = false; LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; diff --git a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp --- a/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp +++ b/clang/unittests/Format/DefinitionBlockSeparatorTest.cpp @@ -601,6 +601,90 @@ "}", Style); } + +TEST_F(DefinitionBlockSeparatorTest, DefinitionBlockSpacing) { + FormatStyle Style = getLLVMStyle(); + Style.SeparateDefinitionBlocks = FormatStyle::SDS_Always; + Style.DefinitionBlockSpacing = 2; + /// This has to be set, otherwise the extra lines will be removed + Style.MaxEmptyLinesToKeep = 2; + verifyFormat("int foo(int i, int j) {\n" + " int r = i + j;\n" + " return r;\n" + "}\n" + "\n" + "\n" + "int bar(int j, int k) {\n" + " int r = j + k;\n" + " return r;\n" + "}", + Style); + + verifyFormat("struct foo {\n" + " int i, j;\n" + "};\n" + "\n" + "\n" + "struct bar {\n" + " int j, k;\n" + "};", + Style); + + verifyFormat("union foo {\n" + " int i, j;\n" + "};\n" + "\n" + "\n" + "union bar {\n" + " int j, k;\n" + "};", + Style); + + verifyFormat("class foo {\n" + " int i, j;\n" + "};\n" + "\n" + "\n" + "class bar {\n" + " int j, k;\n" + "};", + Style); + + verifyFormat("namespace foo {\n" + "int i, j;\n" + "}\n" + "\n" + "\n" + "namespace bar {\n" + "int j, k;\n" + "}", + Style); + + verifyFormat("enum Foo { FOO, BAR };\n" + "\n" + "\n" + "enum Bar { FOOBAR, BARFOO };\n", + Style); + + FormatStyle BreakAfterReturnTypeStyle = Style; + BreakAfterReturnTypeStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_All; + // Test uppercased long typename + verifyFormat("class Foo {\n" + " void\n" + " Bar(int t, int p) {\n" + " int r = t + p;\n" + " return r;\n" + " }\n" + "\n" + "\n" + " HRESULT\n" + " Foobar(int t, int p) {\n" + " int r = t * p;\n" + " return r;\n" + " }\n" + "}\n", + BreakAfterReturnTypeStyle); +} } // namespace } // namespace format } // namespace clang