diff options
author | Owen Pan <owenpiano@gmail.com> | 2024-02-07 20:24:44 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-07 20:24:44 -0800 |
commit | d033799050b7bda70d80a933d5d99b7088a72a95 (patch) | |
tree | 086c70ef55d2f6736a73aa443451a2724dc901f6 /clang | |
parent | 05091aa3ac53a13d08c78882c0c2035e58a1b4c4 (diff) | |
download | llvm-d033799050b7bda70d80a933d5d99b7088a72a95.zip llvm-d033799050b7bda70d80a933d5d99b7088a72a95.tar.gz llvm-d033799050b7bda70d80a933d5d99b7088a72a95.tar.bz2 |
[clang-format] Add Leave to AlwaysBreakTemplateDeclarations (#80569)
Closes #78067.
Diffstat (limited to 'clang')
-rw-r--r-- | clang/docs/ClangFormatStyleOptions.rst | 12 | ||||
-rw-r--r-- | clang/include/clang/Format/Format.h | 10 | ||||
-rw-r--r-- | clang/lib/Format/ContinuationIndenter.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Format/Format.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Format/TokenAnnotator.cpp | 10 | ||||
-rw-r--r-- | clang/unittests/Format/ConfigParseTest.cpp | 2 | ||||
-rw-r--r-- | clang/unittests/Format/FormatTest.cpp | 68 |
7 files changed, 105 insertions, 3 deletions
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index f86be2c..0a8cc18 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1664,6 +1664,18 @@ the configuration (without a prefix: ``Auto``). Possible values: + * ``BTDS_Leave`` (in configuration: ``Leave``) + Do not change the line breaking before the declaration. + + .. code-block:: c++ + + template <typename T> + T foo() { + } + template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa, + int bbbbbbbbbbbbbbbbbbbbb) { + } + * ``BTDS_No`` (in configuration: ``No``) Do not force break before declaration. ``PenaltyBreakTemplateDeclaration`` is taken into account. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 4153213..cb14d98 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1031,6 +1031,16 @@ struct FormatStyle { /// Different ways to break after the template declaration. enum BreakTemplateDeclarationsStyle : int8_t { + /// Do not change the line breaking before the declaration. + /// \code + /// template <typename T> + /// T foo() { + /// } + /// template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa, + /// int bbbbbbbbbbbbbbbbbbbbb) { + /// } + /// \endcode + BTDS_Leave, /// Do not force break before declaration. /// ``PenaltyBreakTemplateDeclaration`` is taken into account. /// \code diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 671ae54..7fd04b2 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -569,7 +569,10 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { return true; } } - return Style.AlwaysBreakTemplateDeclarations != FormatStyle::BTDS_No; + return Style.AlwaysBreakTemplateDeclarations != FormatStyle::BTDS_No && + (Style.AlwaysBreakTemplateDeclarations != + FormatStyle::BTDS_Leave || + Current.NewlinesBefore > 0); } if (Previous.is(TT_FunctionAnnotationRParen) && State.Line->Type != LT_PreprocessorDirective) { diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 9c780cd..c5714af 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -296,6 +296,7 @@ template <> struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> { static void enumeration(IO &IO, FormatStyle::BreakTemplateDeclarationsStyle &Value) { + IO.enumCase(Value, "Leave", FormatStyle::BTDS_Leave); IO.enumCase(Value, "No", FormatStyle::BTDS_No); IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine); IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes); diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 7a62f5f..cec56fa 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -5184,7 +5184,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // concept ... if (Right.is(tok::kw_concept)) return Style.BreakBeforeConceptDeclarations == FormatStyle::BBCDS_Always; - return Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes; + return Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes || + (Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Leave && + Right.NewlinesBefore > 0); } if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) { switch (Style.RequiresClausePosition) { @@ -5617,7 +5619,11 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, return Style.BreakBeforeConceptDeclarations != FormatStyle::BBCDS_Never; if (Right.is(TT_RequiresClause)) return true; - if (Left.ClosesTemplateDeclaration || Left.is(TT_FunctionAnnotationRParen)) + if (Left.ClosesTemplateDeclaration) { + return Style.AlwaysBreakTemplateDeclarations != FormatStyle::BTDS_Leave || + Right.NewlinesBefore > 0; + } + if (Left.is(TT_FunctionAnnotationRParen)) return true; if (Left.ClosesRequiresClause) return true; diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 3f1fc893..7493b0a 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -695,6 +695,8 @@ TEST(ConfigParseTest, ParsesConfiguration) { FormatStyle::RTBS_TopLevelDefinitions); Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; + CHECK_PARSE("AlwaysBreakTemplateDeclarations: Leave", + AlwaysBreakTemplateDeclarations, FormatStyle::BTDS_Leave); CHECK_PARSE("AlwaysBreakTemplateDeclarations: No", AlwaysBreakTemplateDeclarations, FormatStyle::BTDS_No); CHECK_PARSE("AlwaysBreakTemplateDeclarations: MultiLine", diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 87a02a4..b1a2247 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -10697,6 +10697,74 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) { verifyFormat("template <typename T> void\nfoo(aaaaaaaaaaaaaaaaaaaaaaaaaa " "bbbbbbbbbbbbbbbbbbbb) {}", NeverBreak); + + auto Style = getLLVMStyle(); + Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Leave; + + verifyNoChange("template <typename T>\n" + "class C {};", + Style); + verifyFormat("template <typename T> class C {};", Style); + + verifyNoChange("template <typename T>\n" + "void f();", + Style); + verifyFormat("template <typename T> void f();", Style); + + verifyNoChange("template <typename T>\n" + "void f() {}", + Style); + verifyFormat("template <typename T> void f() {}", Style); + + verifyNoChange("template <typename T>\n" + "// T can be A, B or C.\n" + "struct C {};", + Style); + verifyFormat("template <typename T> // T can be A, B or C.\n" + "struct C {};", + Style); + + verifyNoChange("template <typename T>\n" + "C(T) noexcept;", + Style); + verifyFormat("template <typename T> C(T) noexcept;", Style); + + verifyNoChange("template <enum E>\n" + "class A {\n" + "public:\n" + " E *f();\n" + "};", + Style); + verifyFormat("template <enum E> class A {\n" + "public:\n" + " E *f();\n" + "};", + Style); + + verifyNoChange("template <auto x>\n" + "constexpr int simple(int) {\n" + " char c;\n" + " return 1;\n" + "}", + Style); + verifyFormat("template <auto x> constexpr int simple(int) {\n" + " char c;\n" + " return 1;\n" + "}", + Style); + + Style.RequiresClausePosition = FormatStyle::RCPS_WithPreceding; + verifyNoChange("template <auto x>\n" + "requires(x > 1)\n" + "constexpr int with_req(int) {\n" + " return 1;\n" + "}", + Style); + verifyFormat("template <auto x> requires(x > 1)\n" + "constexpr int with_req(int) {\n" + " return 1;\n" + "}", + Style); } TEST_F(FormatTest, WrapsTemplateDeclarationsWithComments) { |