Author: Konrad Kleine Date: 2021-11-22T16:18:04Z New Revision: 07ef031d4abb6d1a277abf7549329ca9be7cf8c6
URL: https://github.com/llvm/llvm-project/commit/07ef031d4abb6d1a277abf7549329ca9be7cf8c6 DIFF: https://github.com/llvm/llvm-project/commit/07ef031d4abb6d1a277abf7549329ca9be7cf8c6.diff LOG: Work on EmptyLineAfterFunctionDefinition Added: Modified: clang/include/clang/Format/Format.h clang/lib/Format/Format.cpp clang/lib/Format/UnwrappedLineFormatter.cpp clang/unittests/Format/FormatTest.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index d38bc6e3f0e68..13d2e17380394 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2168,6 +2168,27 @@ struct FormatStyle { /// \version 13 EmptyLineBeforeAccessModifierStyle EmptyLineBeforeAccessModifier; + /// Different styles for empty line after function definitions. + enum EmptyLineAfterFunctionDefinitionStyle : unsigned char { + /// Keep existing empty lines after function definition. + /// MaxEmptyLinesToKeep is applied instead. + ELAFDS_Leave, + /// Always add empty line after function modifiers if there are none. + /// MaxEmptyLinesToKeep is applied also. + /// \code + /// void one() {} + /// + /// void two() {} + /// + /// void three() {} + /// \endcode + ELAFDS_Always, + }; + + /// Defines when to put an empty line after a function definition. + /// \version 14 + EmptyLineAfterFunctionDefinitionStyle EmptyLineAfterFunctionDefinition; + /// If ``true``, clang-format detects whether function calls and /// definitions are formatted with one parameter per line. /// @@ -3738,6 +3759,7 @@ struct FormatStyle { DisableFormat == R.DisableFormat && EmptyLineAfterAccessModifier == R.EmptyLineAfterAccessModifier && EmptyLineBeforeAccessModifier == R.EmptyLineBeforeAccessModifier && + EmptyLineAfterFunctionDefinition == R.EmptyLineAfterFunctionDefinition && ExperimentalAutoDetectBinPacking == R.ExperimentalAutoDetectBinPacking && PackConstructorInitializers == R.PackConstructorInitializers && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 1d60f2b3a321b..dc46531a9bc2b 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -308,6 +308,17 @@ struct ScalarEnumerationTraits< } }; +template <> +struct ScalarEnumerationTraits< + FormatStyle::EmptyLineAfterFunctionDefinitionStyle> { + static void + enumeration(IO &IO, + FormatStyle::EmptyLineAfterFunctionDefinitionStyle &Value) { + IO.enumCase(Value, "Leave", FormatStyle::ELAFDS_Leave); + IO.enumCase(Value, "Always", FormatStyle::ELAFDS_Always); + } +}; + template <> struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> { static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) { @@ -675,6 +686,8 @@ template <> struct MappingTraits<FormatStyle> { Style.EmptyLineAfterAccessModifier); IO.mapOptional("EmptyLineBeforeAccessModifier", Style.EmptyLineBeforeAccessModifier); + IO.mapOptional("EmptyLineAfterFunctionDefinition", + Style.EmptyLineAfterFunctionDefinition); IO.mapOptional("ExperimentalAutoDetectBinPacking", Style.ExperimentalAutoDetectBinPacking); @@ -1156,6 +1169,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.DerivePointerAlignment = false; LLVMStyle.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Never; LLVMStyle.EmptyLineBeforeAccessModifier = FormatStyle::ELBAMS_LogicalBlock; + LLVMStyle.EmptyLineAfterFunctionDefinition = FormatStyle::ELAFDS_Leave; LLVMStyle.ExperimentalAutoDetectBinPacking = false; LLVMStyle.PackConstructorInitializers = FormatStyle::PCIS_BinPack; LLVMStyle.FixNamespaceComments = true; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 299536cd806eb..1f7384c7dd847 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -1333,6 +1333,18 @@ void UnwrappedLineFormatter::formatFirstToken( } } + if (PreviousLine && PreviousLine->mightBeFunctionDefinition() && + (!PreviousLine->InPPDirective || !RootToken.HasUnescapedNewline)) { + switch (Style.EmptyLineAfterFunctionDefinition) { + case FormatStyle::ELAFDS_Leave: + Newlines = std::max(Newlines, 1u); + break; + case FormatStyle::ELAFDS_Always: + Newlines = std::max(Newlines, 2u); + break; + } + } + if (Newlines) Indent = NewlineIndent; diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 6507cbefc5a90..4a9a71393b4ff 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -11083,6 +11083,308 @@ TEST_F(FormatTest, FormatsAfterAndBeforeAccessModifiersInteraction) { Style); } +TEST_F(FormatTest, FormatsEmptyLineAfterFunctionDefinition) { + + FormatStyle Style = getLLVMStyle(); + EXPECT_EQ(Style.EmptyLineAfterFunctionDefinition, FormatStyle::ELAFDS_Leave); + // verifyFormat("void one() {}\n" + // "\n" + // "void two() {}\n" + // "void three() {}\n", + // Style); + + // // Check if lines are removed. + // verifyFormat("void one() {}\n" + // "void two() {}\n" + // "void three() {}\n", + // "void one() {}\n" + // "\n" + // "void two() {}\n" + // "void three() {}\n", + // Style); + + Style.EmptyLineAfterFunctionDefinition = FormatStyle::ELAFDS_Always; + verifyFormat("void one() {}\n" + "\n" + "void two() {}\n" + "\n" + "void three() {}\n" + "\n", + Style); + + // Check if lines are added. + verifyFormat("void one() {}\n" + "\n" + "void two() {}\n" + "\n" + "void three() {}\n" + "\n", + "void one() {}\n" + "void two() {}\n" + "void three() {}\n", + Style); + + // // Leave tests rely on the code layout, test::messUp can not be used. + // Style.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Leave; + // Style.MaxEmptyLinesToKeep = 0u; + // verifyFormat("struct foo {\n" + // "private:\n" + // " void f() {}\n" + // "\n" + // "private:\n" + // " int i;\n" + // "\n" + // "protected:\n" + // " int j;\n" + // "};\n", + // Style); + + // // Check if MaxEmptyLinesToKeep is respected. + // EXPECT_EQ("struct foo {\n" + // "private:\n" + // " void f() {}\n" + // "\n" + // "private:\n" + // " int i;\n" + // "\n" + // "protected:\n" + // " int j;\n" + // "};\n", + // format("struct foo {\n" + // "private:\n" + // "\n\n\n" + // " void f() {}\n" + // "\n" + // "private:\n" + // "\n\n\n" + // " int i;\n" + // "\n" + // "protected:\n" + // "\n\n\n" + // " int j;\n" + // "};\n", + // Style)); + + // Style.MaxEmptyLinesToKeep = 1u; + // EXPECT_EQ("struct foo {\n" + // "private:\n" + // "\n" + // " void f() {}\n" + // "\n" + // "private:\n" + // "\n" + // " int i;\n" + // "\n" + // "protected:\n" + // "\n" + // " int j;\n" + // "};\n", + // format("struct foo {\n" + // "private:\n" + // "\n" + // " void f() {}\n" + // "\n" + // "private:\n" + // "\n" + // " int i;\n" + // "\n" + // "protected:\n" + // "\n" + // " int j;\n" + // "};\n", + // Style)); + // // Check if no lines are kept. + // EXPECT_EQ("struct foo {\n" + // "private:\n" + // " void f() {}\n" + // "\n" + // "private:\n" + // " int i;\n" + // "\n" + // "protected:\n" + // " int j;\n" + // "};\n", + // format("struct foo {\n" + // "private:\n" + // " void f() {}\n" + // "\n" + // "private:\n" + // " int i;\n" + // "\n" + // "protected:\n" + // " int j;\n" + // "};\n", + // Style)); + // // Check if MaxEmptyLinesToKeep is respected. + // EXPECT_EQ("struct foo {\n" + // "private:\n" + // "\n" + // " void f() {}\n" + // "\n" + // "private:\n" + // "\n" + // " int i;\n" + // "\n" + // "protected:\n" + // "\n" + // " int j;\n" + // "};\n", + // format("struct foo {\n" + // "private:\n" + // "\n\n\n" + // " void f() {}\n" + // "\n" + // "private:\n" + // "\n\n\n" + // " int i;\n" + // "\n" + // "protected:\n" + // "\n\n\n" + // " int j;\n" + // "};\n", + // Style)); + + // Style.MaxEmptyLinesToKeep = 10u; + // EXPECT_EQ("struct foo {\n" + // "private:\n" + // "\n\n\n" + // " void f() {}\n" + // "\n" + // "private:\n" + // "\n\n\n" + // " int i;\n" + // "\n" + // "protected:\n" + // "\n\n\n" + // " int j;\n" + // "};\n", + // format("struct foo {\n" + // "private:\n" + // "\n\n\n" + // " void f() {}\n" + // "\n" + // "private:\n" + // "\n\n\n" + // " int i;\n" + // "\n" + // "protected:\n" + // "\n\n\n" + // " int j;\n" + // "};\n", + // Style)); + + // // Test with comments. + // Style = getLLVMStyle(); + // verifyFormat("struct foo {\n" + // "private:\n" + // " // comment\n" + // " void f() {}\n" + // "\n" + // "private: /* comment */\n" + // " int i;\n" + // "};\n", + // Style); + // verifyFormat("struct foo {\n" + // "private:\n" + // " // comment\n" + // " void f() {}\n" + // "\n" + // "private: /* comment */\n" + // " int i;\n" + // "};\n", + // "struct foo {\n" + // "private:\n" + // "\n" + // " // comment\n" + // " void f() {}\n" + // "\n" + // "private: /* comment */\n" + // "\n" + // " int i;\n" + // "};\n", + // Style); + + // Style.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Always; + // verifyFormat("struct foo {\n" + // "private:\n" + // "\n" + // " // comment\n" + // " void f() {}\n" + // "\n" + // "private: /* comment */\n" + // "\n" + // " int i;\n" + // "};\n", + // "struct foo {\n" + // "private:\n" + // " // comment\n" + // " void f() {}\n" + // "\n" + // "private: /* comment */\n" + // " int i;\n" + // "};\n", + // Style); + // verifyFormat("struct foo {\n" + // "private:\n" + // "\n" + // " // comment\n" + // " void f() {}\n" + // "\n" + // "private: /* comment */\n" + // "\n" + // " int i;\n" + // "};\n", + // Style); + + // // Test with preprocessor defines. + // Style = getLLVMStyle(); + // verifyFormat("struct foo {\n" + // "private:\n" + // "#ifdef FOO\n" + // "#endif\n" + // " void f() {}\n" + // "};\n", + // Style); + // verifyFormat("struct foo {\n" + // "private:\n" + // "#ifdef FOO\n" + // "#endif\n" + // " void f() {}\n" + // "};\n", + // "struct foo {\n" + // "private:\n" + // "\n" + // "#ifdef FOO\n" + // "#endif\n" + // " void f() {}\n" + // "};\n", + // Style); + + // Style.EmptyLineAfterAccessModifier = FormatStyle::ELAAMS_Always; + // verifyFormat("struct foo {\n" + // "private:\n" + // "\n" + // "#ifdef FOO\n" + // "#endif\n" + // " void f() {}\n" + // "};\n", + // "struct foo {\n" + // "private:\n" + // "#ifdef FOO\n" + // "#endif\n" + // " void f() {}\n" + // "};\n", + // Style); + // verifyFormat("struct foo {\n" + // "private:\n" + // "\n" + // "#ifdef FOO\n" + // "#endif\n" + // " void f() {}\n" + // "};\n", + // Style); +} + TEST_F(FormatTest, FormatsArrays) { verifyFormat("aaaaaaaaaaaaaaaaaaaaaaaaa[aaaaaaaaaaaaaaaaaaaaaaaaa]\n" " [bbbbbbbbbbbbbbbbbbbbbbbbb] = c;"); _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits