ghvg1313 created this revision.
ghvg1313 added a reviewer: klimek.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

>From `clang-format` version 3.7.0 and up, , there is no way to keep following 
>format of ObjectiveC block:

  - (void)_aMethod
  {
      [self.test1 t:self w:self callback:^(typeof(self) self, NSNumber *u, 
NSNumber *v) {
          u = c;
      }]
  }

Regardless of the change in `.clang-format` configuration file, all parameters 
will be lined up so that colons will be on the same column, like following:

  - (void)_aMethod
  {
      [self.test1 t:self
                  w:self
           callback:^(typeof(self) self, NSNumber *u, NSNumber *v) {
               u = c;
           }]
  }

Considering with ObjectiveC, the first code style is cleaner & more readable 
for some people, I've added a config option: 
`ObjCDontBreakBeforeNestedBlockParam` (boolean) so that if it is enable, the 
first code style will be favored.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D70926

Files:
  clang/include/clang/Format/Format.h
  clang/lib/Format/ContinuationIndenter.cpp
  clang/lib/Format/Format.cpp
  clang/unittests/Format/FormatTest.cpp

Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ 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<int>[10];",
             format("auto a = new unique_ptr<int > [ 10];"));
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ 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;
Index: clang/lib/Format/ContinuationIndenter.cpp
===================================================================
--- clang/lib/Format/ContinuationIndenter.cpp
+++ 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.
Index: clang/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ 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 <Protocol>`` instead of ``Foo<Protocol>``.
   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 &&
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to