Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -1339,6 +1339,23 @@ bar(); }); + * ``bool BeforeClassStructInit`` Wrap before class / struct initialization. + + .. code-block:: c++ + + true: + struct new_struct struct_name = + { + a = 1, + b = 2, + }; + + false: + struct new_struct struct_name = { + a = 1, + b = 2, + }; + * ``bool BeforeWhile`` Wrap before ``while``. .. code-block:: c++ Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -1608,6 +1608,22 @@ /// }); /// \endcode bool BeforeLambdaBody; + /// Wrap before class / struct initialization. + /// \code + /// true: + /// struct new_struct struct_name = + /// { + /// a = 1, + /// b = 2, + /// }; + /// + /// false: + /// struct new_struct struct_name = { + /// a = 1, + /// b = 2, + /// }; + /// \endcode + bool BeforeClassStructInit; /// Wrap before ``while``. /// \code /// true: Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -720,6 +720,8 @@ IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch); IO.mapOptional("BeforeElse", Wrapping.BeforeElse); IO.mapOptional("BeforeLambdaBody", Wrapping.BeforeLambdaBody); + IO.mapOptional("BeforeClassStructInit", + Wrapping.BeforeClassStructInit); IO.mapOptional("BeforeWhile", Wrapping.BeforeWhile); IO.mapOptional("IndentBraces", Wrapping.IndentBraces); IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction); @@ -831,6 +833,7 @@ /*BeforeCatch=*/false, /*BeforeElse=*/false, /*BeforeLambdaBody=*/false, + /*BeforeClassStructInit=*/false, /*BeforeWhile=*/false, /*IndentBraces=*/false, /*SplitEmptyFunction=*/true, @@ -904,6 +907,7 @@ /*BeforeCatch=*/true, /*BeforeElse=*/true, /*BeforeLambdaBody=*/false, + /*BeforeClassStructInit=*/false, /*BeforeWhile=*/true, /*IndentBraces=*/true, /*SplitEmptyFunction=*/true, @@ -967,6 +971,7 @@ /*BeforeCatch=*/false, /*BeforeElse=*/false, /*BeforeLambdaBody=*/false, + /*BeforeClassStructInit=*/false, /*BeforeWhile=*/false, /*IndentBraces=*/false, /*SplitEmptyFunction=*/true, Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -2702,7 +2702,11 @@ nextToken(); } } - if (FormatTok->Tok.is(tok::l_brace)) { + if ((InitialToken.is(tok::kw_struct) || InitialToken.is(tok::kw_class)) && + FormatTok->Tok.is(tok::equal) && Style.BraceWrapping.BeforeClassStructInit) { + nextToken(); + FormatTok->MustBreakBefore = true; + } else if (FormatTok->Tok.is(tok::l_brace)) { if (ParseAsExpr) { parseChildBlock(); } else { Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -5069,6 +5069,114 @@ format(Input, Style)); } +TEST_F(FormatTest, BreakBeforeClassStructInit) { + FormatStyle Style = getLLVMStyle(); + Style.ColumnLimit = 80; + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.BeforeClassStructInit = true; + Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_No; + verifyFormat("struct new_struct struct_name =\n" + " {a = 1};", + Style); + verifyFormat("class new_class class_name =\n" + " {a = 1};", + Style); + verifyFormat("struct new_struct struct_name =\n" + " {a = 1, b = 2};", + Style); + verifyFormat("struct new_struct struct_name =\n" + " {\n" + " a = 1,\n" + " b = 2,\n" + " };", + Style); + verifyFormat("typedef struct Foo =\n" + " {\n" + " a = 1,\n" + " b = 2,\n" + " };", + Style); + verifyFormat("static constexpr struct Foo =\n" + " {\n" + " a = 1,\n" + " b = 2,\n" + " };", + Style); + verifyFormat("template <> struct Foo =\n" + " {\n" + " a = 1,\n" + " b = 2,\n" + " };", + Style); + verifyFormat("struct =\n" + " {\n" + " a = 1,\n" + " b = 2,\n" + " };", + Style); + // BeforeClassStructInit doesn't affect on AfterStruct behavior + Style.BraceWrapping.AfterStruct = false; + verifyFormat("struct new_struct struct_name {\n" + " a = 1;\n" + " b = 2;\n" + "};", + Style); + Style.BraceWrapping.AfterStruct = true; + verifyFormat("struct new_struct struct_name\n" + "{\n" + " a = 1;\n" + " b = 2;\n" + "};", + Style); + Style.BraceWrapping.BeforeClassStructInit = false; + verifyFormat("struct new_struct struct_name = {a = 1};", Style); + verifyFormat("struct new_struct struct_name = {a = 1, b = 2};", Style); + verifyFormat("struct new_struct struct_name = {\n" + " a = 1,\n" + " b = 2,\n" + "};", + Style); + verifyFormat("class new_class class_name = {\n" + " a = 1,\n" + " b = 2,\n" + "};", + Style); + verifyFormat("typedef struct Foo = {\n" + " a = 1,\n" + " b = 2,\n" + "};", + Style); + verifyFormat("static constexpr struct Foo = {\n" + " a = 1,\n" + " b = 2,\n" + "};", + Style); + verifyFormat("template <> struct Foo = {\n" + " a = 1,\n" + " b = 2,\n" + "};", + Style); + verifyFormat("struct = {\n" + " a = 1,\n" + " b = 2,\n" + "};", + Style); + // BeforeClassStructInit doesn't affect on AfterStruct behavior + Style.BraceWrapping.AfterStruct = false; + verifyFormat("struct new_struct struct_name {\n" + " a = 1;\n" + " b = 2;\n" + "};", + Style); + Style.BraceWrapping.AfterStruct = true; + verifyFormat("struct new_struct struct_name\n" + "{\n" + " a = 1;\n" + " b = 2;\n" + "};", + Style); +} + TEST_F(FormatTest, BreakConstructorInitializersAfterColon) { FormatStyle Style = getLLVMStyle(); Style.BreakConstructorInitializers = FormatStyle::BCIS_AfterColon; @@ -16328,6 +16436,7 @@ CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeCatch); CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeElse); CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeLambdaBody); + CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeClassStructInit); CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeWhile); CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces); CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunction);