2019-05-07 22:18:18 +08:00
|
|
|
//===-- FormattedStringTests.cpp ------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "FormattedString.h"
|
|
|
|
#include "clang/Basic/LLVM.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
|
|
|
|
#include "gmock/gmock.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
TEST(FormattedString, Basic) {
|
|
|
|
FormattedString S;
|
|
|
|
EXPECT_EQ(S.renderAsPlainText(), "");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "");
|
|
|
|
|
2019-07-10 01:59:50 +08:00
|
|
|
S.appendText("foobar ");
|
|
|
|
S.appendText("baz");
|
|
|
|
EXPECT_EQ(S.renderAsPlainText(), "foobar baz");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "foobar baz");
|
2019-05-07 22:18:18 +08:00
|
|
|
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode("foobar");
|
|
|
|
EXPECT_EQ(S.renderAsPlainText(), "foobar");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "`foobar`");
|
|
|
|
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendCodeBlock("foobar");
|
|
|
|
EXPECT_EQ(S.renderAsPlainText(), "foobar");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "```cpp\n"
|
|
|
|
"foobar\n"
|
|
|
|
"```\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(FormattedString, CodeBlocks) {
|
|
|
|
FormattedString S;
|
|
|
|
S.appendCodeBlock("foobar");
|
|
|
|
S.appendCodeBlock("bazqux", "javascript");
|
2019-07-10 01:59:50 +08:00
|
|
|
S.appendText("after");
|
|
|
|
|
|
|
|
std::string ExpectedText = R"(foobar
|
|
|
|
|
|
|
|
bazqux
|
2019-05-07 22:18:18 +08:00
|
|
|
|
2019-07-10 01:59:50 +08:00
|
|
|
after)";
|
|
|
|
EXPECT_EQ(S.renderAsPlainText(), ExpectedText);
|
2019-05-07 22:18:18 +08:00
|
|
|
std::string ExpectedMarkdown = R"md(```cpp
|
|
|
|
foobar
|
|
|
|
```
|
|
|
|
```javascript
|
|
|
|
bazqux
|
|
|
|
```
|
2019-07-10 01:59:50 +08:00
|
|
|
after)md";
|
2019-05-07 22:18:18 +08:00
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), ExpectedMarkdown);
|
|
|
|
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode("foobar");
|
|
|
|
S.appendInlineCode("bazqux");
|
|
|
|
EXPECT_EQ(S.renderAsPlainText(), "foobar bazqux");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "`foobar` `bazqux`");
|
|
|
|
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendText("foo");
|
|
|
|
S.appendInlineCode("bar");
|
|
|
|
S.appendText("baz");
|
|
|
|
|
|
|
|
EXPECT_EQ(S.renderAsPlainText(), "foo bar baz");
|
2019-08-12 22:35:30 +08:00
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "foo `bar` baz");
|
2019-05-07 22:18:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(FormattedString, Escaping) {
|
|
|
|
// Check some ASCII punctuation
|
|
|
|
FormattedString S;
|
|
|
|
S.appendText("*!`");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "\\*\\!\\`");
|
|
|
|
|
|
|
|
// Check all ASCII punctuation.
|
|
|
|
S = FormattedString();
|
|
|
|
std::string Punctuation = R"txt(!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~)txt";
|
|
|
|
// Same text, with each character escaped.
|
|
|
|
std::string EscapedPunctuation;
|
|
|
|
EscapedPunctuation.reserve(2 * Punctuation.size());
|
|
|
|
for (char C : Punctuation)
|
|
|
|
EscapedPunctuation += std::string("\\") + C;
|
|
|
|
S.appendText(Punctuation);
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), EscapedPunctuation);
|
|
|
|
|
|
|
|
// In code blocks we don't need to escape ASCII punctuation.
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode("* foo !+ bar * baz");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "`* foo !+ bar * baz`");
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendCodeBlock("#define FOO\n* foo !+ bar * baz");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "```cpp\n"
|
|
|
|
"#define FOO\n* foo !+ bar * baz\n"
|
|
|
|
"```\n");
|
|
|
|
|
|
|
|
// But we have to escape the backticks.
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode("foo`bar`baz");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "`foo``bar``baz`");
|
|
|
|
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendCodeBlock("foo`bar`baz");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "```cpp\n"
|
|
|
|
"foo`bar`baz\n"
|
|
|
|
"```\n");
|
|
|
|
|
|
|
|
// Inline code blocks starting or ending with backticks should add spaces.
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode("`foo");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "` ``foo `");
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode("foo`");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "` foo`` `");
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode("`foo`");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "` ``foo`` `");
|
|
|
|
|
|
|
|
// Should also add extra spaces if the block stars and ends with spaces.
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode(" foo ");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "` foo `");
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode("foo ");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "`foo `");
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode(" foo");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "` foo`");
|
|
|
|
|
|
|
|
// Code blocks might need more than 3 backticks.
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendCodeBlock("foobarbaz `\nqux");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "```cpp\n"
|
|
|
|
"foobarbaz `\nqux\n"
|
|
|
|
"```\n");
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendCodeBlock("foobarbaz ``\nqux");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "```cpp\n"
|
|
|
|
"foobarbaz ``\nqux\n"
|
|
|
|
"```\n");
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendCodeBlock("foobarbaz ```\nqux");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "````cpp\n"
|
|
|
|
"foobarbaz ```\nqux\n"
|
|
|
|
"````\n");
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendCodeBlock("foobarbaz ` `` ``` ```` `\nqux");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "`````cpp\n"
|
|
|
|
"foobarbaz ` `` ``` ```` `\nqux\n"
|
|
|
|
"`````\n");
|
|
|
|
}
|
|
|
|
|
2019-08-12 22:35:30 +08:00
|
|
|
TEST(FormattedString, MarkdownWhitespace) {
|
|
|
|
// Whitespace should be added as separators between blocks.
|
|
|
|
FormattedString S;
|
|
|
|
S.appendText("foo");
|
|
|
|
S.appendText("bar");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "foo bar");
|
|
|
|
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode("foo");
|
|
|
|
S.appendInlineCode("bar");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "`foo` `bar`");
|
|
|
|
|
|
|
|
// However, we don't want to add any extra whitespace.
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendText("foo ");
|
|
|
|
S.appendInlineCode("bar");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "foo `bar`");
|
|
|
|
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendText("foo\n");
|
|
|
|
S.appendInlineCode("bar");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "foo\n`bar`");
|
|
|
|
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendInlineCode("foo");
|
|
|
|
S.appendText(" bar");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "`foo` bar");
|
|
|
|
|
|
|
|
S = FormattedString();
|
|
|
|
S.appendText("foo");
|
|
|
|
S.appendCodeBlock("bar");
|
|
|
|
S.appendText("baz");
|
|
|
|
EXPECT_EQ(S.renderAsMarkdown(), "foo\n```cpp\nbar\n```\nbaz");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-07 22:18:18 +08:00
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|