https://github.com/khei4 updated https://github.com/llvm/llvm-project/pull/93634
>From 5d409bcd0966a7581effdf1488c2f4cfa32aebc6 Mon Sep 17 00:00:00 2001 From: Kohei Asano <kohei.as...@sony.com> Date: Mon, 3 Jun 2024 09:15:44 +0900 Subject: [PATCH] [clang-format] add an option to insert a space only for empty braces --- clang/docs/ClangFormatStyleOptions.rst | 78 +++++++++++++++++++- clang/include/clang/Format/Format.h | 82 +++++++++++++++++++-- clang/lib/Format/Format.cpp | 36 ++++++++- clang/lib/Format/TokenAnnotator.cpp | 12 ++- clang/lib/Format/UnwrappedLineFormatter.cpp | 6 +- clang/unittests/Format/ConfigParseTest.cpp | 9 ++- clang/unittests/Format/FormatTest.cpp | 42 ++++++++++- 7 files changed, 246 insertions(+), 19 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 6d092219877f9..bf0088203dd54 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -6028,12 +6028,84 @@ the configuration (without a prefix: ``Auto``). **SpaceInEmptyBlock** (``Boolean``) :versionbadge:`clang-format 10` :ref:`¶ <SpaceInEmptyBlock>` If ``true``, spaces will be inserted into ``{}``. + This option is **deprecated**. The previous behavior is preserved by using + ``SpaceInEmptyBraces`` with ``Custom`` and by setting Record + ``SpaceInEmptyBracesOptions`` to ``true``. + +.. _SpaceInEmptyBlock: + +**SpaceInEmptyBlock** (``Boolean``) :versionbadge:`clang-format 10` :ref:`¶ <SpaceInEmptyBlock>` + If ``true``, spaces will be inserted into ``{}`` for record declarations + and blocks. This option is **deprecated**. The previous behavior is + preserved by using ``SpaceInEmptyBraces`` with ``Custom`` and by setting + ``Record`` on ``SpaceInEmptyBracesOptions`` to ``true``. + +.. _SpaceInEmptyBraces: + +**SpaceInEmptyBraces** (``SpaceInEmptyBracesStyle``) :versionbadge:`clang-format 19` :ref:`¶ <SpaceInEmptyBraces>` + Defines in which cases spaces will be inserted in empty braces. + + Possible values: + + * ``SIEBO_Never`` (in configuration: ``Never``) + Never put a space in empty braces. + + .. code-block:: c++ + + T x{}; + while (true) {} + struct Unit {}; + + * ``SIEBO_Custom`` (in configuration: ``Custom``) + Configure each individual space in empty braces in + `SpacesInEmptyBracesOptions`. + + + +.. _SpaceInEmptyBracesOptions: + +**SpaceInEmptyBracesOptions** (``SpaceInEmptyBracesCustom``) :versionbadge:`clang-format 19` :ref:`¶ <SpaceInEmptyBracesOptions>` + Control of individual spaces in empty braces. + + If ``SpaceInEmptyBraces`` is set to ``Custom``, use this to specify + how each individual space in empty braces case should be handled. + Otherwise, this is ignored. + + .. code-block:: yaml + + # Example of usage: + SpaceInEmptyBraces: Custom + SpaceInEmptyBracesOptions: + Block: true + Record: true + + Nested configuration flags: + + Precise control over the spacing in empty braces. .. code-block:: c++ - true: false: - void f() { } vs. void f() {} - while (true) { } while (true) {} + # Should be declared this way: + SpaceInEmptyBraces: Custom + SpaceInEmptyBracesOptions: + Block: true + Record: true + + * ``bool Block`` Put a space in empty braces of code blocks and record declarations. + + .. code-block:: c++ + + true: false: + int f() { } vs. int f() {} + struct Unit {}; struct Unit {}; + + * ``bool InitList`` Put a space in empty braces of initializer list. + + .. code-block:: c++ + + true: false: + T x{ }; vs. T x{}; + .. _SpaceInEmptyParentheses: diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 274b45d1bc586..b63ddd7e2b92b 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -4487,13 +4487,11 @@ struct FormatStyle { bool SpaceBeforeRangeBasedForLoopColon; /// If ``true``, spaces will be inserted into ``{}``. - /// \code - /// true: false: - /// void f() { } vs. void f() {} - /// while (true) { } while (true) {} - /// \endcode + /// This option is **deprecated**. The previous behavior is preserved by using + /// ``SpaceInEmptyBraces`` with ``Custom`` and by setting Record + /// ``SpaceInEmptyBracesOptions`` to ``true``. /// \version 10 - bool SpaceInEmptyBlock; + // bool SpaceInEmptyBlock; /// If ``true``, spaces may be inserted into ``()``. /// This option is **deprecated**. See ``InEmptyParentheses`` of @@ -4715,6 +4713,75 @@ struct FormatStyle { /// \version 17 SpacesInParensCustom SpacesInParensOptions; + /// Different ways to put a space in empty braces. + enum SpaceInEmptyBracesStyle : int8_t { + /// Never put a space in empty braces. + /// \code + /// T x{}; + /// while (true) {} + /// struct Unit {}; + /// \endcode + SIEBO_Never, + /// Configure each individual space in empty braces in + /// `SpacesInEmptyBracesOptions`. + SIEBO_Custom, + }; + + /// Defines in which cases spaces will be inserted in empty braces. + /// \version 19 + SpaceInEmptyBracesStyle SpaceInEmptyBraces; + + /// Precise control over the spacing in empty braces. + /// \code + /// # Should be declared this way: + /// SpaceInEmptyBraces: Custom + /// SpaceInEmptyBracesOptions: + /// Block: true + /// Record: true + /// \endcode + struct SpaceInEmptyBracesCustom { + /// Put a space in empty braces of code blocks and record declarations. + /// \code + /// true: false: + /// int f() { } vs. int f() {} + /// struct Unit {}; struct Unit {}; + /// \endcode + bool Block; + /// Put a space in empty braces of initializer list. + /// \code + /// true: false: + /// T x{ }; vs. T x{}; + /// \endcode + bool InitList; + + SpaceInEmptyBracesCustom() : Block(false), InitList(false) {} + + SpaceInEmptyBracesCustom(bool Block, bool InitList) + : Block(Block), InitList(InitList) {} + + bool operator==(const SpaceInEmptyBracesCustom &R) const { + return Block == R.Block && InitList == R.InitList; + } + bool operator!=(const SpaceInEmptyBracesCustom &R) const { + return !(*this == R); + } + }; + + /// Control of individual spaces in empty braces. + /// + /// If ``SpaceInEmptyBraces`` is set to ``Custom``, use this to specify + /// how each individual space in empty braces case should be handled. + /// Otherwise, this is ignored. + /// \code{.yaml} + /// # Example of usage: + /// SpaceInEmptyBraces: Custom + /// SpaceInEmptyBracesOptions: + /// Block: true + /// Record: true + /// \endcode + /// \version 19 + SpaceInEmptyBracesCustom SpaceInEmptyBracesOptions; + /// If ``true``, spaces will be inserted after ``[`` and before ``]``. /// Lambdas without arguments or unspecified size array declarations will not /// be affected. @@ -5088,7 +5155,8 @@ struct FormatStyle { SpaceBeforeRangeBasedForLoopColon == R.SpaceBeforeRangeBasedForLoopColon && SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets && - SpaceInEmptyBlock == R.SpaceInEmptyBlock && + SpaceInEmptyBraces == R.SpaceInEmptyBraces && + SpaceInEmptyBracesOptions == R.SpaceInEmptyBracesOptions && SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments && SpacesInAngles == R.SpacesInAngles && SpacesInContainerLiterals == R.SpacesInContainerLiterals && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 9cba0c2614eef..8c6f8c440d73d 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -718,6 +718,21 @@ template <> struct MappingTraits<FormatStyle::SpacesInLineComment> { } }; +template <> struct MappingTraits<FormatStyle::SpaceInEmptyBracesCustom> { + static void mapping(IO &IO, FormatStyle::SpaceInEmptyBracesCustom &Space) { + IO.mapOptional("Block", Space.Block); + IO.mapOptional("InitList", Space.InitList); + } +}; + +template <> +struct ScalarEnumerationTraits<FormatStyle::SpaceInEmptyBracesStyle> { + static void enumeration(IO &IO, FormatStyle::SpaceInEmptyBracesStyle &Value) { + IO.enumCase(Value, "Never", FormatStyle::SIEBO_Never); + IO.enumCase(Value, "Custom", FormatStyle::SIEBO_Custom); + } +}; + template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> { static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) { IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts); @@ -849,6 +864,7 @@ template <> struct MappingTraits<FormatStyle> { bool UseCRLF = false; bool SpaceInEmptyParentheses = false; + bool SpaceInEmptyBlock = false; bool SpacesInConditionalStatement = false; bool SpacesInCStyleCastParentheses = false; bool SpacesInParentheses = false; @@ -875,6 +891,7 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("SpaceAfterControlStatementKeyword", Style.SpaceBeforeParens); IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses); + IO.mapOptional("SpaceInEmptyBlock", SpaceInEmptyBlock); IO.mapOptional("SpacesInConditionalStatement", SpacesInConditionalStatement); IO.mapOptional("SpacesInCStyleCastParentheses", @@ -1091,7 +1108,6 @@ template <> struct MappingTraits<FormatStyle> { Style.SpaceBeforeRangeBasedForLoopColon); IO.mapOptional("SpaceBeforeSquareBrackets", Style.SpaceBeforeSquareBrackets); - IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock); IO.mapOptional("SpacesBeforeTrailingComments", Style.SpacesBeforeTrailingComments); IO.mapOptional("SpacesInAngles", Style.SpacesInAngles); @@ -1099,6 +1115,9 @@ template <> struct MappingTraits<FormatStyle> { Style.SpacesInContainerLiterals); IO.mapOptional("SpacesInLineCommentPrefix", Style.SpacesInLineCommentPrefix); + IO.mapOptional("SpaceInEmptyBraces", Style.SpaceInEmptyBraces); + IO.mapOptional("SpaceInEmptyBracesOptions", + Style.SpaceInEmptyBracesOptions); IO.mapOptional("SpacesInParens", Style.SpacesInParens); IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions); IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets); @@ -1193,6 +1212,13 @@ template <> struct MappingTraits<FormatStyle> { } Style.SpacesInParens = FormatStyle::SIPO_Custom; } + + if (Style.SpaceInEmptyBraces != FormatStyle::SIEBO_Custom && + SpaceInEmptyBlock) { + Style.SpaceInEmptyBraces = FormatStyle::SIEBO_Custom; + Style.SpaceInEmptyBracesOptions.Block = true; + Style.SpaceInEmptyBracesOptions.InitList = false; + } } }; @@ -1562,7 +1588,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true; LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true; LLVMStyle.SpaceBeforeSquareBrackets = false; - LLVMStyle.SpaceInEmptyBlock = false; + LLVMStyle.SpaceInEmptyBraces = FormatStyle::SIEBO_Never; LLVMStyle.SpacesBeforeTrailingComments = 1; LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never; LLVMStyle.SpacesInContainerLiterals = true; @@ -1863,7 +1889,11 @@ FormatStyle getWebKitStyle() { Style.ObjCSpaceAfterProperty = true; Style.PointerAlignment = FormatStyle::PAS_Left; Style.SpaceBeforeCpp11BracedList = true; - Style.SpaceInEmptyBlock = true; + Style.SpaceInEmptyBraces = FormatStyle::SIEBO_Custom; + Style.SpaceInEmptyBracesOptions.Block = true; + Style.SpaceInEmptyBracesOptions.InitList = true; + Style.SpacesInParensOptions.InEmptyParentheses = false; + Style.SpacesInParensOptions.Other = false; return Style; } diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 7c4c76a91f2c5..c94a8ad2bb571 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4337,13 +4337,21 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return Left.is(tok::hash); if (Left.isOneOf(tok::hashhash, tok::hash)) return Right.is(tok::hash); + // FIXME: separate function and other block? if (Left.is(BK_Block) && Right.is(tok::r_brace) && Right.MatchingParen == &Left && Line.Children.empty()) { - return Style.SpaceInEmptyBlock; + return Style.SpaceInEmptyBracesOptions.Block; } - if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) || + if (Style.SpaceInEmptyBracesOptions.InitList && (Left.is(tok::l_brace) && Left.isNot(BK_Block) && Right.is(tok::r_brace) && Right.isNot(BK_Block))) { + return Style.SpaceInEmptyBracesOptions.InitList; + } + if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) || + ((Style.SpaceInEmptyBraces == FormatStyle::SIEBO_Never || + Style.SpaceInEmptyBracesOptions.InitList) && + Left.is(tok::l_brace) && Left.isNot(BK_Block) && + Right.is(tok::r_brace) && Right.isNot(BK_Block))) { return Style.SpacesInParensOptions.InEmptyParentheses; } if (Style.SpacesInParensOptions.InConditionalStatements) { diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 4d53361aaf333..e1a17f29b627d 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -824,7 +824,11 @@ class LineJoiner { if (ShouldMerge()) { // We merge empty blocks even if the line exceeds the column limit. Tok->SpacesRequiredBefore = - (Style.SpaceInEmptyBlock || Line.Last->is(tok::comment)) ? 1 : 0; + ((Style.SpaceInEmptyBraces == FormatStyle::SIEBO_Custom && + Style.SpaceInEmptyBracesOptions.Block) || + Line.Last->is(tok::comment)) + ? 1 + : 0; Tok->CanBreakBefore = true; return 1; } else if (Limit != 0 && !Line.startsWithNamespace() && diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 82e72f08ffb5e..44d418b7ed575 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -187,7 +187,6 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(RemoveSemicolon); CHECK_PARSE_BOOL(SkipMacroDefinitionBody); CHECK_PARSE_BOOL(SpacesInSquareBrackets); - CHECK_PARSE_BOOL(SpaceInEmptyBlock); CHECK_PARSE_BOOL(SpacesInContainerLiterals); CHECK_PARSE_BOOL(SpaceAfterCStyleCast); CHECK_PARSE_BOOL(SpaceAfterTemplateKeyword); @@ -235,6 +234,8 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterOverloadedOperator); CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterPlacementOperator); CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, BeforeNonEmptyParentheses); + CHECK_PARSE_NESTED_BOOL(SpaceInEmptyBracesOptions, Block); + CHECK_PARSE_NESTED_BOOL(SpaceInEmptyBracesOptions, InitList); CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InCStyleCasts); CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InConditionalStatements); CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InEmptyParentheses); @@ -636,6 +637,12 @@ TEST(ConfigParseTest, ParsesConfiguration) { Style.SpacesInParens = FormatStyle::SIPO_Never; Style.SpacesInParensOptions = {}; + // For backward compatibility + Style.SpaceInEmptyBraces = FormatStyle::SIEBO_Never; + Style.SpaceInEmptyBracesOptions = {}; + CHECK_PARSE("SpaceInEmptyBlock: true", SpaceInEmptyBracesOptions, + FormatStyle::SpaceInEmptyBracesCustom(true, false)); + Style.ColumnLimit = 123; FormatStyle BaseStyle = getLLVMStyle(); CHECK_PARSE("BasedOnStyle: LLVM", ColumnLimit, BaseStyle.ColumnLimit); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 2f0c0f0266774..6961d863a3007 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -6961,7 +6961,8 @@ TEST_F(FormatTest, PutEmptyBlocksIntoOneLine) { verifyFormat("enum E {};"); verifyFormat("enum E {}"); FormatStyle Style = getLLVMStyle(); - Style.SpaceInEmptyBlock = true; + Style.SpaceInEmptyBraces = FormatStyle::SIEBO_Custom; + Style.SpaceInEmptyBracesOptions.Block = true; verifyFormat("void f() { }", "void f() {}", Style); Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; verifyFormat("{ }", Style); @@ -6989,7 +6990,8 @@ TEST_F(FormatTest, PutEmptyBlocksIntoOneLine) { Style); Style = getLLVMStyle(FormatStyle::LK_CSharp); - Style.SpaceInEmptyBlock = true; + Style.SpaceInEmptyBraces = FormatStyle::SIEBO_Custom; + Style.SpaceInEmptyBracesOptions.Block = true; verifyFormat("Event += () => { };", Style); } @@ -14029,6 +14031,42 @@ TEST_F(FormatTest, LayoutCxx11BraceInitializers) { verifyFormat("vector< int > x{ };", SpaceBetweenBraces); } +TEST_F(FormatTest, EmptyBracesTest) { + FormatStyle SpaceInEmptyBraces = getLLVMStyle(); + SpaceInEmptyBraces.SpaceInEmptyBraces = FormatStyle::SIEBO_Never; + verifyFormat("void f() {}\n" + "struct Unit {};\n" + "int x{};\n", + SpaceInEmptyBraces); + + SpaceInEmptyBraces.SpaceInEmptyBraces = FormatStyle::SIEBO_Custom; + SpaceInEmptyBraces.SpaceInEmptyBracesOptions.Block = true; + SpaceInEmptyBraces.SpaceInEmptyBracesOptions.InitList = false; + verifyFormat("void f() { }\n" + "struct Unit { };\n" + "int x{};\n", + SpaceInEmptyBraces); + + SpaceInEmptyBraces.SpaceInEmptyBraces = FormatStyle::SIEBO_Custom; + SpaceInEmptyBraces.SpaceInEmptyBracesOptions.Block = false; + SpaceInEmptyBraces.SpaceInEmptyBracesOptions.InitList = true; + verifyFormat("void f() {}\n" + "struct Unit {};\n" + "int x{ };\n", + SpaceInEmptyBraces); + + // SpacesInParensOptions.InEmptyParentheses can be overwritten. + SpaceInEmptyBraces.SpaceInEmptyBraces = FormatStyle::SIEBO_Custom; + SpaceInEmptyBraces.SpaceInEmptyBracesOptions.Block = false; + SpaceInEmptyBraces.SpaceInEmptyBracesOptions.InitList = false; + SpaceInEmptyBraces.SpacesInParens = FormatStyle::SIPO_Custom; + SpaceInEmptyBraces.SpacesInParensOptions.InEmptyParentheses = true; + verifyFormat("void f( ) {}\n" + "struct Unit {};\n" + "int x{};\n", + SpaceInEmptyBraces); +} + TEST_F(FormatTest, FormatsBracedListsInColumnLayout) { verifyFormat("vector<int> x = {1, 22, 333, 4444, 55555, 666666, 7777777,\n" " 1, 22, 333, 4444, 55555, 666666, 7777777,\n" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits