diff options
| author | Jacek Olesiak <jolesiak@google.com> | 2018-07-09 07:08:45 +0000 | 
|---|---|---|
| committer | Jacek Olesiak <jolesiak@google.com> | 2018-07-09 07:08:45 +0000 | 
| commit | 2dc3dac90ce1dae447e935d5070ea182f77de23e (patch) | |
| tree | 3d737d9776ee55ce5a9a8144bd992356d3f4837d | |
| parent | 6b475b730b1c0414cc573c89db986705828cc0a8 (diff) | |
| download | bcm5719-llvm-2dc3dac90ce1dae447e935d5070ea182f77de23e.tar.gz bcm5719-llvm-2dc3dac90ce1dae447e935d5070ea182f77de23e.zip  | |
[clang-format/ObjC] Put ObjC method arguments into one line when they fit
Reapply D47195:
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.
llvm-svn: 336521
| -rw-r--r-- | clang/lib/Format/ContinuationIndenter.cpp | 24 | ||||
| -rw-r--r-- | clang/unittests/Format/FormatTestObjC.cpp | 42 | 
2 files changed, 66 insertions, 0 deletions
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 0862a4e0f95..90d2a999711 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -1398,6 +1398,30 @@ void ContinuationIndenter::moveStatePastScopeCloser(LineState &State) {         (Current.is(tok::greater) && Current.is(TT_DictLiteral))))      State.Stack.pop_back(); +  // 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). +  // We check whether arguements fit after receiver scope closer (into the same +  // line). +  if (State.Stack.back().BreakBeforeParameter && Current.MatchingParen && +      Current.MatchingParen->Previous) { +    const FormatToken &CurrentScopeOpener = *Current.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(tok::r_square)) {      // If this ends the array subscript expr, reset the corresponding value.      const FormatToken *NextNonComment = Current.getNextNonComment(); diff --git a/clang/unittests/Format/FormatTestObjC.cpp b/clang/unittests/Format/FormatTestObjC.cpp index 58e75363a55..e56df6d130d 100644 --- a/clang/unittests/Format/FormatTestObjC.cpp +++ b/clang/unittests/Format/FormatTestObjC.cpp @@ -820,6 +820,48 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) {    verifyFormat("aaaaaa = [aa aa:aa\n"                 "             aa:aa];"); +  // Message receiver taking multiple lines. +  // 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];"); +  // Arguments just fit into one line. +  Style.ColumnLimit = 23; +  verifyFormat("[[obj a:42\n" +               "      b:42\n" +               "      c:42\n" +               "      d:42] e:42 f:42];"); + +  // Arguments do not fit into one line with a receiver. +  Style.ColumnLimit = 20; +  verifyFormat("[[obj a:42] a:42\n" +               "            b:42];"); +  verifyFormat("[[obj a:42] a:42\n" +               "            b:42\n" +               "            c:42];"); +  verifyFormat("[[obj aaaaaa:42\n" +               "           b:42]\n" +               "    cc:42\n" +               "     d:42];"); + +  // Avoid breaking receiver expression. +  Style.ColumnLimit = 30; +  verifyFormat("fooooooo =\n" +               "    [[obj fooo] aaa:42\n" +               "                aaa:42];"); +  verifyFormat("[[[obj foo] bar] aa:42\n" +               "                 bb:42\n" +               "                 cc:42];"); +    Style.ColumnLimit = 70;    verifyFormat(        "void f() {\n"  | 

