From dca2f9dcbaf981e7d07eefcbc59901fd3a4f5770 Mon Sep 17 00:00:00 2001 From: Ben Hamilton Date: Fri, 2 Feb 2018 20:15:14 +0000 Subject: [PATCH] [clang-format] New format param ObjCBinPackProtocolList Summary: This is an alternative approach to D42014 after some investigation by stephanemoore@ and myself. Previously, the format parameter `BinPackParameters` controlled both C function parameter list bin-packing and Objective-C protocol conformance list bin-packing. We found in the Google style, some teams were changing `BinPackParameters` from its default (`true`) to `false` so they could lay out Objective-C protocol conformance list items one-per-line instead of bin-packing them into as few lines as possible. To allow teams to use one-per-line Objective-C protocol lists without changing bin-packing for other areas like C function parameter lists, this diff introduces a new LibFormat parameter `ObjCBinPackProtocolList` to control the behavior just for ObjC protocol conformance lists. The new parameter is an enum which defaults to `Auto` to keep the previous behavior (delegating to `BinPackParameters`). Depends On D42649 Test Plan: New tests added. make -j12 FormatTests && ./tools/clang/unittests/Format/FormatTests Reviewers: jolesiak, stephanemoore, djasper Reviewed By: stephanemoore Subscribers: Wizard, hokein, cfe-commits, klimek Differential Revision: https://reviews.llvm.org/D42650 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@324131 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Format/Format.h | 44 +++++++++++++++++++++++++++++ lib/Format/ContinuationIndenter.cpp | 13 ++++++++- lib/Format/Format.cpp | 10 +++++++ unittests/Format/FormatTestObjC.cpp | 17 +++++++++-- 4 files changed, 81 insertions(+), 3 deletions(-) diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index bffa6ddac2..6a37137506 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -390,6 +390,17 @@ struct FormatStyle { /// \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 The style of breaking before or after binary operators. enum BinaryOperatorStyle { /// Break after operators. @@ -1299,6 +1310,38 @@ struct FormatStyle { /// \brief The indentation used for namespaces. NamespaceIndentationKind NamespaceIndentation; + /// \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 ObjCBinPackProtocolList; + /// \brief The number of characters to use for indentation of ObjC blocks. /// \code{.objc} /// ObjCBlockIndentWidth: 4 @@ -1681,6 +1724,7 @@ struct FormatStyle { MacroBlockEnd == R.MacroBlockEnd && MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep && NamespaceIndentation == R.NamespaceIndentation && + ObjCBinPackProtocolList == R.ObjCBinPackProtocolList && ObjCBlockIndentWidth == R.ObjCBlockIndentWidth && ObjCSpaceAfterProperty == R.ObjCSpaceAfterProperty && ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList && diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index 3711ee01c4..db4fe8f0a3 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -1222,9 +1222,20 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, Current.MatchingParen->getPreviousNonComment() && Current.MatchingParen->getPreviousNonComment()->is(tok::comma); + // If ObjCBinPackProtocolList is unspecified, fall back to BinPackParameters + // for backwards compatibility. + bool ObjCBinPackProtocolList = + (Style.ObjCBinPackProtocolList == FormatStyle::BPS_Auto && + Style.BinPackParameters) || + Style.ObjCBinPackProtocolList == FormatStyle::BPS_Always; + + bool BinPackDeclaration = + (State.Line->Type != LT_ObjCDecl && Style.BinPackParameters) || + (State.Line->Type == LT_ObjCDecl && ObjCBinPackProtocolList); + 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 || diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 631d186e62..90b14e74f9 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -105,6 +105,14 @@ template <> struct ScalarEnumerationTraits { } }; +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); @@ -378,6 +386,7 @@ template <> struct MappingTraits { IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd); IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep); IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation); + IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList); IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth); IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty); IO.mapOptional("ObjCSpaceBeforeProtocolList", @@ -637,6 +646,7 @@ FormatStyle getLLVMStyle() { LLVMStyle.MaxEmptyLinesToKeep = 1; LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; + LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; LLVMStyle.ObjCBlockIndentWidth = 2; LLVMStyle.ObjCSpaceAfterProperty = false; LLVMStyle.ObjCSpaceBeforeProtocolList = true; diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp index 23e9066371..d9805859f6 100644 --- a/unittests/Format/FormatTestObjC.cpp +++ b/unittests/Format/FormatTestObjC.cpp @@ -281,8 +281,7 @@ TEST_F(FormatTestObjC, FormatObjCInterface) { " ccccccccccccc, ccccccccccccc,\n" " ccccccccccccc, ccccccccccccc> {\n" "}"); - - Style.BinPackParameters = false; + Style.ObjCBinPackProtocolList = FormatStyle::BPS_Never; verifyFormat("@interface ddddddddddddd () <\n" " ddddddddddddd,\n" " ddddddddddddd,\n" @@ -290,6 +289,20 @@ TEST_F(FormatTestObjC, FormatObjCInterface) { " ddddddddddddd> {\n" "}"); + Style.BinPackParameters = false; + Style.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; + verifyFormat("@interface eeeeeeeeeeeee () <\n" + " eeeeeeeeeeeee,\n" + " eeeeeeeeeeeee,\n" + " eeeeeeeeeeeee,\n" + " eeeeeeeeeeeee> {\n" + "}"); + Style.ObjCBinPackProtocolList = 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" -- 2.40.0