diff --git a/clang/lib/Format/BreakableToken.cpp b/clang/lib/Format/BreakableToken.cpp --- a/clang/lib/Format/BreakableToken.cpp +++ b/clang/lib/Format/BreakableToken.cpp @@ -176,13 +176,15 @@ if (ColumnLimit <= UsedColumns) return BreakableToken::Split(StringRef::npos, 0); unsigned MaxSplit = ColumnLimit - UsedColumns; - StringRef::size_type SpaceOffset = 0; + StringRef::size_type NewLine = 0; + StringRef::size_type AfterSpace = 0; StringRef::size_type SlashOffset = 0; StringRef::size_type WordStartOffset = 0; StringRef::size_type SplitPoint = 0; for (unsigned Chars = 0;;) { unsigned Advance; - if (Text[0] == '\\') { + bool EscapeSequence = Text[0] == '\\'; + if (EscapeSequence) { Advance = encoding::getEscapeSequenceLength(Text); Chars += Advance; } else { @@ -194,8 +196,21 @@ if (Chars > MaxSplit || Text.size() <= Advance) break; + if (EscapeSequence && Advance == 2) { + switch (Text[1]) { + case 'n': + NewLine = SplitPoint + 2; + break; + case 'f': + case 'r': + case 't': + case 'v': + AfterSpace = SplitPoint + 2; + break; + } + } if (IsBlank(Text[0])) - SpaceOffset = SplitPoint; + AfterSpace = SplitPoint + 1; if (Text[0] == '/') SlashOffset = SplitPoint; if (Advance == 1 && !isAlphanumeric(Text[0])) @@ -205,8 +220,10 @@ Text = Text.substr(Advance); } - if (SpaceOffset != 0) - return BreakableToken::Split(SpaceOffset + 1, 0); + if (NewLine != 0) + return BreakableToken::Split(NewLine, 0); + if (AfterSpace >= 2) + return BreakableToken::Split(AfterSpace, 0); if (SlashOffset != 0) return BreakableToken::Split(SlashOffset + 1, 0); if (WordStartOffset != 0) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -14815,6 +14815,33 @@ "\"/and\"", format("\"some/tex/and\"", getLLVMStyleWithColumns(6))); + // Escape sequences should be recognized. + verifyFormat(R"(x = "some\n" + "text";)", + R"(x = "some\ntext";)", getLLVMStyleWithColumns(12)); + verifyFormat(R"(x = "some\n" + "text";)", + R"(x = "some\ntext";)", getLLVMStyleWithColumns(13)); + verifyFormat(R"(x = "some\n" + " text";)", + R"(x = "some\n text";)", getLLVMStyleWithColumns(13)); + verifyFormat(R"(x = "some\t" + "text";)", + R"(x = "some\ttext";)", getLLVMStyleWithColumns(12)); + verifyFormat(R"(x = "some\t" + "text";)", + R"(x = "some\ttext";)", getLLVMStyleWithColumns(13)); + // A newline outside of the column limit should not cause a break. + verifyFormat(R"(x = "something " + "so\nshort";)", + R"(x = "something so\nshort";)", getLLVMStyleWithColumns(16)); + verifyFormat(R"(x = "something " + "so\nshort";)", + R"(x = "something so\nshort";)", getLLVMStyleWithColumns(19)); + verifyFormat(R"(x = "something so\n" + "short";)", + R"(x = "something so\nshort";)", getLLVMStyleWithColumns(20)); + EXPECT_EQ("variable =\n" " \"long string \"\n" " \"literal\";",