Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -1135,7 +1135,8 @@ // }, a, b, c); if (Current.isNot(tok::comment) && Previous && Previous->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) && - !Previous->is(TT_DictLiteral) && State.Stack.size() > 1) { + !Previous->is(TT_DictLiteral) && State.Stack.size() > 1 && + !State.Stack.back().HasMultipleNestedBlocks) { if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline) for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i) State.Stack[i].NoLineBreak = true; Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -3043,6 +3043,22 @@ return true; } + // Deal with lambda arguments in C++ - we want consistent line breaks whether + // they happen to be at arg0, arg1 or argN. The selection is a bit nuanced + // as aggressive line breaks only make sense when the user had set + // Style.BinPackArguments to 'false'. + if ((Style.Language == FormatStyle::LK_Cpp || + Style.Language == FormatStyle::LK_ObjC) && + Left.is(tok::l_paren) && Left.BlockParameterCount > 0 && + !Right.isOneOf(tok::l_paren, TT_LambdaLSquare)) { + // Always break lines in the "multiple lumbdas" case. + if (Left.BlockParameterCount > 1) + return true; + // Break lines with a lambda when the style disallows arg packing. + if (!Style.BinPackArguments) + return true; + } + return false; } Index: lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- lib/Format/UnwrappedLineFormatter.cpp +++ lib/Format/UnwrappedLineFormatter.cpp @@ -988,8 +988,7 @@ Path.push_front(Best); Best = Best->Previous; } - for (std::deque::iterator I = Path.begin(), E = Path.end(); - I != E; ++I) { + for (auto I = Path.begin(), E = Path.end(); I != E; ++I) { unsigned Penalty = 0; formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty); Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false); @@ -998,8 +997,8 @@ printLineState((*I)->Previous->State); if ((*I)->NewLine) { llvm::dbgs() << "Penalty for placing " - << (*I)->Previous->State.NextToken->Tok.getName() << ": " - << Penalty << "\n"; + << (*I)->Previous->State.NextToken->Tok.getName() + << " on a new line: " << Penalty << "\n"; } }); } Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -11785,6 +11785,60 @@ " return j;\n" " });"); + // A lambda passed as arg0 is always pushed to the next line. + verifyFormat("void f() {\n" + " something->Method1(\n" + " [this] {\n" + " Do1();\n" + " Do2();\n" + " },\n" + " 1);\n" + "}\n"); + + // A lambda passed as arg1 forces arg0 to be pushed out when + // BinPackArguments=false. + { + auto Style = getGoogleStyle(); + Style.BinPackArguments = false; + verifyFormat("void f() {\n" + " something->Method2s(\n" + " 1,\n" + " [this] {\n" + " Do1();\n" + " Do2();\n" + " },\n" + " 1);\n" + "}\n", + Style); + } + + // A lambda with a very long line forces arg0 to be pushed out irrespective of + // the BinPackArguments value. + verifyFormat("void f() {\n" + " something->Method2l(\n" + " 1,\n" + " [this] {\n" + " Do1();\n" + " D0000000000000000000000000000000000000000000000000000000001();\n" + " },\n" + " 1);\n" + "}\n"); + + // Multiple lambdas are treated correctly even when there is a short arg0. + verifyFormat("void f() {\n" + " something->Method3(\n" + " 1,\n" + " [this] {\n" + " Do1();\n" + " Do2();\n" + " },\n" + " [this] {\n" + " Do1();\n" + " Do2();\n" + " },\n" + " 1);\n" + "}\n"); + // More complex introducers. verifyFormat("return [i, args...] {};");