Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -3888,6 +3888,23 @@ bbbbbbbbbbbbbbbbbbbb(), cccccccccccccccccccc() + * ``PCIS_NextLineOnly`` (in configuration: ``NextLineOnly``) + Put all constructor initializers on the next line if they fit. + Otherwise, put each one on its own line. + + .. code-block:: c++ + + Constructor() + : a(), b() + + Constructor() + : aaaaaaaaaaaaaaaaaaaa(), bbbbbbbbbbbbbbbbbbbb(), ddddddddddddd() + + Constructor() + : aaaaaaaaaaaaaaaaaaaa(), + bbbbbbbbbbbbbbbbbbbb(), + cccccccccccccccccccc() + .. _PenaltyBreakAssignment: Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -2929,6 +2929,21 @@ /// cccccccccccccccccccc() /// \endcode PCIS_NextLine, + /// Put all constructor initializers on the next line if they fit. + /// Otherwise, put each one on its own line. + /// \code + /// Constructor() + /// : a(), b() + /// + /// Constructor() + /// : aaaaaaaaaaaaaaaaaaaa(), bbbbbbbbbbbbbbbbbbbb(), ddddddddddddd() + /// + /// Constructor() + /// : aaaaaaaaaaaaaaaaaaaa(), + /// bbbbbbbbbbbbbbbbbbbb(), + /// cccccccccccccccccccc() + /// \endcode + PCIS_NextLineOnly, }; /// The pack constructor initializers style to use. Index: clang/lib/Format/ContinuationIndenter.cpp =================================================================== --- clang/lib/Format/ContinuationIndenter.cpp +++ clang/lib/Format/ContinuationIndenter.cpp @@ -1053,13 +1053,16 @@ bool PreviousIsBreakingCtorInitializerColon = PreviousNonComment && PreviousNonComment->is(TT_CtorInitializerColon) && Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon; + bool AllowAllConstructorInitializersOnNextLine = + Style.PackConstructorInitializers == FormatStyle::PCIS_NextLine || + Style.PackConstructorInitializers == FormatStyle::PCIS_NextLineOnly; if (!(Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) || PreviousIsBreakingCtorInitializerColon) || (!Style.AllowAllParametersOfDeclarationOnNextLine && State.Line->MustBeDeclaration) || (!Style.AllowAllArgumentsOnNextLine && !State.Line->MustBeDeclaration) || - (Style.PackConstructorInitializers != FormatStyle::PCIS_NextLine && + (!AllowAllConstructorInitializersOnNextLine && PreviousIsBreakingCtorInitializerColon) || Previous.is(TT_DictLiteral)) { CurrentState.BreakBeforeParameter = true; @@ -1069,7 +1072,7 @@ // and we allow all arguments on the next line, we should not break // before the next parameter. if (PreviousIsBreakingCtorInitializerColon && - Style.PackConstructorInitializers == FormatStyle::PCIS_NextLine) { + AllowAllConstructorInitializersOnNextLine) { CurrentState.BreakBeforeParameter = false; } } @@ -1401,7 +1404,8 @@ if (Style.PackConstructorInitializers > FormatStyle::PCIS_BinPack) { CurrentState.AvoidBinPacking = true; CurrentState.BreakBeforeParameter = - Style.PackConstructorInitializers != FormatStyle::PCIS_NextLine; + Style.PackConstructorInitializers != FormatStyle::PCIS_NextLine && + Style.PackConstructorInitializers != FormatStyle::PCIS_NextLineOnly; } else { CurrentState.BreakBeforeParameter = false; } Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -443,6 +443,7 @@ IO.enumCase(Value, "BinPack", FormatStyle::PCIS_BinPack); IO.enumCase(Value, "CurrentLine", FormatStyle::PCIS_CurrentLine); IO.enumCase(Value, "NextLine", FormatStyle::PCIS_NextLine); + IO.enumCase(Value, "OnlyNextLine", FormatStyle::PCIS_NextLineOnly); } }; Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -4576,6 +4576,18 @@ Right.isOneOf(TT_CtorInitializerComma, TT_CtorInitializerColon)) { return true; } + if (Style.PackConstructorInitializers == FormatStyle::PCIS_NextLineOnly) { + if ((Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon || + Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma) && + Right.is(TT_CtorInitializerColon)) { + return true; + } + + if (Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon && + Left.is(TT_CtorInitializerColon)) { + return true; + } + } // Break only if we have multiple inheritance. if (Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma && Right.is(TT_InheritanceComma)) { Index: clang/unittests/Format/ConfigParseTest.cpp =================================================================== --- clang/unittests/Format/ConfigParseTest.cpp +++ clang/unittests/Format/ConfigParseTest.cpp @@ -400,6 +400,8 @@ PackConstructorInitializers, FormatStyle::PCIS_CurrentLine); CHECK_PARSE("PackConstructorInitializers: NextLine", PackConstructorInitializers, FormatStyle::PCIS_NextLine); + CHECK_PARSE("PackConstructorInitializers: OnlyNextLine", + PackConstructorInitializers, FormatStyle::PCIS_NextLineOnly); // For backward compatibility: CHECK_PARSE("BasedOnStyle: Google\n" "ConstructorInitializerAllOnOneLineOrOnePerLine: true\n" Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -7289,6 +7289,19 @@ Style); verifyFormat("Constructor() : a(a), b(b) {}", Style); + Style.PackConstructorInitializers = FormatStyle::PCIS_NextLineOnly; + verifyFormat("Constructor()\n" + " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + verifyFormat("Constructor()\n" + " : a(a), b(b) {}", + Style); + verifyFormat("Constructor()\n" + " : aaaaaaaaaaaaaaaaaaaa(a)\n" + " , bbbbbbbbbbbbbbbbbbbbb(b)\n" + " , cccccccccccccccccccccc(c) {}", + Style); + Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; Style.PackConstructorInitializers = FormatStyle::PCIS_NextLine; verifyFormat("Constructor()\n" @@ -7301,6 +7314,19 @@ " bbbbbbbbbbbbbbbbbbbbb(b) {}", Style); + Style.PackConstructorInitializers = FormatStyle::PCIS_NextLineOnly; + verifyFormat("Constructor()\n" + " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + verifyFormat("Constructor()\n" + " : a(a), b(b) {}", + Style); + verifyFormat("Constructor()\n" + " : aaaaaaaaaaaaaaaaaaaa(a),\n" + " bbbbbbbbbbbbbbbbbbbbb(b),\n" + " cccccccccccccccccccccc(c) {}", + Style); + Style.BreakConstructorInitializers = FormatStyle::BCIS_AfterColon; Style.PackConstructorInitializers = FormatStyle::PCIS_NextLine; verifyFormat("Constructor() :\n" @@ -7312,6 +7338,19 @@ " aaaaaaaaaaaaaaaaaa(a),\n" " bbbbbbbbbbbbbbbbbbbbb(b) {}", Style); + + Style.PackConstructorInitializers = FormatStyle::PCIS_NextLineOnly; + verifyFormat("Constructor() :\n" + " aaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + verifyFormat("Constructor() :\n" + " a(a), b(b) {}", + Style); + verifyFormat("Constructor() :\n" + " aaaaaaaaaaaaaaaaaaaa(a),\n" + " bbbbbbbbbbbbbbbbbbbbb(b),\n" + " cccccccccccccccccccccc(c) {}", + Style); } // Test interactions between AllowAllParametersOfDeclarationOnNextLine and @@ -7319,6 +7358,7 @@ // BreakConstructorInitializers modes Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; Style.AllowAllParametersOfDeclarationOnNextLine = true; + Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine; verifyFormat("SomeClassWithALongName::Constructor(\n" " int aaaaaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbbb)\n" " : aaaaaaaaaaaaaaaaaaaa(a)\n" @@ -7333,6 +7373,14 @@ " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", Style); + Style.PackConstructorInitializers = FormatStyle::PCIS_NextLineOnly; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa,\n" + " int bbbbbbbbbbbbb,\n" + " int cccccccccccccccc)\n" + " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + Style.AllowAllParametersOfDeclarationOnNextLine = false; Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine; verifyFormat("SomeClassWithALongName::Constructor(\n" @@ -7359,6 +7407,14 @@ " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", Style); + Style.PackConstructorInitializers = FormatStyle::PCIS_NextLineOnly; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa,\n" + " int bbbbbbbbbbbbb,\n" + " int cccccccccccccccc)\n" + " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + Style.AllowAllParametersOfDeclarationOnNextLine = false; Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine; verifyFormat("SomeClassWithALongName::Constructor(\n" @@ -7384,6 +7440,14 @@ " aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", Style); + Style.PackConstructorInitializers = FormatStyle::PCIS_NextLineOnly; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa,\n" + " int bbbbbbbbbbbbb,\n" + " int cccccccccccccccc) :\n" + " aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + Style.AllowAllParametersOfDeclarationOnNextLine = false; Style.PackConstructorInitializers = FormatStyle::PCIS_CurrentLine; verifyFormat("SomeClassWithALongName::Constructor(\n" @@ -7587,6 +7651,16 @@ " aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}", Style); + Style.PackConstructorInitializers = FormatStyle::PCIS_NextLineOnly; + verifyFormat( + "SomeClass::Constructor() :\n" + " aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}", + Style); + verifyFormat( + "SomeClass::Constructor() : // NOLINT\n" + " aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}", + Style); + Style.PackConstructorInitializers = FormatStyle::PCIS_BinPack; verifyFormat( "SomeClass::Constructor() :\n" @@ -7845,6 +7919,8 @@ input += " a,\n"; input += " a) {}"; verifyFormat(input, OnePerLine); + OnePerLine.PackConstructorInitializers = FormatStyle::PCIS_NextLineOnly; + verifyFormat(input, OnePerLine); } #endif @@ -20884,6 +20960,19 @@ "SomeClass::Constructor()\n" " : aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa) {}", Style); + Style.PackConstructorInitializers = FormatStyle::PCIS_NextLineOnly; + verifyFormat("SomeClass::Constructor()\n" + " : aaaaaaaa(aaaaaaaa) {}", + Style); + verifyFormat("SomeClass::Constructor()\n" + " : aaaaa(aaaaa), aaaaa(aaaaa), aaaaa(aaaaa)\n", + Style); + verifyFormat( + "SomeClass::Constructor()\n" + " : aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa), aaaaaaaa(aaaaaaaa) {}", + Style); + + Style.PackConstructorInitializers = FormatStyle::PCIS_NextLine; Style.ConstructorInitializerIndentWidth = 4; Style.ColumnLimit = 60; verifyFormat("SomeClass::Constructor()\n" @@ -20891,6 +20980,12 @@ " , aaaaaaaa(aaaaaaaa)\n" " , aaaaaaaa(aaaaaaaa) {}", Style); + Style.PackConstructorInitializers = FormatStyle::PCIS_NextLineOnly; + verifyFormat("SomeClass::Constructor()\n" + " : aaaaaaaa(aaaaaaaa)\n" + " , aaaaaaaa(aaaaaaaa)\n" + " , aaaaaaaa(aaaaaaaa) {}", + Style); } TEST_F(FormatTest, ConstructorInitializersWithPreprocessorDirective) {