[clang-format] BreakBeforeNoexceptSpecifier option added (#65808)
It really bugs me that it breaks to
``` c++
...) noexcept(
noexcept(condition)...
```
This is a fix for people like me.
This commit is contained in:
@@ -1108,6 +1108,54 @@ the configuration (without a prefix: ``Auto``).
|
||||
int d,
|
||||
int e);
|
||||
|
||||
.. _AllowBreakBeforeNoexceptSpecifier:
|
||||
|
||||
**AllowBreakBeforeNoexceptSpecifier** (``BreakBeforeNoexceptSpecifierStyle``) :versionbadge:`clang-format 18` :ref:`¶ <AllowBreakBeforeNoexceptSpecifier>`
|
||||
Controls if there could be a line break before a ``noexcept`` specifier.
|
||||
|
||||
Possible values:
|
||||
|
||||
* ``BBNSS_Never`` (in configuration: ``Never``)
|
||||
No line break allowed.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
void foo(int arg1,
|
||||
double arg2) noexcept;
|
||||
|
||||
void bar(int arg1, double arg2) noexcept(
|
||||
noexcept(baz(arg1)) &&
|
||||
noexcept(baz(arg2)));
|
||||
|
||||
* ``BBNSS_OnlyWithParen`` (in configuration: ``OnlyWithParen``)
|
||||
For a simple ``noexcept`` there is no line break allowed, but when we
|
||||
have a condition it is.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
void foo(int arg1,
|
||||
double arg2) noexcept;
|
||||
|
||||
void bar(int arg1, double arg2)
|
||||
noexcept(noexcept(baz(arg1)) &&
|
||||
noexcept(baz(arg2)));
|
||||
|
||||
* ``BBNSS_Always`` (in configuration: ``Always``)
|
||||
Line breaks are allowed. But note that because of the associated
|
||||
penalties ``clang-format`` often prefers not to break before the
|
||||
``noexcept``.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
void foo(int arg1,
|
||||
double arg2) noexcept;
|
||||
|
||||
void bar(int arg1, double arg2)
|
||||
noexcept(noexcept(baz(arg1)) &&
|
||||
noexcept(baz(arg2)));
|
||||
|
||||
|
||||
|
||||
.. _AllowShortBlocksOnASingleLine:
|
||||
|
||||
**AllowShortBlocksOnASingleLine** (``ShortBlockStyle``) :versionbadge:`clang-format 3.5` :ref:`¶ <AllowShortBlocksOnASingleLine>`
|
||||
|
||||
@@ -389,6 +389,7 @@ AST Matchers
|
||||
|
||||
clang-format
|
||||
------------
|
||||
- Add ``AllowBreakBeforeNoexceptSpecifier`` option.
|
||||
|
||||
libclang
|
||||
--------
|
||||
|
||||
@@ -593,6 +593,47 @@ struct FormatStyle {
|
||||
/// \version 3.3
|
||||
bool AllowAllParametersOfDeclarationOnNextLine;
|
||||
|
||||
/// Different ways to break before a noexcept specifier.
|
||||
enum BreakBeforeNoexceptSpecifierStyle : int8_t {
|
||||
/// No line break allowed.
|
||||
/// \code
|
||||
/// void foo(int arg1,
|
||||
/// double arg2) noexcept;
|
||||
///
|
||||
/// void bar(int arg1, double arg2) noexcept(
|
||||
/// noexcept(baz(arg1)) &&
|
||||
/// noexcept(baz(arg2)));
|
||||
/// \endcode
|
||||
BBNSS_Never,
|
||||
/// For a simple ``noexcept`` there is no line break allowed, but when we
|
||||
/// have a condition it is.
|
||||
/// \code
|
||||
/// void foo(int arg1,
|
||||
/// double arg2) noexcept;
|
||||
///
|
||||
/// void bar(int arg1, double arg2)
|
||||
/// noexcept(noexcept(baz(arg1)) &&
|
||||
/// noexcept(baz(arg2)));
|
||||
/// \endcode
|
||||
BBNSS_OnlyWithParen,
|
||||
/// Line breaks are allowed. But note that because of the associated
|
||||
/// penalties ``clang-format`` often prefers not to break before the
|
||||
/// ``noexcept``.
|
||||
/// \code
|
||||
/// void foo(int arg1,
|
||||
/// double arg2) noexcept;
|
||||
///
|
||||
/// void bar(int arg1, double arg2)
|
||||
/// noexcept(noexcept(baz(arg1)) &&
|
||||
/// noexcept(baz(arg2)));
|
||||
/// \endcode
|
||||
BBNSS_Always,
|
||||
};
|
||||
|
||||
/// Controls if there could be a line break before a ``noexcept`` specifier.
|
||||
/// \version 18
|
||||
BreakBeforeNoexceptSpecifierStyle AllowBreakBeforeNoexceptSpecifier;
|
||||
|
||||
/// Different styles for merging short blocks containing at most one
|
||||
/// statement.
|
||||
enum ShortBlockStyle : int8_t {
|
||||
@@ -4576,6 +4617,8 @@ struct FormatStyle {
|
||||
AllowAllArgumentsOnNextLine == R.AllowAllArgumentsOnNextLine &&
|
||||
AllowAllParametersOfDeclarationOnNextLine ==
|
||||
R.AllowAllParametersOfDeclarationOnNextLine &&
|
||||
AllowBreakBeforeNoexceptSpecifier ==
|
||||
R.AllowBreakBeforeNoexceptSpecifier &&
|
||||
AllowShortBlocksOnASingleLine == R.AllowShortBlocksOnASingleLine &&
|
||||
AllowShortCaseLabelsOnASingleLine ==
|
||||
R.AllowShortCaseLabelsOnASingleLine &&
|
||||
|
||||
@@ -59,6 +59,16 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
|
||||
|
||||
namespace llvm {
|
||||
namespace yaml {
|
||||
template <>
|
||||
struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> {
|
||||
static void enumeration(IO &IO,
|
||||
FormatStyle::BreakBeforeNoexceptSpecifierStyle &Value) {
|
||||
IO.enumCase(Value, "Never", FormatStyle::BBNSS_Never);
|
||||
IO.enumCase(Value, "OnlyWithParen", FormatStyle::BBNSS_OnlyWithParen);
|
||||
IO.enumCase(Value, "Always", FormatStyle::BBNSS_Always);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
|
||||
static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
|
||||
IO.enumCase(Value, "None",
|
||||
@@ -260,6 +270,7 @@ struct ScalarEnumerationTraits<FormatStyle::BreakBeforeInlineASMColonStyle> {
|
||||
IO.enumCase(Value, "Always", FormatStyle::BBIAS_Always);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
|
||||
static void
|
||||
@@ -904,6 +915,8 @@ template <> struct MappingTraits<FormatStyle> {
|
||||
Style.AllowAllArgumentsOnNextLine);
|
||||
IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
|
||||
Style.AllowAllParametersOfDeclarationOnNextLine);
|
||||
IO.mapOptional("AllowBreakBeforeNoexceptSpecifier",
|
||||
Style.AllowBreakBeforeNoexceptSpecifier);
|
||||
IO.mapOptional("AllowShortBlocksOnASingleLine",
|
||||
Style.AllowShortBlocksOnASingleLine);
|
||||
IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
|
||||
@@ -1448,6 +1461,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
|
||||
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
|
||||
LLVMStyle.BreakBeforeConceptDeclarations = FormatStyle::BBCDS_Always;
|
||||
LLVMStyle.BreakBeforeInlineASMColon = FormatStyle::BBIAS_OnlyMultiline;
|
||||
LLVMStyle.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Never;
|
||||
LLVMStyle.BreakBeforeTernaryOperators = true;
|
||||
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
|
||||
LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
|
||||
|
||||
@@ -5654,6 +5654,17 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
|
||||
return !isItAnEmptyLambdaAllowed(Right, ShortLambdaOption);
|
||||
}
|
||||
|
||||
if (Right.is(tok::kw_noexcept) && Right.is(TT_TrailingAnnotation)) {
|
||||
switch (Style.AllowBreakBeforeNoexceptSpecifier) {
|
||||
case FormatStyle::BBNSS_Never:
|
||||
return false;
|
||||
case FormatStyle::BBNSS_Always:
|
||||
return true;
|
||||
case FormatStyle::BBNSS_OnlyWithParen:
|
||||
return Right.Next && Right.Next->is(tok::l_paren);
|
||||
}
|
||||
}
|
||||
|
||||
return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace,
|
||||
tok::kw_class, tok::kw_struct, tok::comment) ||
|
||||
Right.isMemberAccess() ||
|
||||
|
||||
@@ -953,6 +953,14 @@ TEST(ConfigParseTest, ParsesConfiguration) {
|
||||
FormatStyle::RPS_ReturnStatement);
|
||||
CHECK_PARSE("RemoveParentheses: Leave", RemoveParentheses,
|
||||
FormatStyle::RPS_Leave);
|
||||
|
||||
CHECK_PARSE("AllowBreakBeforeNoexceptSpecifier: Always",
|
||||
AllowBreakBeforeNoexceptSpecifier, FormatStyle::BBNSS_Always);
|
||||
CHECK_PARSE("AllowBreakBeforeNoexceptSpecifier: OnlyWithParen",
|
||||
AllowBreakBeforeNoexceptSpecifier,
|
||||
FormatStyle::BBNSS_OnlyWithParen);
|
||||
CHECK_PARSE("AllowBreakBeforeNoexceptSpecifier: Never",
|
||||
AllowBreakBeforeNoexceptSpecifier, FormatStyle::BBNSS_Never);
|
||||
}
|
||||
|
||||
TEST(ConfigParseTest, ParsesConfigurationWithLanguages) {
|
||||
|
||||
@@ -26239,6 +26239,52 @@ TEST_F(FormatTest, RemoveParentheses) {
|
||||
Style);
|
||||
}
|
||||
|
||||
TEST_F(FormatTest, AllowBreakBeforeNoexceptSpecifier) {
|
||||
auto Style = getLLVMStyleWithColumns(35);
|
||||
|
||||
EXPECT_EQ(Style.AllowBreakBeforeNoexceptSpecifier, FormatStyle::BBNSS_Never);
|
||||
verifyFormat("void foo(int arg1,\n"
|
||||
" double arg2) noexcept;",
|
||||
Style);
|
||||
|
||||
// The following line does not fit within the 35 column limit, but that's what
|
||||
// happens with no break allowed.
|
||||
verifyFormat("void bar(int arg1, double arg2) noexcept(\n"
|
||||
" noexcept(baz(arg1)) &&\n"
|
||||
" noexcept(baz(arg2)));",
|
||||
Style);
|
||||
|
||||
verifyFormat("void aVeryLongFunctionNameWithoutAnyArguments() noexcept;",
|
||||
Style);
|
||||
|
||||
Style.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_Always;
|
||||
verifyFormat("void foo(int arg1,\n"
|
||||
" double arg2) noexcept;",
|
||||
Style);
|
||||
|
||||
verifyFormat("void bar(int arg1, double arg2)\n"
|
||||
" noexcept(noexcept(baz(arg1)) &&\n"
|
||||
" noexcept(baz(arg2)));",
|
||||
Style);
|
||||
|
||||
verifyFormat("void aVeryLongFunctionNameWithoutAnyArguments()\n"
|
||||
" noexcept;",
|
||||
Style);
|
||||
|
||||
Style.AllowBreakBeforeNoexceptSpecifier = FormatStyle::BBNSS_OnlyWithParen;
|
||||
verifyFormat("void foo(int arg1,\n"
|
||||
" double arg2) noexcept;",
|
||||
Style);
|
||||
|
||||
verifyFormat("void bar(int arg1, double arg2)\n"
|
||||
" noexcept(noexcept(baz(arg1)) &&\n"
|
||||
" noexcept(baz(arg2)));",
|
||||
Style);
|
||||
|
||||
verifyFormat("void aVeryLongFunctionNameWithoutAnyArguments() noexcept;",
|
||||
Style);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace test
|
||||
} // namespace format
|
||||
|
||||
Reference in New Issue
Block a user