Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -136,8 +136,32 @@ } // If binary operators are moved to the next line (including commas for some - // styles of constructor initializers), that's always ok. - if (!Current.isOneOf(TT_BinaryOperator, tok::comma) && + // styles of constructor initializers), that's always ok. Also the second + // element in a sequence of two consecutive string literals is ok to be + // moved to the next line. + bool ContinuesStringLiteral = Current.isStringLiteral() && Previous.isStringLiteral(); + if (!ContinuesStringLiteral) { + // In case of ObjC string literals, the following code: + // @"line1" + // @"line2" + // turns into the sequence of tokens: + // (@, TT_ObjCLiteral), + // ("line1", TT_Unknown), + // (@, TT_ObjCLiteral), + // ("line2", TT_Unknown), + // so we need to specially check for that. + ContinuesStringLiteral = Current.is(TT_ObjCStringLiteral) && + Previous.is(TT_Unknown) && + Previous.Previous && + Previous.Previous->is(TT_ObjCStringLiteral); + } + DEBUG({ + llvm::dbgs() << "Previous = " << Previous.TokenText << "\n"; + llvm::dbgs() << "Current = " << Current.TokenText << "\n"; + llvm::dbgs() << "ContinuesStringLiteral = " << ContinuesStringLiteral << "\n"; + }); + if (!(Current.isOneOf(TT_BinaryOperator, tok::comma) || + ContinuesStringLiteral) && State.Stack.back().NoLineBreakInOperand) return false; Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -6381,6 +6381,42 @@ " \"text \" \\\n" " \"other\";", format("#define A \"some text other\";", AlignLeft)); + + // The second of two consecutive string literals can be put on a newline. + EXPECT_EQ("long_long_long_long\n" + " << long_long_long_long << \"long lo\"\n" + " \"ng\"", + format("long_long_long_long\n" + " << long_long_long_long << \"long lo\"\n" + " \"ng\"", + getLLVMStyleWithColumns(40))); + EXPECT_EQ("long_long_long_long(long_lon, \"long lo\"\n" + " \"ng\");", + format("long_long_long_long(long_lon, \"long lo\"\n" + " \"ng\");")); + // The second and third of three consecutive string literals can be put on a + // newline. + EXPECT_EQ("long_long_long_long\n" + " << long_long_long_long << \"long lo\"\n" + " \"long lo\"\n" + " \"long lo\"", + format("long_long_long_long\n" + " << long_long_long_long << \"long lo\"\n" + " \"long lo\"\n" + " \"long lo\"", + getLLVMStyleWithColumns(40))); + EXPECT_EQ("long_long_long_long(long_lon, \"long lo\"\n" + " \"long lo\"\n" + " \"ng\");", + format("long_long_long_long(long_lon, \"long lo\"\n" + " \"long lo\"\n" + " \"ng\");")); + EXPECT_EQ("long_long_long_long(long_lon, L\"long lo\"\n" + " U\"long lo\"\n" + " u8\"ng\");", + format("long_long_long_long(long_lon, L\"long lo\"\n" + " U\"long lo\"\n" + " u8\"ng\");")); } TEST_F(FormatTest, FullyRemoveEmptyLines) { Index: unittests/Format/FormatTestObjC.cpp =================================================================== --- unittests/Format/FormatTestObjC.cpp +++ unittests/Format/FormatTestObjC.cpp @@ -772,6 +772,38 @@ " NSFontAttributeNameeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee : " "regularFont,\n" "};"); + + // The second of two consecutive string literals can be but on a newline. + Style = getGoogleStyle(FormatStyle::LK_ObjC); + Style.ColumnLimit = 40; + EXPECT_EQ("long_long_long_long\n" + " << long_long_long_long << @\"long lo\"\n" + " @\"ng\"", + format("long_long_long_long\n" + " << long_long_long_long << @\"long lo\"\n" + " @\"ng\"")); + EXPECT_EQ("long_long_long_long(long_lon, @\"long lo\"\n" + " @\"ng\");", + format("long_long_long_long(long_lon, @\"long lo\"\n" + " @\"ng\");")); + // The second and third of three consecutive string literals can be but on a + // newline. + Style = getGoogleStyle(FormatStyle::LK_ObjC); + Style.ColumnLimit = 40; + EXPECT_EQ("long_long_long_long\n" + " << long_long_long_long << @\"long lo\"\n" + " @\"long lo\"\n" + " @\"ng\"", + format("long_long_long_long\n" + " << long_long_long_long << @\"long lo\"\n" + " @\"long lo\"\n" + " @\"ng\"")); + EXPECT_EQ("long_long_long_long(long_lon, @\"long lo\"\n" + " @\"long lo\"\n" + " @\"ng\");", + format("long_long_long_long(long_lon, @\"long lo\"\n" + " @\"long lo\"\n" + " @\"ng\");")); } TEST_F(FormatTestObjC, ObjCArrayLiterals) {