diff --git a/clang-tools-extra/clangd/FormattedString.cpp b/clang-tools-extra/clangd/FormattedString.cpp --- a/clang-tools-extra/clangd/FormattedString.cpp +++ b/clang-tools-extra/clangd/FormattedString.cpp @@ -23,17 +23,16 @@ // Escaping ASCII punctiation ensures we can't start a markdown construct. constexpr llvm::StringLiteral Punctuation = R"txt(!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~)txt"; - std::string R; - for (size_t From = 0; From < Input.size();) { - size_t Next = Input.find_first_of(Punctuation, From); - R += Input.substr(From, Next - From); - if (Next == llvm::StringRef::npos) - break; - R += "\\"; - R += Input[Next]; - - From = Next + 1; + for (char C : Input) { + if (Punctuation.contains(C)) { + // Has to be escaped. + R += "\\"; + } else if (C == '\n') { + // Putting two spaces at the end of the line preserves line breaks. + R += " "; + } + R += C; } return R; } diff --git a/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp b/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp --- a/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp +++ b/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp @@ -179,7 +179,7 @@ S = FormattedString(); S.appendText("foo\n"); S.appendInlineCode("bar"); - EXPECT_EQ(S.renderAsMarkdown(), "foo\n`bar`"); + EXPECT_EQ(S.renderAsMarkdown(), "foo \n`bar`"); S = FormattedString(); S.appendInlineCode("foo"); @@ -193,6 +193,12 @@ EXPECT_EQ(S.renderAsMarkdown(), "foo\n```cpp\nbar\n```\nbaz"); } +TEST(FormattedString, MarkdownLineBreaks) { + FormattedString S; + S.appendText("foo\nbar\nbaz"); + // To preserve line breaks, two spaces are added at the end of each line. + EXPECT_EQ(S.renderAsMarkdown(), "foo \nbar \nbaz"); +} } // namespace } // namespace clangd