Index: cfe/trunk/docs/ClangFormatStyleOptions.rst =================================================================== --- cfe/trunk/docs/ClangFormatStyleOptions.rst +++ cfe/trunk/docs/ClangFormatStyleOptions.rst @@ -277,6 +277,41 @@ int a; // My comment a vs. int a; // My comment a int b = 2; // comment b int b = 2; // comment about b +**AllowAllArgumentsOnNextLine** (``bool``) + If a function call or braced initializer list doesn't fit on a + line, allow putting all arguments onto the next line, even if + ``BinPackArguments`` is ``false``. + + .. code-block:: c++ + + true: + callFunction( + a, b, c, d); + + false: + callFunction(a, + b, + c, + d); + +**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. + Note that this parameter has no effect if + ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is false. + + .. code-block:: c++ + + true: + MyClass::MyClass() : + member0(0), member1(2) {} + + false: + MyClass::MyClass() : + member0(0), + member1(2) {} + **AllowAllParametersOfDeclarationOnNextLine** (``bool``) If the function declaration doesn't fit on a line, allow putting all parameters of a function declaration onto Index: cfe/trunk/include/clang/Format/Format.h =================================================================== --- cfe/trunk/include/clang/Format/Format.h +++ cfe/trunk/include/clang/Format/Format.h @@ -154,6 +154,38 @@ /// \endcode bool AlignTrailingComments; + /// \brief If a function call or braced initializer list doesn't fit on a + /// line, allow putting all arguments onto the next line, even if + /// ``BinPackArguments`` is ``false``. + /// \code + /// true: + /// callFunction( + /// a, b, c, d); + /// + /// false: + /// callFunction(a, + /// b, + /// c, + /// d); + /// \endcode + bool AllowAllArgumentsOnNextLine; + + /// \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. + /// Note that this parameter has no effect if + /// ```ConstructorInitializerAllOnOneLineOrOnePerLine``` is false. + /// \code + /// true: + /// MyClass::MyClass() : + /// member0(0), member1(2) {} + /// + /// false: + /// MyClass::MyClass() : + /// member0(0), + /// member1(2) {} + bool AllowAllConstructorInitializersOnNextLine; + /// If the function declaration doesn't fit on a line, /// allow putting all parameters of a function declaration onto /// the next line even if ``BinPackParameters`` is ``false``. @@ -1761,6 +1793,9 @@ AlignEscapedNewlines == R.AlignEscapedNewlines && AlignOperands == R.AlignOperands && AlignTrailingComments == R.AlignTrailingComments && + AllowAllArgumentsOnNextLine == R.AllowAllArgumentsOnNextLine && + AllowAllConstructorInitializersOnNextLine == + R.AllowAllConstructorInitializersOnNextLine && AllowAllParametersOfDeclarationOnNextLine == R.AllowAllParametersOfDeclarationOnNextLine && AllowShortBlocksOnASingleLine == R.AllowShortBlocksOnASingleLine && Index: cfe/trunk/lib/Format/ContinuationIndenter.cpp =================================================================== --- cfe/trunk/lib/Format/ContinuationIndenter.cpp +++ cfe/trunk/lib/Format/ContinuationIndenter.cpp @@ -881,14 +881,30 @@ State.Stack.back().BreakBeforeClosingBrace = true; if (State.Stack.back().AvoidBinPacking) { - // If we are breaking after '(', '{', '<', this is not bin packing - // unless AllowAllParametersOfDeclarationOnNextLine is false or this is a - // dict/object literal. - if (!Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) || + // If we are breaking after '(', '{', '<', or this is the break after a ':' + // to start a member initializater list in a constructor, this should not + // be considered bin packing unless the relevant AllowAll option is false or + // this is a dict/object literal. + bool PreviousIsBreakingCtorInitializerColon = + Previous.is(TT_CtorInitializerColon) && + Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon; + if (!(Previous.isOneOf(tok::l_paren, tok::l_brace, TT_BinaryOperator) || + PreviousIsBreakingCtorInitializerColon) || (!Style.AllowAllParametersOfDeclarationOnNextLine && State.Line->MustBeDeclaration) || + (!Style.AllowAllArgumentsOnNextLine && + !State.Line->MustBeDeclaration) || + (!Style.AllowAllConstructorInitializersOnNextLine && + PreviousIsBreakingCtorInitializerColon) || Previous.is(TT_DictLiteral)) State.Stack.back().BreakBeforeParameter = true; + + // If we are breaking after a ':' to start a member initializer list, + // and we allow all arguments on the next line, we should not break + // before the next parameter. + if (PreviousIsBreakingCtorInitializerColon && + Style.AllowAllConstructorInitializersOnNextLine) + State.Stack.back().BreakBeforeParameter = false; } return Penalty; @@ -1102,9 +1118,13 @@ ? 0 : 2); State.Stack.back().NestedBlockIndent = State.Stack.back().Indent; - if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine) + if (Style.ConstructorInitializerAllOnOneLineOrOnePerLine) { State.Stack.back().AvoidBinPacking = true; - State.Stack.back().BreakBeforeParameter = false; + State.Stack.back().BreakBeforeParameter = + !Style.AllowAllConstructorInitializersOnNextLine; + } else { + State.Stack.back().BreakBeforeParameter = false; + } } if (Current.is(TT_CtorInitializerColon) && Style.BreakConstructorInitializers == FormatStyle::BCIS_AfterColon) { Index: cfe/trunk/lib/Format/Format.cpp =================================================================== --- cfe/trunk/lib/Format/Format.cpp +++ cfe/trunk/lib/Format/Format.cpp @@ -335,6 +335,10 @@ IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines); IO.mapOptional("AlignOperands", Style.AlignOperands); IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments); + IO.mapOptional("AllowAllArgumentsOnNextLine", + Style.AllowAllArgumentsOnNextLine); + IO.mapOptional("AllowAllConstructorInitializersOnNextLine", + Style.AllowAllConstructorInitializersOnNextLine); IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine", Style.AllowAllParametersOfDeclarationOnNextLine); IO.mapOptional("AllowShortBlocksOnASingleLine", @@ -351,6 +355,7 @@ Style.AlwaysBreakAfterDefinitionReturnType); IO.mapOptional("AlwaysBreakAfterReturnType", Style.AlwaysBreakAfterReturnType); + // If AlwaysBreakAfterDefinitionReturnType was specified but // AlwaysBreakAfterReturnType was not, initialize the latter from the // former for backwards compatibility. @@ -641,6 +646,8 @@ LLVMStyle.AlignTrailingComments = true; LLVMStyle.AlignConsecutiveAssignments = false; LLVMStyle.AlignConsecutiveDeclarations = false; + LLVMStyle.AllowAllArgumentsOnNextLine = true; + LLVMStyle.AllowAllConstructorInitializersOnNextLine = true; LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true; LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All; LLVMStyle.AllowShortBlocksOnASingleLine = false; Index: cfe/trunk/unittests/Format/FormatTest.cpp =================================================================== --- cfe/trunk/unittests/Format/FormatTest.cpp +++ cfe/trunk/unittests/Format/FormatTest.cpp @@ -3956,6 +3956,191 @@ " aaaa(aaaa) {}")); } +TEST_F(FormatTest, AllowAllConstructorInitializersOnNextLine) { + FormatStyle Style = getLLVMStyle(); + Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; + Style.ColumnLimit = 60; + Style.ConstructorInitializerAllOnOneLineOrOnePerLine = true; + Style.AllowAllConstructorInitializersOnNextLine = true; + Style.BinPackParameters = false; + + for (int i = 0; i < 4; ++i) { + // Test all combinations of parameters that should not have an effect. + Style.AllowAllParametersOfDeclarationOnNextLine = i & 1; + Style.AllowAllArgumentsOnNextLine = i & 2; + + Style.AllowAllConstructorInitializersOnNextLine = true; + Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; + verifyFormat("Constructor()\n" + " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + verifyFormat("Constructor() : a(a), b(b) {}", Style); + + Style.AllowAllConstructorInitializersOnNextLine = false; + verifyFormat("Constructor()\n" + " : aaaaaaaaaaaaaaaaaaaa(a)\n" + " , bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + verifyFormat("Constructor() : a(a), b(b) {}", Style); + + Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; + Style.AllowAllConstructorInitializersOnNextLine = true; + verifyFormat("Constructor()\n" + " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + + Style.AllowAllConstructorInitializersOnNextLine = false; + verifyFormat("Constructor()\n" + " : aaaaaaaaaaaaaaaaaaaa(a),\n" + " bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + + Style.BreakConstructorInitializers = FormatStyle::BCIS_AfterColon; + Style.AllowAllConstructorInitializersOnNextLine = true; + verifyFormat("Constructor() :\n" + " aaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + + Style.AllowAllConstructorInitializersOnNextLine = false; + verifyFormat("Constructor() :\n" + " aaaaaaaaaaaaaaaaaa(a),\n" + " bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + } + + // Test interactions between AllowAllParametersOfDeclarationOnNextLine and + // AllowAllConstructorInitializersOnNextLine in all + // BreakConstructorInitializers modes + Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma; + Style.AllowAllParametersOfDeclarationOnNextLine = true; + Style.AllowAllConstructorInitializersOnNextLine = false; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbbb)\n" + " : aaaaaaaaaaaaaaaaaaaa(a)\n" + " , bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + + Style.AllowAllConstructorInitializersOnNextLine = true; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa,\n" + " int bbbbbbbbbbbbb,\n" + " int cccccccccccccccc)\n" + " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + + Style.AllowAllParametersOfDeclarationOnNextLine = false; + Style.AllowAllConstructorInitializersOnNextLine = false; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa,\n" + " int bbbbbbbbbbbbb)\n" + " : aaaaaaaaaaaaaaaaaaaa(a)\n" + " , bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + + Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; + + Style.AllowAllParametersOfDeclarationOnNextLine = true; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbbb)\n" + " : aaaaaaaaaaaaaaaaaaaa(a),\n" + " bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + + Style.AllowAllConstructorInitializersOnNextLine = true; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa,\n" + " int bbbbbbbbbbbbb,\n" + " int cccccccccccccccc)\n" + " : aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + + Style.AllowAllParametersOfDeclarationOnNextLine = false; + Style.AllowAllConstructorInitializersOnNextLine = false; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa,\n" + " int bbbbbbbbbbbbb)\n" + " : aaaaaaaaaaaaaaaaaaaa(a),\n" + " bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + + Style.BreakConstructorInitializers = FormatStyle::BCIS_AfterColon; + Style.AllowAllParametersOfDeclarationOnNextLine = true; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbbb) :\n" + " aaaaaaaaaaaaaaaaaaaa(a),\n" + " bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + + Style.AllowAllConstructorInitializersOnNextLine = true; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa,\n" + " int bbbbbbbbbbbbb,\n" + " int cccccccccccccccc) :\n" + " aaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); + + Style.AllowAllParametersOfDeclarationOnNextLine = false; + Style.AllowAllConstructorInitializersOnNextLine = false; + verifyFormat("SomeClassWithALongName::Constructor(\n" + " int aaaaaaaaaaaaaaaaaaaaaaaa,\n" + " int bbbbbbbbbbbbb) :\n" + " aaaaaaaaaaaaaaaaaaaa(a),\n" + " bbbbbbbbbbbbbbbbbbbbb(b) {}", + Style); +} + +TEST_F(FormatTest, AllowAllArgumentsOnNextLine) { + FormatStyle Style = getLLVMStyle(); + Style.ColumnLimit = 60; + Style.BinPackArguments = false; + for (int i = 0; i < 4; ++i) { + // Test all combinations of parameters that should not have an effect. + Style.AllowAllParametersOfDeclarationOnNextLine = i & 1; + Style.AllowAllConstructorInitializersOnNextLine = i & 2; + + Style.AllowAllArgumentsOnNextLine = true; + verifyFormat("void foo() {\n" + " FunctionCallWithReallyLongName(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbb);\n" + "}", + Style); + Style.AllowAllArgumentsOnNextLine = false; + verifyFormat("void foo() {\n" + " FunctionCallWithReallyLongName(\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " bbbbbbbbbbbb);\n" + "}", + Style); + + Style.AllowAllArgumentsOnNextLine = true; + verifyFormat("void foo() {\n" + " auto VariableWithReallyLongName = {\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbb};\n" + "}", + Style); + Style.AllowAllArgumentsOnNextLine = false; + verifyFormat("void foo() {\n" + " auto VariableWithReallyLongName = {\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " bbbbbbbbbbbb};\n" + "}", + Style); + } + + // This parameter should not affect declarations. + Style.BinPackParameters = false; + Style.AllowAllArgumentsOnNextLine = false; + Style.AllowAllParametersOfDeclarationOnNextLine = true; + verifyFormat("void FunctionCallWithReallyLongName(\n" + " int aaaaaaaaaaaaaaaaaaaaaaa, int bbbbbbbbbbbb);", + Style); + Style.AllowAllParametersOfDeclarationOnNextLine = false; + verifyFormat("void FunctionCallWithReallyLongName(\n" + " int aaaaaaaaaaaaaaaaaaaaaaa,\n" + " int bbbbbbbbbbbb);", + Style); +} + TEST_F(FormatTest, BreakConstructorInitializersAfterColon) { FormatStyle Style = getLLVMStyle(); Style.BreakConstructorInitializers = FormatStyle::BCIS_AfterColon; @@ -3973,17 +4158,23 @@ verifyFormat("template \n" "Constructor() : Initializer(FitsOnTheLine) {}", getStyleWithColumns(Style, 50)); + Style.ConstructorInitializerAllOnOneLineOrOnePerLine = true; + verifyFormat( + "SomeClass::Constructor() :\n" + " aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}", + Style); + Style.ConstructorInitializerAllOnOneLineOrOnePerLine = false; verifyFormat( "SomeClass::Constructor() :\n" " aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}", - Style); + Style); verifyFormat( "SomeClass::Constructor() :\n" " aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n" " aaaaaaaaaaaaa(aaaaaaaaaaaaaa) {}", - Style); + Style); verifyFormat( "SomeClass::Constructor() :\n" " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa),\n" @@ -4029,7 +4220,7 @@ FormatStyle OnePerLine = Style; OnePerLine.ConstructorInitializerAllOnOneLineOrOnePerLine = true; - OnePerLine.AllowAllParametersOfDeclarationOnNextLine = false; + OnePerLine.AllowAllConstructorInitializersOnNextLine = false; verifyFormat("SomeClass::Constructor() :\n" " aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n" " aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n" @@ -11025,6 +11216,8 @@ CHECK_PARSE_BOOL(AlignTrailingComments); CHECK_PARSE_BOOL(AlignConsecutiveAssignments); CHECK_PARSE_BOOL(AlignConsecutiveDeclarations); + CHECK_PARSE_BOOL(AllowAllArgumentsOnNextLine); + CHECK_PARSE_BOOL(AllowAllConstructorInitializersOnNextLine); CHECK_PARSE_BOOL(AllowAllParametersOfDeclarationOnNextLine); CHECK_PARSE_BOOL(AllowShortBlocksOnASingleLine); CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine);