From: Francois Ferrand Date: Tue, 13 Jun 2017 07:02:43 +0000 (+0000) Subject: clang-format: add option to merge empty function body X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3e1f3e75d998c8f82cea7d1aab6c0137634575c6;p=clang clang-format: add option to merge empty function body Summary: This option supplements the AllowShortFunctionsOnASingleLine flag, to merge empty function body at the beginning of the line: e.g. when the function is not short-enough and breaking braces after function. int f() {} Reviewers: krasimir, djasper Reviewed By: djasper Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D33447 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@305272 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 7ec3e22ca4..4081e2131c 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -688,6 +688,18 @@ struct FormatStyle { bool BeforeElse; /// \brief Indent the wrapped braces themselves. bool IndentBraces; + /// \brief If ``false``, empty function body can be put on a single line. + /// This option is used only if the opening brace of the function has + /// already been wrapped, i.e. the `AfterFunction` brace wrapping mode is + /// set, and the function could/should not be put on a single line (as per + /// `AllowShortFunctionsOnASingleLine` and constructor formatting options). + /// \code + /// int f() vs. inf f() + /// {} { + /// } + /// \endcode + /// + bool SplitEmptyFunctionBody; }; /// \brief Control of individual brace wrapping cases. diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 2ef6516e02..0eaf44d204 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -410,6 +410,7 @@ template <> struct MappingTraits { IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); IO.mapOptional("BeforeElse", Wrapping.BeforeElse); IO.mapOptional("IndentBraces", Wrapping.IndentBraces); + IO.mapOptional("SplitEmptyFunctionBody", Wrapping.SplitEmptyFunctionBody); } }; @@ -485,7 +486,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { return Style; FormatStyle Expanded = Style; Expanded.BraceWrapping = {false, false, false, false, false, false, - false, false, false, false, false}; + false, false, false, false, false, true}; switch (Style.BreakBeforeBraces) { case FormatStyle::BS_Linux: Expanded.BraceWrapping.AfterClass = true; @@ -498,6 +499,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { Expanded.BraceWrapping.AfterFunction = true; Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterUnion = true; + Expanded.BraceWrapping.SplitEmptyFunctionBody = false; break; case FormatStyle::BS_Stroustrup: Expanded.BraceWrapping.AfterFunction = true; @@ -517,7 +519,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { break; case FormatStyle::BS_GNU: Expanded.BraceWrapping = {true, true, true, true, true, true, - true, true, true, true, true}; + true, true, true, true, true, true}; break; case FormatStyle::BS_WebKit: Expanded.BraceWrapping.AfterFunction = true; @@ -554,7 +556,7 @@ FormatStyle getLLVMStyle() { LLVMStyle.BreakBeforeTernaryOperators = true; LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; LLVMStyle.BraceWrapping = {false, false, false, false, false, false, - false, false, false, false, false}; + false, false, false, false, false, true}; LLVMStyle.BreakAfterJavaFieldAnnotations = false; LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; LLVMStyle.BreakBeforeInheritanceComma = false; diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp index 01504da0a2..eb8de6598e 100644 --- a/lib/Format/UnwrappedLineFormatter.cpp +++ b/lib/Format/UnwrappedLineFormatter.cpp @@ -186,6 +186,12 @@ private: ? 0 : Limit - TheLine->Last->TotalLength; + if (TheLine->Last->is(TT_FunctionLBrace) && + TheLine->First == TheLine->Last && + !Style.BraceWrapping.SplitEmptyFunctionBody && + I[1]->First->is(tok::r_brace)) + return tryMergeSimpleBlock(I, E, Limit); + // FIXME: TheLine->Level != 0 might or might not be the right check to do. // If necessary, change to something smarter. bool MergeShortFunctions = @@ -215,7 +221,10 @@ private: Limit -= 2; unsigned MergedLines = 0; - if (MergeShortFunctions) { + if (MergeShortFunctions || + (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty && + I[1]->First == I[1]->Last && I + 2 != E && + I[2]->First->is(tok::r_brace))) { MergedLines = tryMergeSimpleBlock(I + 1, E, Limit); // If we managed to merge the block, count the function header, which is // on a separate line. diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 64e963db4c..783fe45042 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -6239,6 +6239,35 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) { getLLVMStyleWithColumns(23)); } +TEST_F(FormatTest, PullEmptyFunctionDefinitionsIntoSingleLine) { + FormatStyle MergeEmptyOnly = getLLVMStyle(); + MergeEmptyOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + verifyFormat("class C {\n" + " int f() {}\n" + "};", + MergeEmptyOnly); + verifyFormat("class C {\n" + " int f() {\n" + " return 42;\n" + " }\n" + "};", + MergeEmptyOnly); + verifyFormat("int f() {}", MergeEmptyOnly); + verifyFormat("int f() {\n" + " return 42;\n" + "}", + MergeEmptyOnly); + + // Also verify behavior when BraceWrapping.AfterFunction = true + MergeEmptyOnly.BreakBeforeBraces = FormatStyle::BS_Custom; + MergeEmptyOnly.BraceWrapping.AfterFunction = true; + verifyFormat("int f() {}", MergeEmptyOnly); + verifyFormat("class C {\n" + " int f() {}\n" + "};", + MergeEmptyOnly); +} + TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) { FormatStyle MergeInlineOnly = getLLVMStyle(); MergeInlineOnly.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; @@ -6250,6 +6279,101 @@ TEST_F(FormatTest, PullInlineFunctionDefinitionsIntoSingleLine) { " return 42;\n" "}", MergeInlineOnly); + + // SFS_Inline implies SFS_Empty + verifyFormat("class C {\n" + " int f() {}\n" + "};", + MergeInlineOnly); + verifyFormat("int f() {}", MergeInlineOnly); + + // Also verify behavior when BraceWrapping.AfterFunction = true + MergeInlineOnly.BreakBeforeBraces = FormatStyle::BS_Custom; + MergeInlineOnly.BraceWrapping.AfterFunction = true; + verifyFormat("class C {\n" + " int f() { return 42; }\n" + "};", + MergeInlineOnly); + verifyFormat("int f()\n" + "{\n" + " return 42;\n" + "}", + MergeInlineOnly); + + // SFS_Inline implies SFS_Empty + verifyFormat("int f() {}", MergeInlineOnly); + verifyFormat("class C {\n" + " int f() {}\n" + "};", + MergeInlineOnly); +} + +TEST_F(FormatTest, SplitEmptyFunctionBody) { + FormatStyle Style = getLLVMStyle(); + Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None; + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterFunction = true; + Style.BraceWrapping.SplitEmptyFunctionBody = false; + Style.ColumnLimit = 40; + + verifyFormat("int f()\n" + "{}", + Style); + verifyFormat("int f()\n" + "{\n" + " return 42;\n" + "}", + Style); + verifyFormat("int f()\n" + "{\n" + " // some comment\n" + "}", + Style); + + Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty; + verifyFormat("int f() {}", Style); + verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" + "{}", + Style); + verifyFormat("int f()\n" + "{\n" + " return 0;\n" + "}", + Style); + + Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline; + verifyFormat("class Foo {\n" + " int f() {}\n" + "};\n", + Style); + verifyFormat("class Foo {\n" + " int f() { return 0; }\n" + "};\n", + Style); + verifyFormat("class Foo {\n" + " int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" + " {}\n" + "};\n", + Style); + verifyFormat("class Foo {\n" + " int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" + " {\n" + " return 0;\n" + " }\n" + "};\n", + Style); + + Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; + verifyFormat("int f() {}", Style); + verifyFormat("int f() { return 0; }", Style); + verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" + "{}", + Style); + verifyFormat("int aaaaaaaaaaaaaa(int bbbbbbbbbbbbbb)\n" + "{\n" + " return 0;\n" + "}", + Style); } TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) { @@ -8960,6 +9084,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeCatch); CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeElse); CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces); + CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunctionBody); } #undef CHECK_PARSE_BOOL