diff options
author | rmarker <37921131+rmarker@users.noreply.github.com> | 2024-02-05 06:56:32 +1030 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-04 12:26:32 -0800 |
commit | 256200732111afd03bb7437564f3a3d77c0ec3f5 (patch) | |
tree | b4beee78935f7d40cb6e91123788d07232baa1f6 | |
parent | 9ff83f12fe406f9c3c6b2cd0ee96660a7485f29f (diff) | |
download | llvm-256200732111afd03bb7437564f3a3d77c0ec3f5.zip llvm-256200732111afd03bb7437564f3a3d77c0ec3f5.tar.gz llvm-256200732111afd03bb7437564f3a3d77c0ec3f5.tar.bz2 |
[clang-format] Add Automatic and ExceptShortType options for AlwaysBreakAfterReturnType. (#78011)
The RTBS_None option in Clang-format avoids breaking after a short
return type.
However, there was an issue with the behaviour in that it wouldn't take
the leading indentation of the line into account.
This meant that the behaviour wasn't applying when intended.
In order to address this situation without breaking the existing
formatting, RTBS_None has been deprecated.
In its place are two new options for AlwaysBreakAfterReturnType.
The option RTBS_Automatic will break after the return type based on
PenaltyReturnTypeOnItsOwnLine.
The option RTBS_ExceptShortType will take the leading indentation into
account and prevent breaking after short return types.
This allows the inconsistent behaviour of RTBS_None to be avoided and
users to decide whether they want to allow breaking after short return
types or not.
Resolves #78010
-rw-r--r-- | clang/docs/ClangFormatStyleOptions.rst | 30 | ||||
-rw-r--r-- | clang/include/clang/Format/Format.h | 29 | ||||
-rw-r--r-- | clang/lib/Format/ContinuationIndenter.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Format/Format.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Format/TokenAnnotator.cpp | 2 | ||||
-rw-r--r-- | clang/unittests/Format/ConfigParseTest.cpp | 4 | ||||
-rw-r--r-- | clang/unittests/Format/FormatTest.cpp | 46 |
7 files changed, 116 insertions, 11 deletions
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 0b88728..976d9e2 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1537,8 +1537,10 @@ the configuration (without a prefix: ``Auto``). Possible values: * ``RTBS_None`` (in configuration: ``None``) - Break after return type automatically. - ``PenaltyReturnTypeOnItsOwnLine`` is taken into account. + This is **deprecated**. See ``Automatic`` below. + + * ``RTBS_Automatic`` (in configuration: ``Automatic``) + Break after return type based on ``PenaltyReturnTypeOnItsOwnLine``. .. code-block:: c++ @@ -1547,6 +1549,22 @@ the configuration (without a prefix: ``Auto``). }; int f(); int f() { return 1; } + int + LongName::AnotherLongName(); + + * ``RTBS_ExceptShortType`` (in configuration: ``ExceptShortType``) + Same as ``Automatic`` above, except that there is no break after short + return types. + + .. code-block:: c++ + + class A { + int f() { return 0; }; + }; + int f(); + int f() { return 1; } + int LongName:: + AnotherLongName(); * ``RTBS_All`` (in configuration: ``All``) Always break after the return type. @@ -1565,6 +1583,8 @@ the configuration (without a prefix: ``Auto``). f() { return 1; } + int + LongName::AnotherLongName(); * ``RTBS_TopLevel`` (in configuration: ``TopLevel``) Always break after the return types of top-level functions. @@ -1580,6 +1600,8 @@ the configuration (without a prefix: ``Auto``). f() { return 1; } + int + LongName::AnotherLongName(); * ``RTBS_AllDefinitions`` (in configuration: ``AllDefinitions``) Always break after the return type of function definitions. @@ -1597,6 +1619,8 @@ the configuration (without a prefix: ``Auto``). f() { return 1; } + int + LongName::AnotherLongName(); * ``RTBS_TopLevelDefinitions`` (in configuration: ``TopLevelDefinitions``) Always break after the return type of top-level definitions. @@ -1611,6 +1635,8 @@ the configuration (without a prefix: ``Auto``). f() { return 1; } + int + LongName::AnotherLongName(); diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index efcb4e1..2ca80a7 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -914,16 +914,31 @@ struct FormatStyle { /// Different ways to break after the function definition or /// declaration return type. enum ReturnTypeBreakingStyle : int8_t { - /// Break after return type automatically. - /// ``PenaltyReturnTypeOnItsOwnLine`` is taken into account. + /// This is **deprecated**. See ``Automatic`` below. + RTBS_None, + /// Break after return type based on ``PenaltyReturnTypeOnItsOwnLine``. /// \code /// class A { /// int f() { return 0; }; /// }; /// int f(); /// int f() { return 1; } + /// int + /// LongName::AnotherLongName(); /// \endcode - RTBS_None, + RTBS_Automatic, + /// Same as ``Automatic`` above, except that there is no break after short + /// return types. + /// \code + /// class A { + /// int f() { return 0; }; + /// }; + /// int f(); + /// int f() { return 1; } + /// int LongName:: + /// AnotherLongName(); + /// \endcode + RTBS_ExceptShortType, /// Always break after the return type. /// \code /// class A { @@ -938,6 +953,8 @@ struct FormatStyle { /// f() { /// return 1; /// } + /// int + /// LongName::AnotherLongName(); /// \endcode RTBS_All, /// Always break after the return types of top-level functions. @@ -951,6 +968,8 @@ struct FormatStyle { /// f() { /// return 1; /// } + /// int + /// LongName::AnotherLongName(); /// \endcode RTBS_TopLevel, /// Always break after the return type of function definitions. @@ -966,6 +985,8 @@ struct FormatStyle { /// f() { /// return 1; /// } + /// int + /// LongName::AnotherLongName(); /// \endcode RTBS_AllDefinitions, /// Always break after the return type of top-level definitions. @@ -978,6 +999,8 @@ struct FormatStyle { /// f() { /// return 1; /// } + /// int + /// LongName::AnotherLongName(); /// \endcode RTBS_TopLevelDefinitions, }; diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index a3eb913..a3aca4a 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -328,9 +328,17 @@ bool ContinuationIndenter::canBreak(const LineState &State) { // Don't break after very short return types (e.g. "void") as that is often // unexpected. - if (Current.is(TT_FunctionDeclarationName) && State.Column < 6) { - if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) + if (Current.is(TT_FunctionDeclarationName)) { + if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None && + State.Column < 6) { return false; + } + + if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_ExceptShortType) { + assert(State.Column >= State.FirstIndent); + if (State.Column - State.FirstIndent < 6) + return false; + } } // If binary operators are moved to the next line (including commas for some @@ -587,7 +595,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { !State.Line->ReturnTypeWrapped && // Don't break before a C# function when no break after return type. (!Style.isCSharp() || - Style.AlwaysBreakAfterReturnType != FormatStyle::RTBS_None) && + Style.AlwaysBreakAfterReturnType > FormatStyle::RTBS_ExceptShortType) && // Don't always break between a JavaScript `function` and the function // name. !Style.isJavaScript() && Previous.isNot(tok::kw_template) && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 10fe35c..01d6e9a 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -558,6 +558,8 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> { static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { IO.enumCase(Value, "None", FormatStyle::RTBS_None); + IO.enumCase(Value, "Automatic", FormatStyle::RTBS_Automatic); + IO.enumCase(Value, "ExceptShortType", FormatStyle::RTBS_ExceptShortType); IO.enumCase(Value, "All", FormatStyle::RTBS_All); IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel); IO.enumCase(Value, "TopLevelDefinitions", diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index d0c4273..7a62f5f 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3434,6 +3434,8 @@ bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const { switch (Style.AlwaysBreakAfterReturnType) { case FormatStyle::RTBS_None: + case FormatStyle::RTBS_Automatic: + case FormatStyle::RTBS_ExceptShortType: return false; case FormatStyle::RTBS_All: case FormatStyle::RTBS_TopLevel: diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 6436581..3f1fc893 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -680,6 +680,10 @@ TEST(ConfigParseTest, ParsesConfiguration) { Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_All; CHECK_PARSE("AlwaysBreakAfterReturnType: None", AlwaysBreakAfterReturnType, FormatStyle::RTBS_None); + CHECK_PARSE("AlwaysBreakAfterReturnType: Automatic", + AlwaysBreakAfterReturnType, FormatStyle::RTBS_Automatic); + CHECK_PARSE("AlwaysBreakAfterReturnType: ExceptShortType", + AlwaysBreakAfterReturnType, FormatStyle::RTBS_ExceptShortType); CHECK_PARSE("AlwaysBreakAfterReturnType: All", AlwaysBreakAfterReturnType, FormatStyle::RTBS_All); CHECK_PARSE("AlwaysBreakAfterReturnType: TopLevel", diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index a471e36..2f7febd 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -9867,14 +9867,48 @@ TEST_F(FormatTest, AlignsStringLiterals) { TEST_F(FormatTest, ReturnTypeBreakingStyle) { FormatStyle Style = getLLVMStyle(); + Style.ColumnLimit = 60; + // No declarations or definitions should be moved to own line. Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; verifyFormat("class A {\n" " int f() { return 1; }\n" " int g();\n" + " long\n" + " foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaar();\n" "};\n" "int f() { return 1; }\n" - "int g();", + "int g();\n" + "int foooooooooooooooooooooooooooo::\n" + " baaaaaaaaaaaaaaaaaaaaar();", + Style); + + // It is now allowed to break after a short return type if necessary. + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_Automatic; + verifyFormat("class A {\n" + " int f() { return 1; }\n" + " int g();\n" + " long\n" + " foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaar();\n" + "};\n" + "int f() { return 1; }\n" + "int g();\n" + "int\n" + "foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaaar();", + Style); + + // It now must never break after a short return type. + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_ExceptShortType; + verifyFormat("class A {\n" + " int f() { return 1; }\n" + " int g();\n" + " long foooooooooooooooooooooooooooo::\n" + " baaaaaaaaaaaaaaaaaaaar();\n" + "};\n" + "int f() { return 1; }\n" + "int g();\n" + "int foooooooooooooooooooooooooooo::\n" + " baaaaaaaaaaaaaaaaaaaaar();", Style); // All declarations and definitions should have the return type moved to its @@ -9891,13 +9925,17 @@ TEST_F(FormatTest, ReturnTypeBreakingStyle) { " }\n" " int\n" " g();\n" + " long\n" + " foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaar();\n" "};\n" "int\n" "f() {\n" " return 1;\n" "}\n" "int\n" - "g();", + "g();\n" + "int\n" + "foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaaar();", Style); // Top-level definitions, and no kinds of declarations should have the @@ -9926,7 +9964,9 @@ TEST_F(FormatTest, ReturnTypeBreakingStyle) { " return 1;\n" "}\n" "int\n" - "g();", + "g();\n" + "int\n" + "foooooooooooooooooooooooooooo::baaaaaaaaaaaaaaaaaaaaar();", Style); // All definitions should have the return type moved to its own line, but no |