diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -1993,6 +1993,10 @@ [self onOperationDone]; }]; +**ObjCDontBreakBeforeNestedBlockParam** (``bool``) + Dont break parameters list into lines when there is nested block + parameters in a fuction call. + **ObjCSpaceAfterProperty** (``bool``) Add a space after ``@property`` in Objective-C, i.e. use ``@property (readonly)`` instead of ``@property(readonly)``. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -337,6 +337,29 @@ int a [5]; vs int a[5]; +- Option ``ObjCDontBreakBeforeNestedBlockParam`` has been added to prevent + linebreaks for arguments declarations in functions or blocks. + + .. code-block:: c++ + + true: + - (void)_aMethod + { + [self.test1 t:self w:self callback:^(typeof(self) self, NSNumber *u, NSNumber *v) { + u = c; + }] + } + + false: + - (void)_aMethod + { + [self.test1 t:self + w:self + callback:^(typeof(self) self, NSNumber *u, NSNumber *v) { + u = c; + }] + } + - Clang-format now supports JavaScript null operators. .. code-block:: c++ diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1646,6 +1646,10 @@ /// ``@property (readonly)`` instead of ``@property(readonly)``. bool ObjCSpaceAfterProperty; + /// \brief Dont break parameters list into lines when there is nested block + /// parameters in a fuction call. + bool ObjCDontBreakBeforeNestedBlockParam; + /// Add a space in front of an Objective-C protocol list, i.e. use /// ``Foo `` instead of ``Foo``. bool ObjCSpaceBeforeProtocolList; @@ -2126,6 +2130,7 @@ NamespaceMacros == R.NamespaceMacros && ObjCBinPackProtocolList == R.ObjCBinPackProtocolList && ObjCBlockIndentWidth == R.ObjCBlockIndentWidth && + ObjCDontBreakBeforeNestedBlockParam == R.ObjCDontBreakBeforeNestedBlockParam && ObjCSpaceAfterProperty == R.ObjCSpaceAfterProperty && ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList && PenaltyBreakAssignment == R.PenaltyBreakAssignment && diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -863,7 +863,7 @@ bool NestedBlockSpecialCase = !Style.isCpp() && Current.is(tok::r_brace) && State.Stack.size() > 1 && State.Stack[State.Stack.size() - 2].NestedBlockInlined; - if (!NestedBlockSpecialCase) + if (!NestedBlockSpecialCase && !Style.ObjCDontBreakBeforeNestedBlockParam) for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) State.Stack[i].BreakBeforeParameter = true; @@ -1380,7 +1380,8 @@ (!BinPackInconclusiveFunctions && Current.PackingKind == PPK_Inconclusive))); - if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen) { + if (Current.is(TT_ObjCMethodExpr) && Current.MatchingParen && + !Style.ObjCDontBreakBeforeNestedBlockParam) { if (Style.ColumnLimit) { // If this '[' opens an ObjC call, determine whether all parameters fit // into one line and put one per line if they don't. diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -497,6 +497,8 @@ IO.mapOptional("NamespaceMacros", Style.NamespaceMacros); IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList); IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth); + IO.mapOptional("ObjCDontBreakBeforeNestedBlockParam", + Style.ObjCDontBreakBeforeNestedBlockParam); IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty); IO.mapOptional("ObjCSpaceBeforeProtocolList", Style.ObjCSpaceBeforeProtocolList); @@ -791,7 +793,7 @@ LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true; LLVMStyle.NamespaceIndentation = FormatStyle::NI_None; LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto; - LLVMStyle.ObjCBlockIndentWidth = 2; + LLVMStyle.ObjCDontBreakBeforeNestedBlockParam = false; LLVMStyle.ObjCSpaceAfterProperty = false; LLVMStyle.ObjCSpaceBeforeProtocolList = true; LLVMStyle.PointerAlignment = FormatStyle::PAS_Right; diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -14444,6 +14444,29 @@ verifyFormat("include \"a.td\"\ninclude \"b.td\"", Style); } +TEST_F(FormatTest, DoNotBreakLineBeforeNestedBlockParam) { + FormatStyle Style = getLLVMStyle(); + Style.ObjCDontBreakBeforeNestedBlockParam = true; + Style.ColumnLimit = 0; + + verifyFormat("[self.test1 t:self callback:^(typeof(self) self, " \ + "NSNumber *u, NSNumber *v) {\n u = v;\n}]", Style); + + verifyFormat("[self.test1 t:self w:self callback:^(typeof(self) self, " \ + "NSNumber *u, NSNumber *v) {\n u = v;\n}]", Style); + + verifyFormat("[self.test1 t:self w:self callback:^(typeof(self) self, " \ + "NSNumber *u, NSNumber *v) {\n u = c;\n} w:self " \ + "callback2:^(typeof(self) self, NSNumber *a, NSNumber *b, " \ + "NSNumber *c) {\n b = c;\n}]", Style); + + Style.ColumnLimit = 80; + verifyFormat("[self.test_method a:self b:self\n" \ + " callback:^(typeof(self) self, NSNumber *u, " \ + "NSNumber *v) {\n" \ + " u = v;\n" \" }]", Style); +} + TEST_F(FormatTest, ArrayOfTemplates) { EXPECT_EQ("auto a = new unique_ptr[10];", format("auto a = new unique_ptr [ 10];"));