Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -390,6 +390,49 @@ /// \endcode bool BinPackParameters; + /// \brief The style of wrapping parameters on the same line (bin-packed) or + /// on one line each. + enum BinPackStyle { + /// Automatically determine parameter bin-packing behavior. + BPS_Auto, + /// Always bin-pack parameters. + BPS_Always, + /// Never bin-pack parameters. + BPS_Never, + }; + + /// \brief Controls bin-packing Objective-C protocol conformance list + /// items into as few lines as possible when they go over `ColumnLimit`. + /// + /// If ``Auto`` (the default), delegates to the value in + /// ``BinPackParameters``. If that is ``true``, bin-packs Objective-C + /// protocol conformance list items into as few lines as possible + /// whenever they go over ``ColumnLimit``. + /// + /// If ``Always``, always bin-packs Objective-C protocol conformance + /// list items into as few lines as possible whenever they go over + /// ``ColumnLimit``. + /// + /// If ``Never``, lays out Objective-C protocol conformance list items + /// onto individual lines whenever they go over ``ColumnLimit``. + /// + /// \code + /// Always (or Auto, if BinPackParameters=true): + /// @interface ccccccccccccc () < + /// ccccccccccccc, ccccccccccccc, + /// ccccccccccccc, ccccccccccccc> { + /// } + /// + /// Never (or Auto, if BinPackParameters=false): + /// @interface ddddddddddddd () < + /// ddddddddddddd, + /// ddddddddddddd, + /// ddddddddddddd, + /// ddddddddddddd> { + /// } + /// \endcode + BinPackStyle BinPackObjCProtocolList; + /// \brief The style of breaking before or after binary operators. enum BinaryOperatorStyle { /// Break after operators. @@ -1646,6 +1689,7 @@ R.AlwaysBreakTemplateDeclarations && BinPackArguments == R.BinPackArguments && BinPackParameters == R.BinPackParameters && + BinPackObjCProtocolList == R.BinPackObjCProtocolList && BreakBeforeBinaryOperators == R.BreakBeforeBinaryOperators && BreakBeforeBraces == R.BreakBeforeBraces && BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators && Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -1222,9 +1222,20 @@ Current.MatchingParen->getPreviousNonComment() && Current.MatchingParen->getPreviousNonComment()->is(tok::comma); + // If BinPackObjCProtocolList is unspecified, fall back to BinPackParameters + // for backwards compatibility. + bool BinPackObjCProtocolList = + (Style.BinPackObjCProtocolList == FormatStyle::BPS_Auto && + Style.BinPackParameters) || + Style.BinPackObjCProtocolList == FormatStyle::BPS_Always; + + bool BinPackDeclaration = + (State.Line->Type != LT_ObjCDecl && Style.BinPackParameters) || + (State.Line->Type == LT_ObjCDecl && BinPackObjCProtocolList); + AvoidBinPacking = (Style.Language == FormatStyle::LK_JavaScript && EndsInComma) || - (State.Line->MustBeDeclaration && !Style.BinPackParameters) || + (State.Line->MustBeDeclaration && !BinPackDeclaration) || (!State.Line->MustBeDeclaration && !Style.BinPackArguments) || (Style.ExperimentalAutoDetectBinPacking && (Current.PackingKind == PPK_OnePerLine || Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -105,6 +105,14 @@ } }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) { + IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto); + IO.enumCase(Value, "Always", FormatStyle::BPS_Always); + IO.enumCase(Value, "Never", FormatStyle::BPS_Never); + } +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) { IO.enumCase(Value, "All", FormatStyle::BOS_All); @@ -323,6 +331,7 @@ Style.AlwaysBreakTemplateDeclarations); IO.mapOptional("BinPackArguments", Style.BinPackArguments); IO.mapOptional("BinPackParameters", Style.BinPackParameters); + IO.mapOptional("BinPackObjCProtocolList", Style.BinPackObjCProtocolList); IO.mapOptional("BraceWrapping", Style.BraceWrapping); IO.mapOptional("BreakBeforeBinaryOperators", Style.BreakBeforeBinaryOperators); @@ -599,6 +608,7 @@ LLVMStyle.AlwaysBreakTemplateDeclarations = false; LLVMStyle.BinPackArguments = true; LLVMStyle.BinPackParameters = true; + LLVMStyle.BinPackObjCProtocolList = FormatStyle::BPS_Auto; LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; LLVMStyle.BreakBeforeTernaryOperators = true; LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; Index: unittests/Format/FormatTestObjC.cpp =================================================================== --- unittests/Format/FormatTestObjC.cpp +++ unittests/Format/FormatTestObjC.cpp @@ -281,8 +281,7 @@ " ccccccccccccc, ccccccccccccc,\n" " ccccccccccccc, ccccccccccccc> {\n" "}"); - - Style.BinPackParameters = false; + Style.BinPackObjCProtocolList = FormatStyle::BPS_Never; verifyFormat("@interface ddddddddddddd () <\n" " ddddddddddddd,\n" " ddddddddddddd,\n" @@ -290,6 +289,20 @@ " ddddddddddddd> {\n" "}"); + Style.BinPackParameters = false; + Style.BinPackObjCProtocolList = FormatStyle::BPS_Auto; + verifyFormat("@interface eeeeeeeeeeeee () <\n" + " eeeeeeeeeeeee,\n" + " eeeeeeeeeeeee,\n" + " eeeeeeeeeeeee,\n" + " eeeeeeeeeeeee> {\n" + "}"); + Style.BinPackObjCProtocolList = FormatStyle::BPS_Always; + verifyFormat("@interface fffffffffffff () <\n" + " fffffffffffff, fffffffffffff,\n" + " fffffffffffff, fffffffffffff> {\n" + "}"); + Style = getGoogleStyle(FormatStyle::LK_ObjC); verifyFormat("@interface Foo : NSObject {\n" " @public\n"