jolesiak created this revision. Herald added subscribers: cfe-commits, klimek.
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 Repository: rC Clang https://reviews.llvm.org/D46879 Files: lib/Format/ContinuationIndenter.cpp unittests/Format/FormatTestObjC.cpp Index: unittests/Format/FormatTestObjC.cpp =================================================================== --- unittests/Format/FormatTestObjC.cpp +++ unittests/Format/FormatTestObjC.cpp @@ -792,6 +792,35 @@ " 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" Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -1067,8 +1067,34 @@ 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:
Index: unittests/Format/FormatTestObjC.cpp =================================================================== --- unittests/Format/FormatTestObjC.cpp +++ unittests/Format/FormatTestObjC.cpp @@ -792,6 +792,35 @@ " 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" Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -1067,8 +1067,34 @@ 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:
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits