Index: 2 =================================================================== --- 2 +++ 2 @@ -328,6 +328,11 @@ unsigned ExtraSpaces) { FormatToken &Current = *State.NextToken; const FormatToken &Previous = *State.NextToken->Previous; + DEBUG({ + llvm::dbgs() << "addTokenOnCurrentLine\n"; + llvm::dbgs() << " Previous = " << Previous.TokenText << "\n"; + llvm::dbgs() << " Current = " << Current.TokenText << "\n"; + }); if (Current.is(tok::equal) && (State.Line->First->is(tok::kw_for) || Current.NestingLevel == 0) && State.Stack.back().VariablePos == 0) { @@ -381,8 +386,12 @@ // caaaaaaaaaaaall( // caaaaaaaaaaaaaaaaaaaaaaall(aaaaaaaaaaaaaa, aaaaaaaaa)))); Current.FakeLParens.size() > 0 && - Current.FakeLParens.back() > prec::Unknown) + Current.FakeLParens.back() > prec::Unknown) { + DEBUG({ + llvm::dbgs() << ":386\n"; + }); State.Stack.back().NoLineBreak = true; + } if (Previous.is(TT_TemplateString) && Previous.opensScope()) State.Stack.back().NoLineBreak = true; @@ -848,6 +857,9 @@ (Current.IsMultiline ? Current.LastLineColumnWidth : State.Column + Current.ColumnWidth) - strlen("${"); + bool CanBreakProtrudingToken = + State.Stack.empty() || (!State.Stack.back().NoLineBreak && + !State.Stack.back().NoLineBreakInOperand); moveStatePastScopeOpener(State, Newline); moveStatePastFakeRParens(State); @@ -861,7 +873,9 @@ State.Column += Current.ColumnWidth; State.NextToken = State.NextToken->Next; - unsigned Penalty = breakProtrudingToken(Current, State, DryRun); + unsigned Penalty = 0; + if (CanBreakProtrudingToken) + Penalty = breakProtrudingToken(Current, State, DryRun); if (State.Column > getColumnLimit(State)) { unsigned ExcessCharacters = State.Column - getColumnLimit(State); Penalty += Style.PenaltyExcessCharacter * ExcessCharacters; Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -848,6 +848,9 @@ (Current.IsMultiline ? Current.LastLineColumnWidth : State.Column + Current.ColumnWidth) - strlen("${"); + bool CanBreakProtrudingToken = + State.Stack.empty() || (!State.Stack.back().NoLineBreak && + !State.Stack.back().NoLineBreakInOperand); moveStatePastScopeOpener(State, Newline); moveStatePastFakeRParens(State); @@ -861,7 +864,9 @@ State.Column += Current.ColumnWidth; State.NextToken = State.NextToken->Next; - unsigned Penalty = breakProtrudingToken(Current, State, DryRun); + unsigned Penalty = 0; + if (CanBreakProtrudingToken) + Penalty = breakProtrudingToken(Current, State, DryRun); if (State.Column > getColumnLimit(State)) { unsigned ExcessCharacters = State.Column - getColumnLimit(State); Penalty += Style.PenaltyExcessCharacter * ExcessCharacters; Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -6465,8 +6465,9 @@ "_T(\"aaaaaaaaaaaaaa\")\n" "_T(\"aaaaaaaaaaaa\")", format(" _T(\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\")", Style)); - EXPECT_EQ("f(x, _T(\"aaaaaaaaa\")\n" - " _T(\"aaaaaa\"),\n" + EXPECT_EQ("f(x,\n" + " _T(\"aaaaaaaaaaaa\")\n" + " _T(\"aaa\"),\n" " z);", format("f(x, _T(\"aaaaaaaaaaaaaaa\"), z);", Style)); @@ -6498,6 +6499,90 @@ "_T(\"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXn\"));")); } +TEST_F(FormatTest, BreaksStringLiteralOperands) { + // In a function call with two operands, the second can be broken with no line + // break before it. + EXPECT_EQ("func(a, \"long long \"\n" + " \"long long\");", + format("func(a, \"long long long long\");", + getLLVMStyleWithColumns(24))); + // In a function call with three operands, the second must be broken with a + // line break before it. + EXPECT_EQ("func(a,\n" + " \"long long long \"\n" + " \"long\",\n" + " c);", + format("func(a, \"long long long long\", c);", + getLLVMStyleWithColumns(24))); + // In a function call with three operands, the third must be broken with a + // line break before it. + EXPECT_EQ("func(a, b,\n" + " \"long long long \"\n" + " \"long\");", + format("func(a, b, \"long long long long\");", + getLLVMStyleWithColumns(24))); + // In a function call with three operands, both the second and the third must + // be broken with a line break before them. + EXPECT_EQ("func(a,\n" + " \"long long long \"\n" + " \"long\",\n" + " \"long long long \"\n" + " \"long\");", + format("func(a, \"long long long long\", \"long long long long\");", + getLLVMStyleWithColumns(24))); + // In a chain of << with two operands, the second can be broken with no line + // break before it. + EXPECT_EQ("a << \"line line \"\n" + " \"line\";", + format("a << \"line line line\";", + getLLVMStyleWithColumns(20))); + // In a chain of << with three operands, the second can be broken with no line + // break before it. + EXPECT_EQ("abcde << \"line \"\n" + " \"line line\"\n" + " << c;", + format("abcde << \"line line line\" << c;", + getLLVMStyleWithColumns(20))); + // In a chain of << with three operands, the third must be broken with a line + // break before it. + EXPECT_EQ("a << b\n" + " << \"line line \"\n" + " \"line\";", + format("a << b << \"line line line\";", + getLLVMStyleWithColumns(20))); + // In a chain of << with three operands, the second can be broken with no line + // break before it and the third must be broken with a line break before it. + EXPECT_EQ("abcd << \"line line \"\n" + " \"line\"\n" + " << \"line line \"\n" + " \"line\";", + format("abcd << \"line line line\" << \"line line line\";", + getLLVMStyleWithColumns(20))); + // In a chain of binary operators with two operands, the second can be broken + // with no line break before it. + EXPECT_EQ("abcd + \"line line \"\n" + " \"line line\";", + format("abcd + \"line line line line\";", + getLLVMStyleWithColumns(20))); + // In a chain of binary operators with three operands, the second must be + // broken with a line break before it. + EXPECT_EQ("abcd +\n" + " \"line line \"\n" + " \"line line\" +\n" + " e;", + format("abcd + \"line line line line\" + e;", + getLLVMStyleWithColumns(20))); + // In a function call with two operands, with AlignAfterOpenBracket enabled, + // the first must be broken with a line break before it. + FormatStyle Style = getLLVMStyleWithColumns(25); + Style.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak; + EXPECT_EQ("someFunction(\n" + " \"long long long \"\n" + " \"long\",\n" + " a);", + format("someFunction(\"long long long long\", a);", Style)); +} + TEST_F(FormatTest, DontSplitStringLiteralsWithEscapedNewlines) { EXPECT_EQ( "aaaaaaaaaaa = \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\\n"