Author: jolesiak
Date: Thu May 17 01:35:15 2018
New Revision: 332582

URL: http://llvm.org/viewvc/llvm-project?rev=332582&view=rev
Log:
[clang-format] Fix putting ObjC message arguments in one line for multiline 
receiver

Summary:
Currently BreakBeforeParameter is set to true everytime message receiver spans 
multiple lines, e.g.:
```
[[object block:^{
  return 42;
}] aa:42 bb:42];
```
will be formatted:
```
[[object block:^{
  return 42;
}] aa:42
   bb:42];
```
even though arguments could fit into one line. This change fixes this behavior.

Test Plan:
make -j12 FormatTests && tools/clang/unittests/Format/FormatTests

Reviewers: benhamilton, djasper

Reviewed By: benhamilton

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D46879

Modified:
    cfe/trunk/lib/Format/ContinuationIndenter.cpp
    cfe/trunk/unittests/Format/FormatTestObjC.cpp

Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=332582&r1=332581&r2=332582&view=diff
==============================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Thu May 17 01:35:15 2018
@@ -1073,8 +1073,34 @@ unsigned ContinuationIndenter::moveState
   if (Current.isMemberAccess())
     State.Stack.back().StartOfFunctionCall =
         !Current.NextOperator ? 0 : State.Column;
-  if (Current.is(TT_SelectorName))
+  if (Current.is(TT_SelectorName) &&
+      !State.Stack.back().ObjCSelectorNameFound) {
     State.Stack.back().ObjCSelectorNameFound = true;
+
+    // Reevaluate whether ObjC message arguments fit into one line.
+    // If a receiver spans multiple lines, e.g.:
+    //   [[object block:^{
+    //     return 42;
+    //   }] a:42 b:42];
+    // BreakBeforeParameter is calculated based on an incorrect assumption
+    // (it is checked whether the whole expression fits into one line without
+    // considering a line break inside a message receiver).
+    if (Current.Previous && Current.Previous->closesScope() &&
+        Current.Previous->MatchingParen &&
+        Current.Previous->MatchingParen->Previous) {
+      const FormatToken &CurrentScopeOpener =
+          *Current.Previous->MatchingParen->Previous;
+      if (CurrentScopeOpener.is(TT_ObjCMethodExpr) &&
+          CurrentScopeOpener.MatchingParen) {
+        int NecessarySpaceInLine =
+            getLengthToMatchingParen(CurrentScopeOpener, State.Stack) +
+            CurrentScopeOpener.TotalLength - Current.TotalLength - 1;
+        if (State.Column + Current.ColumnWidth + NecessarySpaceInLine <=
+            Style.ColumnLimit)
+          State.Stack.back().BreakBeforeParameter = false;
+      }
+    }
+  }
   if (Current.is(TT_CtorInitializerColon) &&
       Style.BreakConstructorInitializers != FormatStyle::BCIS_AfterColon) {
     // Indent 2 from the column, so:

Modified: cfe/trunk/unittests/Format/FormatTestObjC.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestObjC.cpp?rev=332582&r1=332581&r2=332582&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTestObjC.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTestObjC.cpp Thu May 17 01:35:15 2018
@@ -792,6 +792,35 @@ TEST_F(FormatTestObjC, FormatObjCMethodE
                "      a = 42;\n"
                "    }];");
 
+  // Message receiver taking multiple lines.
+  Style.ColumnLimit = 20;
+  // Non-corner case.
+  verifyFormat("[[object block:^{\n"
+               "  return 42;\n"
+               "}] a:42 b:42];");
+  // Arguments just fit into one line.
+  verifyFormat("[[object block:^{\n"
+               "  return 42;\n"
+               "}] aaaaaaa:42 b:42];");
+  // Arguments just over a column limit.
+  verifyFormat("[[object block:^{\n"
+               "  return 42;\n"
+               "}] aaaaaaa:42\n"
+               "        bb:42];");
+  // Non-corner case.
+  verifyFormat("[[object aaa:42\n"
+               "           b:42]\n"
+               "    cc:42 d:42];");
+  // Arguments just fit into one line.
+  verifyFormat("[[object aaa:42\n"
+               "           b:42]\n"
+               "    cccccc:42 d:42];");
+  // Arguments just over a column limit.
+  verifyFormat("[[object aaa:42\n"
+               "           b:42]\n"
+               "    cccccc:42\n"
+               "        dd:42];");
+
   Style.ColumnLimit = 70;
   verifyFormat(
       "void f() {\n"


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to