forked from OSchip/llvm-project
[clang-format] Fix putting ObjC message arguments in one line for multiline receiver
Summary: Reapply reverted changes from D46879. 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, krasimir Reviewed By: benhamilton, krasimir Subscribers: djasper, klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D47195 llvm-svn: 333171
This commit is contained in:
parent
d0a8ad3ac0
commit
34391f097d
|
@ -1387,6 +1387,29 @@ 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 (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();
|
||||
|
|
|
@ -796,6 +796,41 @@ TEST_F(FormatTestObjC, FormatObjCMethodExpr) {
|
|||
verifyFormat("[((Foo *)foo) bar];");
|
||||
verifyFormat("[((Foo *)foo) bar:1 blech:2];");
|
||||
|
||||
// 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];");
|
||||
// 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];");
|
||||
|
||||
|
||||
Style.ColumnLimit = 70;
|
||||
verifyFormat(
|
||||
"void f() {\n"
|
||||
|
|
Loading…
Reference in New Issue