[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

llvm-svn: 324131
This commit is contained in:
Ben Hamilton 2018-02-02 20:15:14 +00:00
parent e7e147f52c
commit 4dc658ca52
4 changed files with 81 additions and 3 deletions

View File

@ -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 &&

View File

@ -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 ||

View File

@ -105,6 +105,14 @@ template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
}
};
template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
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<FormatStyle::BinaryOperatorStyle> {
static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
IO.enumCase(Value, "All", FormatStyle::BOS_All);
@ -378,6 +386,7 @@ template <> struct MappingTraits<FormatStyle> {
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;

View File

@ -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 <NSSomeDelegate> {\n"
" @public\n"