yixiang updated this revision to Diff 80192.
yixiang added a comment.

- Don't reset indent for statements with multiple blocks.


https://reviews.llvm.org/D27383

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

Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -11263,6 +11263,128 @@
                FourIndent);
 }
 
+TEST_F(FormatTest, FormatsBlocksWithIndentResetting) {
+  FormatStyle ShortBlocks = getLLVMStyle();
+  ShortBlocks.AllowShortBlocksOnASingleLine = true;
+  ShortBlocks.ObjCBlockResetsIndent = true;
+
+  verifyFormat("int (^Block)(int, int);", ShortBlocks);
+  verifyFormat("int (^Block1)(int, int) = ^(int i, int j)", ShortBlocks);
+  verifyFormat("void (^block)(int) = ^(id test) { int i; };", ShortBlocks);
+  verifyFormat("void (^block)(int) = ^(int test) { int i; };", ShortBlocks);
+  verifyFormat("void (^block)(int) = ^id(int test) { int i; };", ShortBlocks);
+  verifyFormat("void (^block)(int) = ^int(int test) { int i; };", ShortBlocks);
+
+  verifyFormat("foo(^{ bar(); });", ShortBlocks);
+  verifyFormat("foo(a, ^{ bar(); });", ShortBlocks);
+  verifyFormat("{ void (^block)(Object *x); }", ShortBlocks);
+
+  verifyFormat("[operation setCompletionBlock:^{\n"
+               "  [self onOperationDone];\n"
+               "}];");
+  verifyFormat("int i = {[operation setCompletionBlock:^{\n"
+               "  [self onOperationDone];\n"
+               "}]};");
+
+  verifyFormat("[operation setCompletionBlock:^(int *i) {\n"
+               "  f();\n"
+               "}];");
+
+  verifyFormat("int a = [operation block:^int(int *i) {\n"
+               "  return 1;\n"
+               "}];");
+
+  FormatStyle ResetsIndent = getLLVMStyle();
+  ResetsIndent.ObjCBlockResetsIndent = true;
+  verifyFormat("[myObject doSomethingWith:arg1\n"
+               "                      aaa:^int(int *a) {\n"
+               "  return 1;\n"
+               "}\n"
+               "                      bbb:f(a * bbbbbbbb)];",
+               ResetsIndent);
+
+  verifyFormat("[operation setCompletionBlock:^{\n"
+               "  [self.delegate newDataAvailable];\n"
+               "}];",
+               ResetsIndent);
+  verifyFormat("dispatch_async(_fileIOQueue, ^{\n"
+               "  NSString *path = [self sessionFilePath];\n"
+               "  if (path) {\n"
+               "    // ...\n"
+               "  }\n"
+               "});",
+               ResetsIndent);
+  verifyFormat("[[SessionService sharedService]\n"
+               "    loadWindowWithCompletionBlock:^(SessionWindow *window) {\n"
+               "  if (window) {\n"
+               "    [self windowDidLoad:window];\n"
+               "  } else {\n"
+               "    [self errorLoadingWindow];\n"
+               "  }\n"
+               "}];",
+               ResetsIndent);
+  verifyFormat("void (^largeBlock)(void) = ^{\n"
+               "  // ...\n"
+               "};\n",
+               ResetsIndent);
+
+  FormatStyle ResetsIndent60 = getLLVMStyleWithColumns(60);
+  ResetsIndent60.ObjCBlockResetsIndent = true;
+  verifyFormat("[[SessionService sharedService]\n"
+               "    loadWindowWithCompletionBlock: //\n"
+               "        ^(SessionWindow *window) {\n"
+               "  if (window) {\n"
+               "    [self windowDidLoad:window];\n"
+               "  } else {\n"
+               "    [self errorLoadingWindow];\n"
+               "  }\n"
+               "}];",
+               ResetsIndent60);
+
+  verifyFormat("[myObject doSomethingWith:arg1\n"
+               "    firstBlock:^(Foo *a) {\n"
+               "      // ...\n"
+               "      int i;\n"
+               "    }\n"
+               "    secondBlock:^(Bar *b) {\n"
+               "      // ...\n"
+               "      int i;\n"
+               "    }\n"
+               "    thirdBlock:^Foo(Bar *b) {\n"
+               "      // ...\n"
+               "      int i;\n"
+               "    }];",
+               ResetsIndent);
+  verifyFormat("[myObject doSomethingWith:arg1\n"
+               "               firstBlock:-1\n"
+               "              secondBlock:^(Bar *b) {\n"
+               "  // ...\n"
+               "  int i;\n"
+               "}];",
+               ResetsIndent);
+
+  verifyFormat("f(^{\n"
+               "  @autoreleasepool {\n"
+               "    if (a) {\n"
+               "      g();\n"
+               "    }\n"
+               "  }\n"
+               "});",
+               ResetsIndent);
+  verifyFormat("Block b = ^int *(A *a, B *b) {}", ResetsIndent);
+  verifyFormat("BOOL (^aaa)(void) = ^BOOL {\n"
+               "};",
+               ResetsIndent);
+
+  FormatStyle FourIndent = getLLVMStyle();
+  FourIndent.ObjCBlockIndentWidth = 4;
+  FourIndent.ObjCBlockResetsIndent = true;
+  verifyFormat("[operation setCompletionBlock:^{\n"
+               "    [self onOperationDone];\n"
+               "}];",
+               FourIndent);
+}
+
 TEST_F(FormatTest, FormatsBlocksWithZeroColumnWidth) {
   FormatStyle ZeroColumn = getLLVMStyle();
   ZeroColumn.ColumnLimit = 0;
Index: lib/Format/Format.cpp
===================================================================
--- lib/Format/Format.cpp
+++ lib/Format/Format.cpp
@@ -322,6 +322,7 @@
     IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
     IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
     IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
+    IO.mapOptional("ObjCBlockResetsIndent", Style.ObjCBlockResetsIndent);
     IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
     IO.mapOptional("ObjCSpaceBeforeProtocolList",
                    Style.ObjCSpaceBeforeProtocolList);
Index: lib/Format/ContinuationIndenter.cpp
===================================================================
--- lib/Format/ContinuationIndenter.cpp
+++ lib/Format/ContinuationIndenter.cpp
@@ -1037,6 +1037,16 @@
 }
 
 void ContinuationIndenter::moveStateToNewBlock(LineState &State) {
+  // Reset the indent of an ObjC block to that of its owner statement if the
+  // statement has only one embedded block.
+  if (Style.ObjCBlockResetsIndent &&
+      State.NextToken->is(TT_ObjCBlockLBrace) &&
+      (State.Stack.size() < 2 ||
+       !State.Stack[State.Stack.size() - 2].HasMultipleNestedBlocks)) {
+    State.Stack.back().Indent = State.Stack.front().Indent;
+    State.Stack.back().NestedBlockIndent =
+        State.Stack.front().NestedBlockIndent;
+  }
   unsigned NestedBlockIndent = State.Stack.back().NestedBlockIndent;
   // ObjC block sometimes follow special indentation rules.
   unsigned NewIndent =
Index: include/clang/Format/Format.h
===================================================================
--- include/clang/Format/Format.h
+++ include/clang/Format/Format.h
@@ -500,6 +500,10 @@
   /// \brief The number of characters to use for indentation of ObjC blocks.
   unsigned ObjCBlockIndentWidth;
 
+  /// \brief Reset the indent of an ObjC block to that of its owner statement
+  /// if the statement has only one embedded block.
+  bool ObjCBlockResetsIndent = false;
+
   /// \brief Add a space after ``@property`` in Objective-C, i.e. use
   /// ``@property (readonly)`` instead of ``@property(readonly)``.
   bool ObjCSpaceAfterProperty;
Index: docs/ClangFormatStyleOptions.rst
===================================================================
--- docs/ClangFormatStyleOptions.rst
+++ docs/ClangFormatStyleOptions.rst
@@ -618,6 +618,10 @@
 **ObjCBlockIndentWidth** (``unsigned``)
   The number of characters to use for indentation of ObjC blocks.
 
+**ObjCBlockResetsIndent** (``bool``)
+  Reset the indent of an ObjC block to that of its owner statement
+  if the statement has only one embedded block.
+
 **ObjCSpaceAfterProperty** (``bool``)
   Add a space after ``@property`` in Objective-C, i.e. use
   ``@property (readonly)`` instead of ``@property(readonly)``.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to