Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -648,9 +648,9 @@ **AllowAllConstructorInitializersOnNextLine** (``bool``) If a constructor definition with a member initializer list doesn't fit on a single line, allow putting all member initializers onto the next - line, if ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is true. + line, if ``ConstructorInitializerAllOnOneLineOrOnePerLine`` is true. Note that this parameter has no effect if - ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is false. + ``ConstructorInitializerAllOnOneLineOrOnePerLine`` is false. .. code-block:: c++ @@ -2141,8 +2141,10 @@ }}} **ConstructorInitializerAllOnOneLineOrOnePerLine** (``bool``) - If the constructor initializers don't fit on a line, put each - initializer on its own line. + If the constructor initializers don't fit on a line, put each initializer + on its own line. + Note that this parameter has no effect if + ``ConstructorInitializerAlwaysOnePerLine`` is true. .. code-block:: c++ @@ -2159,6 +2161,20 @@ return 0; } +**ConstructorInitializerAlwaysOnePerLine** (``bool``) + Always put each constructor initializer on its own line. + + .. code-block:: c++ + + true: + MyClass::MyClass() : + member0(0), + member1(2) {} + + false: + MyClass::MyClass() : + member0(0), member1(2) {} + **ConstructorInitializerIndentWidth** (``unsigned``) The number of characters to use for indentation of constructor initializer lists as well as inheritance lists. Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -507,9 +507,9 @@ /// \brief If a constructor definition with a member initializer list doesn't /// fit on a single line, allow putting all member initializers onto the next - /// line, if ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is true. + /// line, if ``ConstructorInitializerAllOnOneLineOrOnePerLine`` is true. /// Note that this parameter has no effect if - /// ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is false. + /// ``ConstructorInitializerAllOnOneLineOrOnePerLine`` is false. /// \code /// true: /// MyClass::MyClass() : @@ -1894,9 +1894,24 @@ /// \endcode bool CompactNamespaces; + /// Always put each constructor initializer on its own line. + /// \code + /// true: + /// MyClass::MyClass() : + /// member0(0), + /// member1(2) {} + /// + /// false: + /// MyClass::MyClass() : + /// member0(0), member1(2) {} + /// \endcode + bool ConstructorInitializerAlwaysOnePerLine; + // clang-format off - /// If the constructor initializers don't fit on a line, put each - /// initializer on its own line. + /// If the constructor initializers don't fit on a line, put each initializer + /// on its own line. + /// Note that this parameter has no effect if + /// ``ConstructorInitializerAlwaysOnePerLine`` is true. /// \code /// true: /// SomeClass::Constructor() @@ -3424,6 +3439,8 @@ BreakStringLiterals == R.BreakStringLiterals && ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas && BreakInheritanceList == R.BreakInheritanceList && + ConstructorInitializerAlwaysOnePerLine == + R.ConstructorInitializerAlwaysOnePerLine && ConstructorInitializerAllOnOneLineOrOnePerLine == R.ConstructorInitializerAllOnOneLineOrOnePerLine && ConstructorInitializerIndentWidth == Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -633,6 +633,8 @@ IO.mapOptional("ColumnLimit", Style.ColumnLimit); IO.mapOptional("CommentPragmas", Style.CommentPragmas); IO.mapOptional("CompactNamespaces", Style.CompactNamespaces); + IO.mapOptional("ConstructorInitializerAlwaysOnePerLine", + Style.ConstructorInitializerAlwaysOnePerLine); IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine", Style.ConstructorInitializerAllOnOneLineOrOnePerLine); IO.mapOptional("ConstructorInitializerIndentWidth", @@ -1034,6 +1036,7 @@ LLVMStyle.ColumnLimit = 80; LLVMStyle.CommentPragmas = "^ IWYU pragma:"; LLVMStyle.CompactNamespaces = false; + LLVMStyle.ConstructorInitializerAlwaysOnePerLine = false; LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false; LLVMStyle.ConstructorInitializerIndentWidth = 4; LLVMStyle.ContinuationIndentWidth = 4; Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -3739,13 +3739,19 @@ return Style.BreakBeforeConceptDeclarations; return (Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes); } - if (Right.is(TT_CtorInitializerComma) && - Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma && - !Style.ConstructorInitializerAllOnOneLineOrOnePerLine) - return true; - if (Right.is(TT_CtorInitializerColon) && + if (Style.ConstructorInitializerAlwaysOnePerLine) { + if (Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon && + (Left.is(TT_CtorInitializerComma) || Right.is(TT_CtorInitializerColon))) + return true; + + if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon && + Left.isOneOf(TT_CtorInitializerColon, TT_CtorInitializerComma)) + return true; + } + if (Right.isOneOf(TT_CtorInitializerComma, TT_CtorInitializerColon) && Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma && - !Style.ConstructorInitializerAllOnOneLineOrOnePerLine) + (Style.ConstructorInitializerAlwaysOnePerLine || + !Style.ConstructorInitializerAllOnOneLineOrOnePerLine)) return true; // Break only if we have multiple inheritance. if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma && Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -5953,6 +5953,28 @@ FormatStyle OnePerLine = getLLVMStyle(); OnePerLine.ConstructorInitializerAllOnOneLineOrOnePerLine = true; + + OnePerLine.ConstructorInitializerAlwaysOnePerLine = true; + verifyFormat("MyClass::MyClass()\n" + " : a(a),\n" + " b(b),\n" + " c(c) {}", + OnePerLine); + verifyFormat("MyClass::MyClass()\n" + " : a(a), // comment\n" + " b(b),\n" + " c(c) {}", + OnePerLine); + verifyFormat("MyClass::MyClass(int a)\n" + " : b(a), // comment\n" + " c(a + 1) { // lined up\n" + "}", + OnePerLine); + verifyFormat("Constructor()\n" + " : a(b, b, b) {}", + OnePerLine); + OnePerLine.ConstructorInitializerAlwaysOnePerLine = false; + OnePerLine.AllowAllParametersOfDeclarationOnNextLine = false; verifyFormat("SomeClass::Constructor()\n" " : aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n" @@ -6319,6 +6341,28 @@ FormatStyle OnePerLine = Style; OnePerLine.ConstructorInitializerAllOnOneLineOrOnePerLine = true; + + OnePerLine.ConstructorInitializerAlwaysOnePerLine = true; + verifyFormat("MyClass::MyClass() :\n" + " a(a),\n" + " b(b),\n" + " c(c) {}", + OnePerLine); + verifyFormat("MyClass::MyClass() :\n" + " a(a), // comment\n" + " b(b),\n" + " c(c) {}", + OnePerLine); + verifyFormat("MyClass::MyClass(int a) :\n" + " b(a), // comment\n" + " c(a + 1) { // lined up\n" + "}", + OnePerLine); + verifyFormat("Constructor() :\n" + " a(b, b, b) {}", + OnePerLine); + OnePerLine.ConstructorInitializerAlwaysOnePerLine = false; + OnePerLine.AllowAllConstructorInitializersOnNextLine = false; verifyFormat("SomeClass::Constructor() :\n" " aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n" @@ -18122,6 +18166,7 @@ CHECK_PARSE_BOOL(BreakBeforeTernaryOperators); CHECK_PARSE_BOOL(BreakStringLiterals); CHECK_PARSE_BOOL(CompactNamespaces); + CHECK_PARSE_BOOL(ConstructorInitializerAlwaysOnePerLine); CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine); CHECK_PARSE_BOOL(DeriveLineEnding); CHECK_PARSE_BOOL(DerivePointerAlignment); @@ -19102,6 +19147,37 @@ Style.ConstructorInitializerAllOnOneLineOrOnePerLine = true; Style.ConstructorInitializerIndentWidth = 4; + + Style.ConstructorInitializerAlwaysOnePerLine = true; + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterFunction = true; + Style.BraceWrapping.SplitEmptyFunction = false; + verifyFormat("MyClass::MyClass()\n" + " : a(a)\n" + " , b(b)\n" + " , c(c)\n" + "{}", + Style); + verifyFormat("MyClass::MyClass()\n" + " : a(a) // comment\n" + " , b(b)\n" + " , c(c)\n" + "{}", + Style); + verifyFormat("MyClass::MyClass(int a)\n" + " : b(a) // comment\n" + " , c(a + 1) // lined up\n" + "{}", + Style); + verifyFormat("Constructor()\n" + " : a(b, b, b)\n" + "{}", + Style); + Style.ConstructorInitializerAlwaysOnePerLine = false; + Style.BreakBeforeBraces = FormatStyle::BS_Attach; + Style.BraceWrapping.AfterFunction = false; + Style.BraceWrapping.SplitEmptyFunction = true; + verifyFormat("SomeClass::Constructor() : aaaaaaaa(aaaaaaaa) {}", Style); verifyFormat( "SomeClass::Constructor() : aaaaa(aaaaa), aaaaa(aaaaa), aaaaa(aaaaa)\n",