forked from OSchip/llvm-project
271 lines
6.9 KiB
C++
271 lines
6.9 KiB
C++
//===-- 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 "llvm/Support/raw_ostream.h"
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace clang {
|
|
namespace clangd {
|
|
namespace markup {
|
|
namespace {
|
|
|
|
TEST(Render, Escaping) {
|
|
// Check some ASCII punctuation
|
|
Paragraph P;
|
|
P.appendText("*!`");
|
|
EXPECT_EQ(P.asMarkdown(), "\\*\\!\\`");
|
|
|
|
// Check all ASCII punctuation.
|
|
P = Paragraph();
|
|
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;
|
|
P.appendText(Punctuation);
|
|
EXPECT_EQ(P.asMarkdown(), EscapedPunctuation);
|
|
|
|
// In code blocks we don't need to escape ASCII punctuation.
|
|
P = Paragraph();
|
|
P.appendCode("* foo !+ bar * baz");
|
|
EXPECT_EQ(P.asMarkdown(), "`* foo !+ bar * baz`");
|
|
|
|
// But we have to escape the backticks.
|
|
P = Paragraph();
|
|
P.appendCode("foo`bar`baz");
|
|
EXPECT_EQ(P.asMarkdown(), "`foo``bar``baz`");
|
|
|
|
// Inline code blocks starting or ending with backticks should add spaces.
|
|
P = Paragraph();
|
|
P.appendCode("`foo");
|
|
EXPECT_EQ(P.asMarkdown(), "` ``foo `");
|
|
P = Paragraph();
|
|
P.appendCode("foo`");
|
|
EXPECT_EQ(P.asMarkdown(), "` foo`` `");
|
|
P = Paragraph();
|
|
P.appendCode("`foo`");
|
|
EXPECT_EQ(P.asMarkdown(), "` ``foo`` `");
|
|
|
|
// Code blocks might need more than 3 backticks.
|
|
Document D;
|
|
D.addCodeBlock("foobarbaz `\nqux");
|
|
EXPECT_EQ(D.asMarkdown(), "```cpp\n"
|
|
"foobarbaz `\nqux\n"
|
|
"```");
|
|
D = Document();
|
|
D.addCodeBlock("foobarbaz ``\nqux");
|
|
EXPECT_THAT(D.asMarkdown(), "```cpp\n"
|
|
"foobarbaz ``\nqux\n"
|
|
"```");
|
|
D = Document();
|
|
D.addCodeBlock("foobarbaz ```\nqux");
|
|
EXPECT_EQ(D.asMarkdown(), "````cpp\n"
|
|
"foobarbaz ```\nqux\n"
|
|
"````");
|
|
D = Document();
|
|
D.addCodeBlock("foobarbaz ` `` ``` ```` `\nqux");
|
|
EXPECT_EQ(D.asMarkdown(), "`````cpp\n"
|
|
"foobarbaz ` `` ``` ```` `\nqux\n"
|
|
"`````");
|
|
}
|
|
|
|
TEST(Paragraph, SeparationOfChunks) {
|
|
// This test keeps appending contents to a single Paragraph and checks
|
|
// expected accumulated contents after each one.
|
|
// Purpose is to check for separation between different chunks.
|
|
Paragraph P;
|
|
|
|
P.appendText("after");
|
|
EXPECT_EQ(P.asMarkdown(), "after");
|
|
EXPECT_EQ(P.asPlainText(), "after");
|
|
|
|
P.appendCode("foobar");
|
|
EXPECT_EQ(P.asMarkdown(), "after `foobar`");
|
|
EXPECT_EQ(P.asPlainText(), "after foobar");
|
|
|
|
P.appendText("bat");
|
|
EXPECT_EQ(P.asMarkdown(), "after `foobar` bat");
|
|
EXPECT_EQ(P.asPlainText(), "after foobar bat");
|
|
}
|
|
|
|
TEST(Paragraph, ExtraSpaces) {
|
|
// Make sure spaces inside chunks are dropped.
|
|
Paragraph P;
|
|
P.appendText("foo\n \t baz");
|
|
P.appendCode(" bar\n");
|
|
EXPECT_EQ(P.asMarkdown(), "foo baz `bar`");
|
|
EXPECT_EQ(P.asPlainText(), "foo baz bar");
|
|
}
|
|
|
|
TEST(Paragraph, NewLines) {
|
|
// New lines before and after chunks are dropped.
|
|
Paragraph P;
|
|
P.appendText(" \n foo\nbar\n ");
|
|
P.appendCode(" \n foo\nbar \n ");
|
|
EXPECT_EQ(P.asMarkdown(), "foo bar `foo bar`");
|
|
EXPECT_EQ(P.asPlainText(), "foo bar foo bar");
|
|
}
|
|
|
|
TEST(Document, Separators) {
|
|
Document D;
|
|
D.addParagraph().appendText("foo");
|
|
D.addCodeBlock("test");
|
|
D.addParagraph().appendText("bar");
|
|
|
|
const char ExpectedMarkdown[] = R"md(foo
|
|
```cpp
|
|
test
|
|
```
|
|
bar)md";
|
|
EXPECT_EQ(D.asMarkdown(), ExpectedMarkdown);
|
|
|
|
const char ExpectedText[] = R"pt(foo
|
|
|
|
test
|
|
|
|
bar)pt";
|
|
EXPECT_EQ(D.asPlainText(), ExpectedText);
|
|
}
|
|
|
|
TEST(Document, Spacer) {
|
|
Document D;
|
|
D.addParagraph().appendText("foo");
|
|
D.addSpacer();
|
|
D.addParagraph().appendText("bar");
|
|
EXPECT_EQ(D.asMarkdown(), "foo \n\nbar");
|
|
EXPECT_EQ(D.asPlainText(), "foo\n\nbar");
|
|
}
|
|
|
|
TEST(Document, Heading) {
|
|
Document D;
|
|
D.addHeading(1).appendText("foo");
|
|
D.addHeading(2).appendText("bar");
|
|
D.addParagraph().appendText("baz");
|
|
EXPECT_EQ(D.asMarkdown(), "# foo \n## bar \nbaz");
|
|
EXPECT_EQ(D.asPlainText(), "foo\nbar\nbaz");
|
|
}
|
|
|
|
TEST(CodeBlock, Render) {
|
|
Document D;
|
|
// Code blocks preserves any extra spaces.
|
|
D.addCodeBlock("foo\n bar\n baz");
|
|
|
|
llvm::StringRef ExpectedMarkdown =
|
|
R"md(```cpp
|
|
foo
|
|
bar
|
|
baz
|
|
```)md";
|
|
llvm::StringRef ExpectedPlainText =
|
|
R"pt(foo
|
|
bar
|
|
baz)pt";
|
|
EXPECT_EQ(D.asMarkdown(), ExpectedMarkdown);
|
|
EXPECT_EQ(D.asPlainText(), ExpectedPlainText);
|
|
D.addCodeBlock("foo");
|
|
ExpectedMarkdown =
|
|
R"md(```cpp
|
|
foo
|
|
bar
|
|
baz
|
|
```
|
|
```cpp
|
|
foo
|
|
```)md";
|
|
EXPECT_EQ(D.asMarkdown(), ExpectedMarkdown);
|
|
// FIXME: we shouldn't have 2 empty lines in between. A solution might be
|
|
// having a `verticalMargin` method for blocks, and let container insert new
|
|
// lines according to that before/after blocks.
|
|
ExpectedPlainText =
|
|
R"pt(foo
|
|
bar
|
|
baz
|
|
|
|
|
|
foo)pt";
|
|
EXPECT_EQ(D.asPlainText(), ExpectedPlainText);
|
|
}
|
|
|
|
TEST(BulletList, Render) {
|
|
BulletList L;
|
|
// Flat list
|
|
L.addItem().addParagraph().appendText("foo");
|
|
EXPECT_EQ(L.asMarkdown(), "- foo");
|
|
EXPECT_EQ(L.asPlainText(), "- foo");
|
|
|
|
L.addItem().addParagraph().appendText("bar");
|
|
llvm::StringRef Expected = R"md(- foo
|
|
- bar)md";
|
|
EXPECT_EQ(L.asMarkdown(), Expected);
|
|
EXPECT_EQ(L.asPlainText(), Expected);
|
|
|
|
// Nested list, with a single item.
|
|
Document &D = L.addItem();
|
|
// First item with foo\nbaz
|
|
D.addParagraph().appendText("foo");
|
|
D.addParagraph().appendText("baz");
|
|
|
|
// Nest one level.
|
|
Document &Inner = D.addBulletList().addItem();
|
|
Inner.addParagraph().appendText("foo");
|
|
|
|
// Nest one more level.
|
|
BulletList &InnerList = Inner.addBulletList();
|
|
// Single item, baz\nbaz
|
|
Document &DeepDoc = InnerList.addItem();
|
|
DeepDoc.addParagraph().appendText("baz");
|
|
DeepDoc.addParagraph().appendText("baz");
|
|
StringRef ExpectedMarkdown = R"md(- foo
|
|
- bar
|
|
- foo
|
|
baz
|
|
- foo
|
|
- baz
|
|
baz)md";
|
|
EXPECT_EQ(L.asMarkdown(), ExpectedMarkdown);
|
|
StringRef ExpectedPlainText = R"pt(- foo
|
|
- bar
|
|
- foo
|
|
baz
|
|
- foo
|
|
- baz
|
|
baz)pt";
|
|
EXPECT_EQ(L.asPlainText(), ExpectedPlainText);
|
|
|
|
// Termination
|
|
Inner.addParagraph().appendText("after");
|
|
ExpectedMarkdown = R"md(- foo
|
|
- bar
|
|
- foo
|
|
baz
|
|
- foo
|
|
- baz
|
|
baz
|
|
|
|
after)md";
|
|
EXPECT_EQ(L.asMarkdown(), ExpectedMarkdown);
|
|
ExpectedPlainText = R"pt(- foo
|
|
- bar
|
|
- foo
|
|
baz
|
|
- foo
|
|
- baz
|
|
baz
|
|
after)pt";
|
|
EXPECT_EQ(L.asPlainText(), ExpectedPlainText);
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace markup
|
|
} // namespace clangd
|
|
} // namespace clang
|