https://github.com/dmasloff updated https://github.com/llvm/llvm-project/pull/106145
>From 219424f9cd3477d9290c8766eaa857234a1ae387 Mon Sep 17 00:00:00 2001 From: dmasloff <dmaslo...@gmail.com> Date: Mon, 26 Aug 2024 22:11:05 +0300 Subject: [PATCH 1/6] [clang-format] Add new option: WrapNamespaceBodyWithNewlines --- clang/docs/ClangFormatStyleOptions.rst | 42 ++++ clang/include/clang/Format/Format.h | 40 +++- clang/lib/Format/Format.cpp | 15 ++ clang/lib/Format/UnwrappedLineFormatter.cpp | 42 ++++ clang/unittests/Format/FormatTest.cpp | 205 ++++++++++++++++++++ 5 files changed, 343 insertions(+), 1 deletion(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index a427d7cd40fcdd..06ac88fc337983 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -6652,6 +6652,48 @@ the configuration (without a prefix: ``Auto``). For example: BOOST_PP_STRINGIZE +.. _WrapNamespaceBodyWithEmptyLines: + +**WrapNamespaceBodyWithEmptyLines** (``WrapNamespaceBodyWithEmptyLinesStyle``) :versionbadge:`clang-format 19` :ref:`¶ <WrapNamespaceBodyWithEmptyLines>` + Controls number of empty lines at the begging and at the end of + namespace definition. + + Possible values: + + * ``WNBWELS_Never`` (in configuration: ``Never``) + Removes all empty lines at the beginning and at the end of + namespace definition. + + .. code-block:: c++ + + namespace N1 { + namespace N2 + function(); + } + } + + * ``WNBWELS_Always`` (in configuration: ``Always``) + Always adds an empty line at the beginning and at the end of + namespace definition. MaxEmptyLinesToKeep is also applied, but + empty lines between consecutive namespace declarations are + always removed. + + .. code-block:: c++ + + namespace N1 { + namespace N2 { + + function(); + + } + } + + * ``WNBWELS_Leave`` (in configuration: ``Leave``) + Keeps existing newlines at the beginning and at the end of + namespace definition using MaxEmptyLinesToKeep for formatting. + + + .. END_FORMAT_STYLE_OPTIONS Adding additional style options diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index d8b62c7652a0f6..963c7cbe1f8809 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -5057,6 +5057,43 @@ struct FormatStyle { /// \version 11 std::vector<std::string> WhitespaceSensitiveMacros; + /// Different styles for modify number of empty lines in + /// the beginning and at the of end of namespaces. + enum WrapNamespaceBodyWithEmptyLinesStyle : int8_t { + /// Removes all empty lines at the beginning and at the end of + /// namespace definition. + /// \code + /// namespace N1 { + /// namespace N2 + /// function(); + /// } + /// } + /// \endcode + WNBWELS_Never, + /// Always adds an empty line at the beginning and at the end of + /// namespace definition. MaxEmptyLinesToKeep is also applied, but + /// empty lines between consecutive namespace declarations are + /// always removed. + /// \code + /// namespace N1 { + /// namespace N2 { + /// + /// function(); + /// + /// } + /// } + /// \endcode + WNBWELS_Always, + /// Keeps existing newlines at the beginning and at the end of + /// namespace definition using MaxEmptyLinesToKeep for formatting. + WNBWELS_Leave + }; + + /// Controls number of empty lines at the begging and at the end of + /// namespace definition. + /// \version 19 + WrapNamespaceBodyWithEmptyLinesStyle WrapNamespaceBodyWithEmptyLines; + bool operator==(const FormatStyle &R) const { return AccessModifierOffset == R.AccessModifierOffset && AlignAfterOpenBracket == R.AlignAfterOpenBracket && @@ -5234,7 +5271,8 @@ struct FormatStyle { TypenameMacros == R.TypenameMacros && UseTab == R.UseTab && VerilogBreakBetweenInstancePorts == R.VerilogBreakBetweenInstancePorts && - WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros; + WhitespaceSensitiveMacros == R.WhitespaceSensitiveMacros && + WrapNamespaceBodyWithEmptyLines == R.WrapNamespaceBodyWithEmptyLines; } std::optional<FormatStyle> GetLanguageStyle(LanguageKind Language) const; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index d2463b892fbb96..b0d2836e9c69c2 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -829,6 +829,18 @@ template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> { } }; +template <> +struct ScalarEnumerationTraits< + FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle> { + static void + enumeration(IO &IO, + FormatStyle::WrapNamespaceBodyWithEmptyLinesStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::WNBWELS_Never); + IO.enumCase(Value, "Always", FormatStyle::WNBWELS_Always); + IO.enumCase(Value, "Leave", FormatStyle::WNBWELS_Leave); + } +}; + template <> struct MappingTraits<FormatStyle> { static void mapping(IO &IO, FormatStyle &Style) { // When reading, read the language first, we need it for getPredefinedStyle. @@ -1154,6 +1166,8 @@ template <> struct MappingTraits<FormatStyle> { Style.VerilogBreakBetweenInstancePorts); IO.mapOptional("WhitespaceSensitiveMacros", Style.WhitespaceSensitiveMacros); + IO.mapOptional("WrapNamespaceBodyWithEmptyLines", + Style.WrapNamespaceBodyWithEmptyLines); // If AlwaysBreakAfterDefinitionReturnType was specified but // BreakAfterReturnType was not, initialize the latter from the former for @@ -1623,6 +1637,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.WhitespaceSensitiveMacros.push_back("NS_SWIFT_NAME"); LLVMStyle.WhitespaceSensitiveMacros.push_back("PP_STRINGIZE"); LLVMStyle.WhitespaceSensitiveMacros.push_back("STRINGIZE"); + LLVMStyle.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave; LLVMStyle.PenaltyBreakAssignment = prec::Assignment; LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 1804c1437fd41d..e50f62b49acbcc 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -32,6 +32,26 @@ bool isRecordLBrace(const FormatToken &Tok) { TT_StructLBrace, TT_UnionLBrace); } +bool LineStartsNamespaceScope(const AnnotatedLine *Line, + const AnnotatedLine *PreviousLine, + const AnnotatedLine *PrevPrevLine) { + return PreviousLine && + ((PreviousLine->Last->is(tok::l_brace) && + PreviousLine->startsWithNamespace()) || + (PrevPrevLine && PrevPrevLine->startsWithNamespace() && + PreviousLine->startsWith(tok::l_brace))); +} + +bool LineEndsNamespaceScope(const AnnotatedLine *Line, + const SmallVectorImpl<AnnotatedLine *> &Lines) { + if (!Line) + return false; + const FormatToken *tok = Line->First; + if (!tok || tok->isNot(tok::r_brace)) + return false; + return getNamespaceToken(Line, Lines) != nullptr; +} + /// Tracks the indent level of \c AnnotatedLines across levels. /// /// \c nextLine must be called for each \c AnnotatedLine, after which \c @@ -1493,6 +1513,28 @@ static auto computeNewlines(const AnnotatedLine &Line, Newlines = 1; } + // Modify empty lines after "{" that opens namespace scope. + if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave && + LineStartsNamespaceScope(&Line, PreviousLine, PrevPrevLine)) { + if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never) + Newlines = std::min(Newlines, 1u); + else if (!Line.startsWithNamespace()) + Newlines = std::max(Newlines, 2u); + else + Newlines = std::min(Newlines, 1u); + } + + // Modify empty lines before "}" that closes namespace scope. + if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave && + LineEndsNamespaceScope(&Line, Lines)) { + if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never) + Newlines = std::min(Newlines, 1u); + else if (!LineEndsNamespaceScope(PreviousLine, Lines)) + Newlines = std::max(Newlines, 2u); + else + Newlines = std::min(Newlines, 1u); + } + // Insert or remove empty line before access specifiers. if (PreviousLine && RootToken.isAccessSpecifier()) { switch (Style.EmptyLineBeforeAccessModifier) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index a383a624434b1f..afb56add0c32ba 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -28084,6 +28084,211 @@ TEST_F(FormatTest, BreakBinaryOperations) { Style); } +TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesNever) { + FormatStyle Style = getLLVMStyle(); + Style.FixNamespaceComments = false; + Style.ShortNamespaceLines = 0; + Style.MaxEmptyLinesToKeep = 2; + Style.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Never; + Style.CompactNamespaces = false; + + // Empty namespace + verifyNoChange("namespace N {};", Style); + + // Single namespace + verifyNoChange("namespace N {\n" + "int f1(int a) { return 2 * a; }\n" + "};", + Style); + + // Nested namespace + verifyNoChange("namespace N1 {\n" + "namespace N2 {\n" + "namespace N3 {\n" + "int f1() {\n" + " int a = 1;\n" + " return a;\n" + "}\n" + "}\n" + "}\n" + "}", + Style); + + Style.CompactNamespaces = true; + + // Empty namespace + verifyNoChange("namespace N {\n};", Style); + + // Single namespace + verifyNoChange("namespace N {\n" + "int f1(int a) { return 2 * a; }\n" + "};", + Style); + + // Nested namespace + verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n" + "int f1() {\n" + " int a = 1;\n" + " return a;\n" + "}\n" + "}}}", + Style); +} + +TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesAlways) { + FormatStyle Style = getLLVMStyle(); + Style.FixNamespaceComments = false; + Style.ShortNamespaceLines = 0; + Style.MaxEmptyLinesToKeep = 0; + Style.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Always; + Style.CompactNamespaces = false; + + // Empty namespace + verifyNoChange("namespace N {};", Style); + + // Single namespace + verifyNoChange("namespace N {\n\n" + "int f1(int a) { return 2 * a; }\n\n" + "};", + Style); + + // Nested namespace + verifyNoChange("namespace N1 {\n" + "namespace N2 {\n" + "namespace N3 {\n\n" + "int f1() {\n" + " int a = 1;\n" + " return a;\n" + "}\n\n" + "}\n" + "}\n" + "}", + Style); + + Style.CompactNamespaces = true; + + // Nested namespace + verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n\n" + "int f1() {\n" + " int a = 1;\n" + " return a;\n" + "}\n\n" + "}}}", + Style); + + Style.MaxEmptyLinesToKeep = 2; + Style.CompactNamespaces = false; + + // Empty namespace + verifyNoChange("namespace N {};", Style); + + // Single namespace + verifyNoChange("namespace N {\n\n\n" + "void function()\n\n\n" + "};", + Style); + + // Nested namespace + verifyFormat("namespace N1 {\n" + "namespace N2 {\n" + "namespace N3 {\n\n\n" + "int f1() {\n" + " int a = 1;\n" + " return a;\n" + "}\n\n\n" + "}\n" + "}\n" + "}", + "namespace N1 {\n" + "namespace N2 {\n\n" + "namespace N3 {\n\n\n" + "int f1() {\n" + " int a = 1;\n" + " return a;\n" + "}\n\n\n" + "}\n\n" + "}\n" + "}", + Style); + + Style.CompactNamespaces = true; + + // Nested namespace + verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n\n\n" + "int f1() {\n" + " int a = 1;\n" + " return a;\n" + "}\n\n\n" + "}}}", + Style); +} + +TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesLeave) { + FormatStyle Style = getLLVMStyle(); + Style.FixNamespaceComments = false; + Style.ShortNamespaceLines = 0; + Style.MaxEmptyLinesToKeep = 0; + Style.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave; + Style.CompactNamespaces = false; + + // Empty namespace + verifyNoChange("namespace N {};", Style); + + // Single namespace + verifyNoChange("namespace N {\n" + "int f1(int a) { return 2 * a; }\n" + "};", + Style); + + // Nested namespace + verifyNoChange("namespace N1 {\n" + "namespace N2 {\n" + "namespace N3 {\n" + "int f1() {\n" + " int a = 1;\n" + " return a;\n" + "}\n" + "}\n" + "}\n" + "}", + Style); + + Style.MaxEmptyLinesToKeep = 2; + + // Single namespace + verifyNoChange("namespace N {\n\n\n" + "int f1(int a) { return 2 * a; }\n\n\n" + "};", + Style); + + // Nested namespace + verifyNoChange("namespace N1 {\n" + "namespace N2 {\n\n" + "namespace N3 {\n\n\n" + "int f1() {\n" + " int a = 1;\n" + " return a;\n" + "}\n\n\n" + "}\n\n" + "}\n" + "}", + Style); + + Style.CompactNamespaces = true; + + // Empty namespace + verifyNoChange("namespace N {\n};", Style); + + // Nested namespace + verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n\n\n" + "int f1() {\n" + " int a = 1;\n" + " return a;\n" + "}\n\n\n" + "}}}", + Style); +} + } // namespace } // namespace test } // namespace format >From bf76cbe3571a670b37be02eb4dd4634b673fad00 Mon Sep 17 00:00:00 2001 From: dmasloff <dmaslo...@gmail.com> Date: Mon, 2 Sep 2024 16:50:47 +0300 Subject: [PATCH 2/6] FormatTests update --- clang/unittests/Format/FormatTest.cpp | 90 +++++++++++++++++++-------- 1 file changed, 65 insertions(+), 25 deletions(-) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index b39b86b7e2d3f5..0b833bd240e80c 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -28137,7 +28137,9 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesNever) { Style.CompactNamespaces = true; // Empty namespace - verifyNoChange("namespace N {\n};", Style); + verifyNoChange("namespace N {\n" + "};", + Style); // Single namespace verifyNoChange("namespace N {\n" @@ -28167,19 +28169,23 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesAlways) { verifyNoChange("namespace N {};", Style); // Single namespace - verifyNoChange("namespace N {\n\n" - "int f1(int a) { return 2 * a; }\n\n" + verifyNoChange("namespace N {\n" + "\n" + "int f1(int a) { return 2 * a; }\n" + "\n" "};", Style); // Nested namespace verifyNoChange("namespace N1 {\n" "namespace N2 {\n" - "namespace N3 {\n\n" + "namespace N3 {\n" + "\n" "int f1() {\n" " int a = 1;\n" " return a;\n" - "}\n\n" + "}\n" + "\n" "}\n" "}\n" "}", @@ -28188,11 +28194,13 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesAlways) { Style.CompactNamespaces = true; // Nested namespace - verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n\n" + verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n" + "\n" "int f1() {\n" " int a = 1;\n" " return a;\n" - "}\n\n" + "}\n" + "\n" "}}}", Style); @@ -28203,30 +28211,44 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesAlways) { verifyNoChange("namespace N {};", Style); // Single namespace - verifyNoChange("namespace N {\n\n\n" - "void function()\n\n\n" + verifyNoChange("namespace N {\n" + "\n" + "\n" + "void function()\n" + "\n" + "\n" "};", Style); // Nested namespace verifyFormat("namespace N1 {\n" "namespace N2 {\n" - "namespace N3 {\n\n\n" + "namespace N3 {\n" + "\n" + "\n" "int f1() {\n" " int a = 1;\n" " return a;\n" - "}\n\n\n" + "}\n" + "\n" + "\n" "}\n" "}\n" "}", "namespace N1 {\n" - "namespace N2 {\n\n" - "namespace N3 {\n\n\n" + "namespace N2 {\n" + "\n" + "namespace N3 {\n" + "\n" + "\n" "int f1() {\n" " int a = 1;\n" " return a;\n" - "}\n\n\n" - "}\n\n" + "}\n" + "\n" + "\n" + "}\n" + "\n" "}\n" "}", Style); @@ -28234,11 +28256,15 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesAlways) { Style.CompactNamespaces = true; // Nested namespace - verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n\n\n" + verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n" + "\n" + "\n" "int f1() {\n" " int a = 1;\n" " return a;\n" - "}\n\n\n" + "}\n" + "\n" + "\n" "}}}", Style); } @@ -28276,20 +28302,30 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesLeave) { Style.MaxEmptyLinesToKeep = 2; // Single namespace - verifyNoChange("namespace N {\n\n\n" - "int f1(int a) { return 2 * a; }\n\n\n" + verifyNoChange("namespace N {\n" + "\n" + "\n" + "int f1(int a) { return 2 * a; }\n" + "\n" + "\n" "};", Style); // Nested namespace verifyNoChange("namespace N1 {\n" - "namespace N2 {\n\n" - "namespace N3 {\n\n\n" + "namespace N2 {\n" + "\n" + "namespace N3 {\n" + "\n" + "\n" "int f1() {\n" " int a = 1;\n" " return a;\n" - "}\n\n\n" - "}\n\n" + "}\n" + "\n" + "\n" + "}\n" + "\n" "}\n" "}", Style); @@ -28300,11 +28336,15 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesLeave) { verifyNoChange("namespace N {\n};", Style); // Nested namespace - verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n\n\n" + verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n" + "\n" + "\n" "int f1() {\n" " int a = 1;\n" " return a;\n" - "}\n\n\n" + "}\n" + "\n" + "\n" "}}}", Style); } >From 4dc769cfd1bd9bf39ef892e40c87cfdbc039a4fb Mon Sep 17 00:00:00 2001 From: dmasloff <dmaslo...@gmail.com> Date: Tue, 3 Sep 2024 23:54:25 +0300 Subject: [PATCH 3/6] ConfigParseTest added for new option + minor code-style fixes --- clang/docs/ClangFormatStyleOptions.rst | 2 +- clang/include/clang/Format/Format.h | 2 +- clang/lib/Format/UnwrappedLineFormatter.cpp | 4 ++-- clang/unittests/Format/ConfigParseTest.cpp | 8 ++++++++ 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 06ac88fc337983..b21ebfa2fb9d7b 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -6654,7 +6654,7 @@ the configuration (without a prefix: ``Auto``). .. _WrapNamespaceBodyWithEmptyLines: -**WrapNamespaceBodyWithEmptyLines** (``WrapNamespaceBodyWithEmptyLinesStyle``) :versionbadge:`clang-format 19` :ref:`¶ <WrapNamespaceBodyWithEmptyLines>` +**WrapNamespaceBodyWithEmptyLines** (``WrapNamespaceBodyWithEmptyLinesStyle``) :versionbadge:`clang-format 20` :ref:`¶ <WrapNamespaceBodyWithEmptyLines>` Controls number of empty lines at the begging and at the end of namespace definition. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 963c7cbe1f8809..daa27d4df920d3 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -5091,7 +5091,7 @@ struct FormatStyle { /// Controls number of empty lines at the begging and at the end of /// namespace definition. - /// \version 19 + /// \version 20 WrapNamespaceBodyWithEmptyLinesStyle WrapNamespaceBodyWithEmptyLines; bool operator==(const FormatStyle &R) const { diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index e50f62b49acbcc..92fddd9e62bcb0 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -46,8 +46,8 @@ bool LineEndsNamespaceScope(const AnnotatedLine *Line, const SmallVectorImpl<AnnotatedLine *> &Lines) { if (!Line) return false; - const FormatToken *tok = Line->First; - if (!tok || tok->isNot(tok::r_brace)) + const FormatToken *Tok = Line->First; + if (!Tok || Tok->isNot(tok::r_brace)) return false; return getNamespaceToken(Line, Lines) != nullptr; } diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index b8bdfaaa74e10e..b505d9275d8341 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -848,6 +848,14 @@ TEST(ConfigParseTest, ParsesConfiguration) { CHECK_PARSE("SortUsingDeclarations: true", SortUsingDeclarations, FormatStyle::SUD_LexicographicNumeric); + Style.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave; + CHECK_PARSE("WrapNamespaceBodyWithEmptyLines: Never", + WrapNamespaceBodyWithEmptyLines, FormatStyle::WNBWELS_Never); + CHECK_PARSE("WrapNamespaceBodyWithEmptyLines: Always", + WrapNamespaceBodyWithEmptyLines, FormatStyle::WNBWELS_Always); + CHECK_PARSE("WrapNamespaceBodyWithEmptyLines: Leave", + WrapNamespaceBodyWithEmptyLines, FormatStyle::WNBWELS_Leave); + // FIXME: This is required because parsing a configuration simply overwrites // the first N elements of the list instead of resetting it. Style.ForEachMacros.clear(); >From 5823649f2cc0e6a7bbe62ee089d7f7711a5dd0c0 Mon Sep 17 00:00:00 2001 From: dmasloff <dmaslo...@gmail.com> Date: Tue, 17 Sep 2024 18:43:40 +0300 Subject: [PATCH 4/6] Fix invalid tests with CompactNamespaces option --- clang/unittests/Format/FormatTest.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 0b833bd240e80c..98c4f90ce80160 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -28137,8 +28137,8 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesNever) { Style.CompactNamespaces = true; // Empty namespace - verifyNoChange("namespace N {\n" - "};", + verifyNoChange("namespace N1 { namespace N2 {\n" + "}};", Style); // Single namespace @@ -28333,7 +28333,9 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesLeave) { Style.CompactNamespaces = true; // Empty namespace - verifyNoChange("namespace N {\n};", Style); + verifyNoChange("namespace N1 { namespace N2 {\n" + "}};", + Style); // Nested namespace verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n" >From d219928e6113c8cfb3078df67809ab52111048ad Mon Sep 17 00:00:00 2001 From: dmasloff <dmaslo...@gmail.com> Date: Thu, 26 Sep 2024 00:25:17 +0300 Subject: [PATCH 5/6] Reformat tests in FormatTest.cpp --- clang/unittests/Format/FormatTest.cpp | 317 +++++++++++++------------- 1 file changed, 153 insertions(+), 164 deletions(-) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 98c4f90ce80160..f38640e41e0e93 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -28105,226 +28105,223 @@ TEST_F(FormatTest, BreakBinaryOperations) { } TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesNever) { - FormatStyle Style = getLLVMStyle(); + auto Style = getLLVMStyle(); Style.FixNamespaceComments = false; - Style.ShortNamespaceLines = 0; - Style.MaxEmptyLinesToKeep = 2; - Style.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Never; - Style.CompactNamespaces = false; - // Empty namespace - verifyNoChange("namespace N {};", Style); + // Empty namespace. + verifyFormat("namespace N {}", Style); - // Single namespace - verifyNoChange("namespace N {\n" - "int f1(int a) { return 2 * a; }\n" - "};", - Style); + // Single namespace. + verifyFormat("namespace N {\n" + "int f1(int a) { return 2 * a; }\n" + "}", + Style); - // Nested namespace - verifyNoChange("namespace N1 {\n" - "namespace N2 {\n" - "namespace N3 {\n" - "int f1() {\n" - " int a = 1;\n" - " return a;\n" - "}\n" - "}\n" - "}\n" - "}", - Style); + // Nested namespace. + verifyFormat("namespace N1 {\n" + "namespace N2 {\n" + "int a = 1;\n" + "}\n" + "}", + Style); Style.CompactNamespaces = true; - // Empty namespace - verifyNoChange("namespace N1 { namespace N2 {\n" - "}};", - Style); + verifyFormat("namespace N1 { namespace N2 {\n" + "int a = 1;\n" + "}}", + Style); - // Single namespace - verifyNoChange("namespace N {\n" - "int f1(int a) { return 2 * a; }\n" - "};", - Style); + // Removing empty lines. + verifyFormat("namespace N {\n" + "\n" + "int a = 1;\n" + "\n" + "}", + "namespace N {\n" + "\n" + "\n" + "int a = 1;\n" + "\n" + "\n" + "}", + Style); - // Nested namespace - verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n" - "int f1() {\n" - " int a = 1;\n" - " return a;\n" - "}\n" - "}}}", - Style); + Style.MaxEmptyLinesToKeep = 0; + + verifyFormat("namespace N {\n" + "int a = 1;\n" + "}", + "namespace N {\n" + "\n" + "\n" + "int a = 1;\n" + "\n" + "\n" + "}", + Style); } TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesAlways) { - FormatStyle Style = getLLVMStyle(); + auto Style = getLLVMStyle(); Style.FixNamespaceComments = false; - Style.ShortNamespaceLines = 0; - Style.MaxEmptyLinesToKeep = 0; Style.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Always; - Style.CompactNamespaces = false; - - // Empty namespace - verifyNoChange("namespace N {};", Style); - - // Single namespace - verifyNoChange("namespace N {\n" - "\n" - "int f1(int a) { return 2 * a; }\n" - "\n" - "};", - Style); - - // Nested namespace - verifyNoChange("namespace N1 {\n" - "namespace N2 {\n" - "namespace N3 {\n" - "\n" - "int f1() {\n" - " int a = 1;\n" - " return a;\n" - "}\n" - "\n" - "}\n" - "}\n" - "}", - Style); - Style.CompactNamespaces = true; + // Empty namespace. + verifyFormat("namespace N {}", Style); - // Nested namespace - verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n" - "\n" - "int f1() {\n" - " int a = 1;\n" - " return a;\n" - "}\n" - "\n" - "}}}", - Style); - - Style.MaxEmptyLinesToKeep = 2; - Style.CompactNamespaces = false; - - // Empty namespace - verifyNoChange("namespace N {};", Style); - - // Single namespace - verifyNoChange("namespace N {\n" - "\n" - "\n" - "void function()\n" - "\n" - "\n" - "};", - Style); + // Single namespace. + verifyFormat("namespace N {\n" + "\n" + "int f1(int a) { return 2 * a; }\n" + "\n" + "}", + Style); - // Nested namespace + // Nested namespace. verifyFormat("namespace N1 {\n" "namespace N2 {\n" - "namespace N3 {\n" - "\n" - "\n" - "int f1() {\n" - " int a = 1;\n" - " return a;\n" - "}\n" "\n" + "int a = 1;\n" "\n" "}\n" - "}\n" "}", - "namespace N1 {\n" - "namespace N2 {\n" + Style); + + // Removing empty lines. + verifyFormat("namespace N {\n" "\n" - "namespace N3 {\n" + "int a = 1;\n" "\n" + "}", + "namespace N {" "\n" - "int f1() {\n" - " int a = 1;\n" - " return a;\n" - "}\n" "\n" + "int a = 1;\n" "\n" - "}\n" "\n" - "}\n" "}", Style); Style.CompactNamespaces = true; - // Nested namespace - verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n" + // Nested namespace. + verifyFormat("namespace N1 { namespace N2 {\n" + "\n" + "int a = 1;\n" + "\n" + "}}", + Style); + + Style.MaxEmptyLinesToKeep = 2; + + // Nested namespace. + verifyNoChange("namespace N1 { namespace N2 {\n" "\n" "\n" - "int f1() {\n" - " int a = 1;\n" - " return a;\n" - "}\n" + "int a = 1;\n" "\n" "\n" - "}}}", + "}}", Style); -} -TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesLeave) { - FormatStyle Style = getLLVMStyle(); - Style.FixNamespaceComments = false; - Style.ShortNamespaceLines = 0; - Style.MaxEmptyLinesToKeep = 0; - Style.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Leave; Style.CompactNamespaces = false; - // Empty namespace - verifyNoChange("namespace N {};", Style); + // Empty namespace. + verifyFormat("namespace N {}", Style); - // Single namespace + // Single namespace. verifyNoChange("namespace N {\n" - "int f1(int a) { return 2 * a; }\n" - "};", + "\n" + "\n" + "int a = 1;\n" + "\n" + "\n" + "}", Style); - // Nested namespace + // Nested namespace. verifyNoChange("namespace N1 {\n" "namespace N2 {\n" - "namespace N3 {\n" - "int f1() {\n" - " int a = 1;\n" - " return a;\n" - "}\n" - "}\n" + "\n" + "\n" + "int a = 1;\n" + "\n" + "\n" "}\n" "}", Style); +} + +TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesLeave) { + auto Style = getLLVMStyle(); + Style.FixNamespaceComments = false; + + // Empty namespace. + verifyFormat("namespace N {}", Style); + + // Single namespace. + verifyFormat("namespace N {\n" + "int f1(int a) { return 2 * a; }\n" + "}", + Style); + + // Nested namespace. + verifyFormat("namespace N1 {\n" + "namespace N2 {\n" + "int a = 1;\n" + "}\n" + "}", + Style); + + // Removing empty lines. + verifyFormat("namespace N {\n" + "\n" + "int a = 1;\n" + "\n" + "}", + "namespace N {\n" + "\n" + "\n" + "int a = 1;\n" + "\n" + "\n" + "}", + Style); + + Style.MaxEmptyLinesToKeep = 0; + + verifyFormat("namespace N {\n" + "int a = 1;\n" + "}", + "namespace N {\n" + "\n" + "\n" + "int a = 1;\n" + "\n" + "\n" + "}", + Style); Style.MaxEmptyLinesToKeep = 2; - // Single namespace + // Single namespace. verifyNoChange("namespace N {\n" "\n" "\n" "int f1(int a) { return 2 * a; }\n" "\n" "\n" - "};", + "}", Style); - // Nested namespace + // Nested namespace. verifyNoChange("namespace N1 {\n" "namespace N2 {\n" "\n" - "namespace N3 {\n" - "\n" - "\n" - "int f1() {\n" - " int a = 1;\n" - " return a;\n" - "}\n" "\n" + "int a = 1;\n" "\n" - "}\n" "\n" "}\n" "}", @@ -28332,22 +28329,14 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesLeave) { Style.CompactNamespaces = true; - // Empty namespace + // Nested namespace. verifyNoChange("namespace N1 { namespace N2 {\n" - "}};", - Style); - - // Nested namespace - verifyNoChange("namespace N1 { namespace N2 { namespace N3 {\n" "\n" "\n" - "int f1() {\n" - " int a = 1;\n" - " return a;\n" - "}\n" + "int a = 1;\n" "\n" "\n" - "}}}", + "}}", Style); } >From fe3a8306c2cd5a6442932032e87b9379c14ed89a Mon Sep 17 00:00:00 2001 From: dmasloff <dmaslo...@gmail.com> Date: Sun, 17 Nov 2024 02:07:39 +0300 Subject: [PATCH 6/6] Remove reduntant tests and simplify code --- clang/lib/Format/UnwrappedLineFormatter.cpp | 56 +++-------- clang/unittests/Format/FormatTest.cpp | 106 +------------------- 2 files changed, 16 insertions(+), 146 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 92fddd9e62bcb0..80dcedce777a10 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -32,26 +32,6 @@ bool isRecordLBrace(const FormatToken &Tok) { TT_StructLBrace, TT_UnionLBrace); } -bool LineStartsNamespaceScope(const AnnotatedLine *Line, - const AnnotatedLine *PreviousLine, - const AnnotatedLine *PrevPrevLine) { - return PreviousLine && - ((PreviousLine->Last->is(tok::l_brace) && - PreviousLine->startsWithNamespace()) || - (PrevPrevLine && PrevPrevLine->startsWithNamespace() && - PreviousLine->startsWith(tok::l_brace))); -} - -bool LineEndsNamespaceScope(const AnnotatedLine *Line, - const SmallVectorImpl<AnnotatedLine *> &Lines) { - if (!Line) - return false; - const FormatToken *Tok = Line->First; - if (!Tok || Tok->isNot(tok::r_brace)) - return false; - return getNamespaceToken(Line, Lines) != nullptr; -} - /// Tracks the indent level of \c AnnotatedLines across levels. /// /// \c nextLine must be called for each \c AnnotatedLine, after which \c @@ -1513,27 +1493,21 @@ static auto computeNewlines(const AnnotatedLine &Line, Newlines = 1; } - // Modify empty lines after "{" that opens namespace scope. - if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave && - LineStartsNamespaceScope(&Line, PreviousLine, PrevPrevLine)) { - if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never) - Newlines = std::min(Newlines, 1u); - else if (!Line.startsWithNamespace()) - Newlines = std::max(Newlines, 2u); - else - Newlines = std::min(Newlines, 1u); - } - - // Modify empty lines before "}" that closes namespace scope. - if (Style.WrapNamespaceBodyWithEmptyLines != FormatStyle::WNBWELS_Leave && - LineEndsNamespaceScope(&Line, Lines)) { - if (Style.WrapNamespaceBodyWithEmptyLines == FormatStyle::WNBWELS_Never) - Newlines = std::min(Newlines, 1u); - else if (!LineEndsNamespaceScope(PreviousLine, Lines)) - Newlines = std::max(Newlines, 2u); - else - Newlines = std::min(Newlines, 1u); - } + 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()) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index f38640e41e0e93..959e952fba065a 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -28107,6 +28107,7 @@ TEST_F(FormatTest, BreakBinaryOperations) { TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesNever) { auto Style = getLLVMStyle(); Style.FixNamespaceComments = false; + Style.WrapNamespaceBodyWithEmptyLines = FormatStyle::WNBWELS_Never; // Empty namespace. verifyFormat("namespace N {}", Style); @@ -28188,21 +28189,6 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesAlways) { "}", Style); - // Removing empty lines. - verifyFormat("namespace N {\n" - "\n" - "int a = 1;\n" - "\n" - "}", - "namespace N {" - "\n" - "\n" - "int a = 1;\n" - "\n" - "\n" - "}", - Style); - Style.CompactNamespaces = true; // Nested namespace. @@ -28227,9 +28213,6 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesAlways) { Style.CompactNamespaces = false; - // Empty namespace. - verifyFormat("namespace N {}", Style); - // Single namespace. verifyNoChange("namespace N {\n" "\n" @@ -28253,93 +28236,6 @@ TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesAlways) { Style); } -TEST_F(FormatTest, WrapNamespaceBodyWithEmptyLinesLeave) { - auto Style = getLLVMStyle(); - Style.FixNamespaceComments = false; - - // Empty namespace. - verifyFormat("namespace N {}", Style); - - // Single namespace. - verifyFormat("namespace N {\n" - "int f1(int a) { return 2 * a; }\n" - "}", - Style); - - // Nested namespace. - verifyFormat("namespace N1 {\n" - "namespace N2 {\n" - "int a = 1;\n" - "}\n" - "}", - Style); - - // Removing empty lines. - verifyFormat("namespace N {\n" - "\n" - "int a = 1;\n" - "\n" - "}", - "namespace N {\n" - "\n" - "\n" - "int a = 1;\n" - "\n" - "\n" - "}", - Style); - - Style.MaxEmptyLinesToKeep = 0; - - verifyFormat("namespace N {\n" - "int a = 1;\n" - "}", - "namespace N {\n" - "\n" - "\n" - "int a = 1;\n" - "\n" - "\n" - "}", - Style); - - Style.MaxEmptyLinesToKeep = 2; - - // Single namespace. - verifyNoChange("namespace N {\n" - "\n" - "\n" - "int f1(int a) { return 2 * a; }\n" - "\n" - "\n" - "}", - Style); - - // Nested namespace. - verifyNoChange("namespace N1 {\n" - "namespace N2 {\n" - "\n" - "\n" - "int a = 1;\n" - "\n" - "\n" - "}\n" - "}", - Style); - - Style.CompactNamespaces = true; - - // Nested namespace. - verifyNoChange("namespace N1 { namespace N2 {\n" - "\n" - "\n" - "int a = 1;\n" - "\n" - "\n" - "}}", - Style); -} - } // namespace } // namespace test } // namespace format _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits