xref: /llvm-project/clang-tools-extra/clangd/unittests/support/MarkupTests.cpp (revision 4d006520b8c0cc3a52913b4665bf741c737e5592)
1*fa1f4cf8SSam McCall //===-- MarkupTests.cpp ---------------------------------------------------===//
2*fa1f4cf8SSam McCall //
3*fa1f4cf8SSam McCall // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*fa1f4cf8SSam McCall // See https://llvm.org/LICENSE.txt for license information.
5*fa1f4cf8SSam McCall // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*fa1f4cf8SSam McCall //
7*fa1f4cf8SSam McCall //===----------------------------------------------------------------------===//
8*fa1f4cf8SSam McCall #include "support/Markup.h"
9*fa1f4cf8SSam McCall #include "clang/Basic/LLVM.h"
10*fa1f4cf8SSam McCall #include "llvm/ADT/StringRef.h"
11*fa1f4cf8SSam McCall #include "gmock/gmock.h"
12*fa1f4cf8SSam McCall #include "gtest/gtest.h"
13*fa1f4cf8SSam McCall 
14*fa1f4cf8SSam McCall namespace clang {
15*fa1f4cf8SSam McCall namespace clangd {
16*fa1f4cf8SSam McCall namespace markup {
17*fa1f4cf8SSam McCall namespace {
18*fa1f4cf8SSam McCall 
escape(llvm::StringRef Text)19*fa1f4cf8SSam McCall std::string escape(llvm::StringRef Text) {
20*fa1f4cf8SSam McCall   return Paragraph().appendText(Text.str()).asMarkdown();
21*fa1f4cf8SSam McCall }
22*fa1f4cf8SSam McCall 
23*fa1f4cf8SSam McCall MATCHER_P(escaped, C, "") {
24*fa1f4cf8SSam McCall   return testing::ExplainMatchResult(::testing::HasSubstr(std::string{'\\', C}),
25*fa1f4cf8SSam McCall                                      arg, result_listener);
26*fa1f4cf8SSam McCall }
27*fa1f4cf8SSam McCall 
28*fa1f4cf8SSam McCall MATCHER(escapedNone, "") {
29*fa1f4cf8SSam McCall   return testing::ExplainMatchResult(::testing::Not(::testing::HasSubstr("\\")),
30*fa1f4cf8SSam McCall                                      arg, result_listener);
31*fa1f4cf8SSam McCall }
32*fa1f4cf8SSam McCall 
TEST(Render,Escaping)33*fa1f4cf8SSam McCall TEST(Render, Escaping) {
34*fa1f4cf8SSam McCall   // Check all ASCII punctuation.
35*fa1f4cf8SSam McCall   std::string Punctuation = R"txt(!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~)txt";
36*fa1f4cf8SSam McCall   std::string EscapedPunc = R"txt(!"#$%&'()\*+,-./:;<=>?@[\\]^\_\`{|}~)txt";
37*fa1f4cf8SSam McCall   EXPECT_EQ(escape(Punctuation), EscapedPunc);
38*fa1f4cf8SSam McCall 
39*fa1f4cf8SSam McCall   // Inline code
40*fa1f4cf8SSam McCall   EXPECT_EQ(escape("`foo`"), R"(\`foo\`)");
41*fa1f4cf8SSam McCall   EXPECT_EQ(escape("`foo"), R"(\`foo)");
42*fa1f4cf8SSam McCall   EXPECT_EQ(escape("foo`"), R"(foo\`)");
43*fa1f4cf8SSam McCall   EXPECT_EQ(escape("``foo``"), R"(\`\`foo\`\`)");
44*fa1f4cf8SSam McCall   // Code blocks
45*fa1f4cf8SSam McCall   EXPECT_EQ(escape("```"), R"(\`\`\`)"); // This could also be inline code!
46*fa1f4cf8SSam McCall   EXPECT_EQ(escape("~~~"), R"(\~~~)");
47*fa1f4cf8SSam McCall 
48*fa1f4cf8SSam McCall   // Rulers and headings
49*fa1f4cf8SSam McCall   EXPECT_THAT(escape("## Heading"), escaped('#'));
50*fa1f4cf8SSam McCall   EXPECT_THAT(escape("Foo # bar"), escapedNone());
51*fa1f4cf8SSam McCall   EXPECT_EQ(escape("---"), R"(\---)");
52*fa1f4cf8SSam McCall   EXPECT_EQ(escape("-"), R"(\-)");
53*fa1f4cf8SSam McCall   EXPECT_EQ(escape("==="), R"(\===)");
54*fa1f4cf8SSam McCall   EXPECT_EQ(escape("="), R"(\=)");
55*fa1f4cf8SSam McCall   EXPECT_EQ(escape("***"), R"(\*\*\*)"); // \** could start emphasis!
56*fa1f4cf8SSam McCall 
57*fa1f4cf8SSam McCall   // HTML tags.
58*fa1f4cf8SSam McCall   EXPECT_THAT(escape("<pre"), escaped('<'));
59*fa1f4cf8SSam McCall   EXPECT_THAT(escape("< pre"), escapedNone());
60*fa1f4cf8SSam McCall   EXPECT_THAT(escape("if a<b then"), escaped('<'));
61*fa1f4cf8SSam McCall   EXPECT_THAT(escape("if a<b then c."), escapedNone());
62*fa1f4cf8SSam McCall   EXPECT_THAT(escape("if a<b then c='foo'."), escaped('<'));
63*fa1f4cf8SSam McCall   EXPECT_THAT(escape("std::vector<T>"), escaped('<'));
64*fa1f4cf8SSam McCall   EXPECT_THAT(escape("std::vector<std::string>"), escaped('<'));
65*fa1f4cf8SSam McCall   EXPECT_THAT(escape("std::map<int, int>"), escapedNone());
66*fa1f4cf8SSam McCall   // Autolinks
67*fa1f4cf8SSam McCall   EXPECT_THAT(escape("Email <foo@bar.com>"), escapedNone());
68*fa1f4cf8SSam McCall   EXPECT_THAT(escape("Website <http://foo.bar>"), escapedNone());
69*fa1f4cf8SSam McCall 
70*fa1f4cf8SSam McCall   // Bullet lists.
71*fa1f4cf8SSam McCall   EXPECT_THAT(escape("- foo"), escaped('-'));
72*fa1f4cf8SSam McCall   EXPECT_THAT(escape("* foo"), escaped('*'));
73*fa1f4cf8SSam McCall   EXPECT_THAT(escape("+ foo"), escaped('+'));
74*fa1f4cf8SSam McCall   EXPECT_THAT(escape("+"), escaped('+'));
75*fa1f4cf8SSam McCall   EXPECT_THAT(escape("a + foo"), escapedNone());
76*fa1f4cf8SSam McCall   EXPECT_THAT(escape("a+ foo"), escapedNone());
77*fa1f4cf8SSam McCall   EXPECT_THAT(escape("1. foo"), escaped('.'));
78*fa1f4cf8SSam McCall   EXPECT_THAT(escape("a. foo"), escapedNone());
79*fa1f4cf8SSam McCall 
80*fa1f4cf8SSam McCall   // Emphasis.
81*fa1f4cf8SSam McCall   EXPECT_EQ(escape("*foo*"), R"(\*foo\*)");
82*fa1f4cf8SSam McCall   EXPECT_EQ(escape("**foo**"), R"(\*\*foo\*\*)");
83*fa1f4cf8SSam McCall   EXPECT_THAT(escape("*foo"), escaped('*'));
84*fa1f4cf8SSam McCall   EXPECT_THAT(escape("foo *"), escapedNone());
85*fa1f4cf8SSam McCall   EXPECT_THAT(escape("foo * bar"), escapedNone());
86*fa1f4cf8SSam McCall   EXPECT_THAT(escape("foo_bar"), escapedNone());
87*fa1f4cf8SSam McCall   EXPECT_THAT(escape("foo _bar"), escaped('_'));
88*fa1f4cf8SSam McCall   EXPECT_THAT(escape("foo_ bar"), escaped('_'));
89*fa1f4cf8SSam McCall   EXPECT_THAT(escape("foo _ bar"), escapedNone());
90*fa1f4cf8SSam McCall 
91*fa1f4cf8SSam McCall   // HTML entities.
92*fa1f4cf8SSam McCall   EXPECT_THAT(escape("fish &chips;"), escaped('&'));
93*fa1f4cf8SSam McCall   EXPECT_THAT(escape("fish & chips;"), escapedNone());
94*fa1f4cf8SSam McCall   EXPECT_THAT(escape("fish &chips"), escapedNone());
95*fa1f4cf8SSam McCall   EXPECT_THAT(escape("foo &#42; bar"), escaped('&'));
96*fa1f4cf8SSam McCall   EXPECT_THAT(escape("foo &#xaf; bar"), escaped('&'));
97*fa1f4cf8SSam McCall   EXPECT_THAT(escape("foo &?; bar"), escapedNone());
98*fa1f4cf8SSam McCall 
99*fa1f4cf8SSam McCall   // Links.
100*fa1f4cf8SSam McCall   EXPECT_THAT(escape("[foo](bar)"), escaped(']'));
101*fa1f4cf8SSam McCall   EXPECT_THAT(escape("[foo]: bar"), escaped(']'));
102*fa1f4cf8SSam McCall   // No need to escape these, as the target never exists.
103*fa1f4cf8SSam McCall   EXPECT_THAT(escape("[foo][]"), escapedNone());
104*fa1f4cf8SSam McCall   EXPECT_THAT(escape("[foo][bar]"), escapedNone());
105*fa1f4cf8SSam McCall   EXPECT_THAT(escape("[foo]"), escapedNone());
106*fa1f4cf8SSam McCall 
107*fa1f4cf8SSam McCall   // In code blocks we don't need to escape ASCII punctuation.
108*fa1f4cf8SSam McCall   Paragraph P = Paragraph();
109*fa1f4cf8SSam McCall   P.appendCode("* foo !+ bar * baz");
110*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "`* foo !+ bar * baz`");
111*fa1f4cf8SSam McCall 
112*fa1f4cf8SSam McCall   // But we have to escape the backticks.
113*fa1f4cf8SSam McCall   P = Paragraph();
114*fa1f4cf8SSam McCall   P.appendCode("foo`bar`baz", /*Preserve=*/true);
115*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "`foo``bar``baz`");
116*fa1f4cf8SSam McCall   // In plain-text, we fall back to different quotes.
117*fa1f4cf8SSam McCall   EXPECT_EQ(P.asPlainText(), "'foo`bar`baz'");
118*fa1f4cf8SSam McCall 
119*fa1f4cf8SSam McCall   // Inline code blocks starting or ending with backticks should add spaces.
120*fa1f4cf8SSam McCall   P = Paragraph();
121*fa1f4cf8SSam McCall   P.appendCode("`foo");
122*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "` ``foo `");
123*fa1f4cf8SSam McCall   P = Paragraph();
124*fa1f4cf8SSam McCall   P.appendCode("foo`");
125*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "` foo`` `");
126*fa1f4cf8SSam McCall   P = Paragraph();
127*fa1f4cf8SSam McCall   P.appendCode("`foo`");
128*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "` ``foo`` `");
129*fa1f4cf8SSam McCall 
130*fa1f4cf8SSam McCall   // Code blocks might need more than 3 backticks.
131*fa1f4cf8SSam McCall   Document D;
132*fa1f4cf8SSam McCall   D.addCodeBlock("foobarbaz `\nqux");
133*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), "```cpp\n"
134*fa1f4cf8SSam McCall                             "foobarbaz `\nqux\n"
135*fa1f4cf8SSam McCall                             "```");
136*fa1f4cf8SSam McCall   D = Document();
137*fa1f4cf8SSam McCall   D.addCodeBlock("foobarbaz ``\nqux");
138*fa1f4cf8SSam McCall   EXPECT_THAT(D.asMarkdown(), "```cpp\n"
139*fa1f4cf8SSam McCall                               "foobarbaz ``\nqux\n"
140*fa1f4cf8SSam McCall                               "```");
141*fa1f4cf8SSam McCall   D = Document();
142*fa1f4cf8SSam McCall   D.addCodeBlock("foobarbaz ```\nqux");
143*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), "````cpp\n"
144*fa1f4cf8SSam McCall                             "foobarbaz ```\nqux\n"
145*fa1f4cf8SSam McCall                             "````");
146*fa1f4cf8SSam McCall   D = Document();
147*fa1f4cf8SSam McCall   D.addCodeBlock("foobarbaz ` `` ``` ```` `\nqux");
148*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), "`````cpp\n"
149*fa1f4cf8SSam McCall                             "foobarbaz ` `` ``` ```` `\nqux\n"
150*fa1f4cf8SSam McCall                             "`````");
151*fa1f4cf8SSam McCall }
152*fa1f4cf8SSam McCall 
TEST(Paragraph,Chunks)153*fa1f4cf8SSam McCall TEST(Paragraph, Chunks) {
154*fa1f4cf8SSam McCall   Paragraph P = Paragraph();
155*fa1f4cf8SSam McCall   P.appendText("One ");
156*fa1f4cf8SSam McCall   P.appendCode("fish");
157*fa1f4cf8SSam McCall   P.appendText(", two ");
158*fa1f4cf8SSam McCall   P.appendCode("fish", /*Preserve=*/true);
159*fa1f4cf8SSam McCall 
160*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "One `fish`, two `fish`");
161*fa1f4cf8SSam McCall   EXPECT_EQ(P.asPlainText(), "One fish, two `fish`");
162*fa1f4cf8SSam McCall }
163*fa1f4cf8SSam McCall 
TEST(Paragraph,SeparationOfChunks)164*fa1f4cf8SSam McCall TEST(Paragraph, SeparationOfChunks) {
165*fa1f4cf8SSam McCall   // This test keeps appending contents to a single Paragraph and checks
166*fa1f4cf8SSam McCall   // expected accumulated contents after each one.
167*fa1f4cf8SSam McCall   // Purpose is to check for separation between different chunks.
168*fa1f4cf8SSam McCall   Paragraph P;
169*fa1f4cf8SSam McCall 
170*fa1f4cf8SSam McCall   P.appendText("after ");
171*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "after");
172*fa1f4cf8SSam McCall   EXPECT_EQ(P.asPlainText(), "after");
173*fa1f4cf8SSam McCall 
174*fa1f4cf8SSam McCall   P.appendCode("foobar").appendSpace();
175*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "after `foobar`");
176*fa1f4cf8SSam McCall   EXPECT_EQ(P.asPlainText(), "after foobar");
177*fa1f4cf8SSam McCall 
178*fa1f4cf8SSam McCall   P.appendText("bat");
179*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "after `foobar` bat");
180*fa1f4cf8SSam McCall   EXPECT_EQ(P.asPlainText(), "after foobar bat");
181*fa1f4cf8SSam McCall 
182*fa1f4cf8SSam McCall   P.appendCode("no").appendCode("space");
183*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "after `foobar` bat`no` `space`");
184*fa1f4cf8SSam McCall   EXPECT_EQ(P.asPlainText(), "after foobar batno space");
185*fa1f4cf8SSam McCall }
186*fa1f4cf8SSam McCall 
TEST(Paragraph,ExtraSpaces)187*fa1f4cf8SSam McCall TEST(Paragraph, ExtraSpaces) {
188*fa1f4cf8SSam McCall   // Make sure spaces inside chunks are dropped.
189*fa1f4cf8SSam McCall   Paragraph P;
190*fa1f4cf8SSam McCall   P.appendText("foo\n   \t   baz");
191*fa1f4cf8SSam McCall   P.appendCode(" bar\n");
192*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "foo baz`bar`");
193*fa1f4cf8SSam McCall   EXPECT_EQ(P.asPlainText(), "foo bazbar");
194*fa1f4cf8SSam McCall }
195*fa1f4cf8SSam McCall 
TEST(Paragraph,SpacesCollapsed)196*fa1f4cf8SSam McCall TEST(Paragraph, SpacesCollapsed) {
197*fa1f4cf8SSam McCall   Paragraph P;
198*fa1f4cf8SSam McCall   P.appendText(" foo bar ");
199*fa1f4cf8SSam McCall   P.appendText(" baz ");
200*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "foo bar baz");
201*fa1f4cf8SSam McCall   EXPECT_EQ(P.asPlainText(), "foo bar baz");
202*fa1f4cf8SSam McCall }
203*fa1f4cf8SSam McCall 
TEST(Paragraph,NewLines)204*fa1f4cf8SSam McCall TEST(Paragraph, NewLines) {
205*fa1f4cf8SSam McCall   // New lines before and after chunks are dropped.
206*fa1f4cf8SSam McCall   Paragraph P;
207*fa1f4cf8SSam McCall   P.appendText(" \n foo\nbar\n ");
208*fa1f4cf8SSam McCall   P.appendCode(" \n foo\nbar \n ");
209*fa1f4cf8SSam McCall   EXPECT_EQ(P.asMarkdown(), "foo bar `foo bar`");
210*fa1f4cf8SSam McCall   EXPECT_EQ(P.asPlainText(), "foo bar foo bar");
211*fa1f4cf8SSam McCall }
212*fa1f4cf8SSam McCall 
TEST(Document,Separators)213*fa1f4cf8SSam McCall TEST(Document, Separators) {
214*fa1f4cf8SSam McCall   Document D;
215*fa1f4cf8SSam McCall   D.addParagraph().appendText("foo");
216*fa1f4cf8SSam McCall   D.addCodeBlock("test");
217*fa1f4cf8SSam McCall   D.addParagraph().appendText("bar");
218*fa1f4cf8SSam McCall 
219*fa1f4cf8SSam McCall   const char ExpectedMarkdown[] = R"md(foo
220*fa1f4cf8SSam McCall ```cpp
221*fa1f4cf8SSam McCall test
222*fa1f4cf8SSam McCall ```
223*fa1f4cf8SSam McCall bar)md";
224*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), ExpectedMarkdown);
225*fa1f4cf8SSam McCall 
226*fa1f4cf8SSam McCall   const char ExpectedText[] = R"pt(foo
227*fa1f4cf8SSam McCall 
228*fa1f4cf8SSam McCall test
229*fa1f4cf8SSam McCall 
230*fa1f4cf8SSam McCall bar)pt";
231*fa1f4cf8SSam McCall   EXPECT_EQ(D.asPlainText(), ExpectedText);
232*fa1f4cf8SSam McCall }
233*fa1f4cf8SSam McCall 
TEST(Document,Ruler)234*fa1f4cf8SSam McCall TEST(Document, Ruler) {
235*fa1f4cf8SSam McCall   Document D;
236*fa1f4cf8SSam McCall   D.addParagraph().appendText("foo");
237*fa1f4cf8SSam McCall   D.addRuler();
238*fa1f4cf8SSam McCall 
239*fa1f4cf8SSam McCall   // Ruler followed by paragraph.
240*fa1f4cf8SSam McCall   D.addParagraph().appendText("bar");
241*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), "foo  \n\n---\nbar");
242*fa1f4cf8SSam McCall   EXPECT_EQ(D.asPlainText(), "foo\n\nbar");
243*fa1f4cf8SSam McCall 
244*fa1f4cf8SSam McCall   D = Document();
245*fa1f4cf8SSam McCall   D.addParagraph().appendText("foo");
246*fa1f4cf8SSam McCall   D.addRuler();
247*fa1f4cf8SSam McCall   D.addCodeBlock("bar");
248*fa1f4cf8SSam McCall   // Ruler followed by a codeblock.
249*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), "foo  \n\n---\n```cpp\nbar\n```");
250*fa1f4cf8SSam McCall   EXPECT_EQ(D.asPlainText(), "foo\n\nbar");
251*fa1f4cf8SSam McCall 
252*fa1f4cf8SSam McCall   // Ruler followed by another ruler
253*fa1f4cf8SSam McCall   D = Document();
254*fa1f4cf8SSam McCall   D.addParagraph().appendText("foo");
255*fa1f4cf8SSam McCall   D.addRuler();
256*fa1f4cf8SSam McCall   D.addRuler();
257*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), "foo");
258*fa1f4cf8SSam McCall   EXPECT_EQ(D.asPlainText(), "foo");
259*fa1f4cf8SSam McCall 
260*fa1f4cf8SSam McCall   // Multiple rulers between blocks
261*fa1f4cf8SSam McCall   D.addRuler();
262*fa1f4cf8SSam McCall   D.addParagraph().appendText("foo");
263*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), "foo  \n\n---\nfoo");
264*fa1f4cf8SSam McCall   EXPECT_EQ(D.asPlainText(), "foo\n\nfoo");
265*fa1f4cf8SSam McCall }
266*fa1f4cf8SSam McCall 
TEST(Document,Append)267*fa1f4cf8SSam McCall TEST(Document, Append) {
268*fa1f4cf8SSam McCall   Document D;
269*fa1f4cf8SSam McCall   D.addParagraph().appendText("foo");
270*fa1f4cf8SSam McCall   D.addRuler();
271*fa1f4cf8SSam McCall   Document E;
272*fa1f4cf8SSam McCall   E.addRuler();
273*fa1f4cf8SSam McCall   E.addParagraph().appendText("bar");
274*fa1f4cf8SSam McCall   D.append(std::move(E));
275*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), "foo  \n\n---\nbar");
276*fa1f4cf8SSam McCall }
277*fa1f4cf8SSam McCall 
TEST(Document,Heading)278*fa1f4cf8SSam McCall TEST(Document, Heading) {
279*fa1f4cf8SSam McCall   Document D;
280*fa1f4cf8SSam McCall   D.addHeading(1).appendText("foo");
281*fa1f4cf8SSam McCall   D.addHeading(2).appendText("bar");
282*fa1f4cf8SSam McCall   D.addParagraph().appendText("baz");
283*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), "# foo  \n## bar  \nbaz");
284*fa1f4cf8SSam McCall   EXPECT_EQ(D.asPlainText(), "foo\nbar\nbaz");
285*fa1f4cf8SSam McCall }
286*fa1f4cf8SSam McCall 
TEST(CodeBlock,Render)287*fa1f4cf8SSam McCall TEST(CodeBlock, Render) {
288*fa1f4cf8SSam McCall   Document D;
289*fa1f4cf8SSam McCall   // Code blocks preserves any extra spaces.
290*fa1f4cf8SSam McCall   D.addCodeBlock("foo\n  bar\n  baz");
291*fa1f4cf8SSam McCall 
292*fa1f4cf8SSam McCall   llvm::StringRef ExpectedMarkdown =
293*fa1f4cf8SSam McCall       R"md(```cpp
294*fa1f4cf8SSam McCall foo
295*fa1f4cf8SSam McCall   bar
296*fa1f4cf8SSam McCall   baz
297*fa1f4cf8SSam McCall ```)md";
298*fa1f4cf8SSam McCall   llvm::StringRef ExpectedPlainText =
299*fa1f4cf8SSam McCall       R"pt(foo
300*fa1f4cf8SSam McCall   bar
301*fa1f4cf8SSam McCall   baz)pt";
302*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), ExpectedMarkdown);
303*fa1f4cf8SSam McCall   EXPECT_EQ(D.asPlainText(), ExpectedPlainText);
304*fa1f4cf8SSam McCall   D.addCodeBlock("foo");
305*fa1f4cf8SSam McCall   ExpectedMarkdown =
306*fa1f4cf8SSam McCall       R"md(```cpp
307*fa1f4cf8SSam McCall foo
308*fa1f4cf8SSam McCall   bar
309*fa1f4cf8SSam McCall   baz
310*fa1f4cf8SSam McCall ```
311*fa1f4cf8SSam McCall ```cpp
312*fa1f4cf8SSam McCall foo
313*fa1f4cf8SSam McCall ```)md";
314*fa1f4cf8SSam McCall   EXPECT_EQ(D.asMarkdown(), ExpectedMarkdown);
315*fa1f4cf8SSam McCall   ExpectedPlainText =
316*fa1f4cf8SSam McCall       R"pt(foo
317*fa1f4cf8SSam McCall   bar
318*fa1f4cf8SSam McCall   baz
319*fa1f4cf8SSam McCall 
320*fa1f4cf8SSam McCall foo)pt";
321*fa1f4cf8SSam McCall   EXPECT_EQ(D.asPlainText(), ExpectedPlainText);
322*fa1f4cf8SSam McCall }
323*fa1f4cf8SSam McCall 
TEST(BulletList,Render)324*fa1f4cf8SSam McCall TEST(BulletList, Render) {
325*fa1f4cf8SSam McCall   BulletList L;
326*fa1f4cf8SSam McCall   // Flat list
327*fa1f4cf8SSam McCall   L.addItem().addParagraph().appendText("foo");
328*fa1f4cf8SSam McCall   EXPECT_EQ(L.asMarkdown(), "- foo");
329*fa1f4cf8SSam McCall   EXPECT_EQ(L.asPlainText(), "- foo");
330*fa1f4cf8SSam McCall 
331*fa1f4cf8SSam McCall   L.addItem().addParagraph().appendText("bar");
332*fa1f4cf8SSam McCall   llvm::StringRef Expected = R"md(- foo
333*fa1f4cf8SSam McCall - bar)md";
334*fa1f4cf8SSam McCall   EXPECT_EQ(L.asMarkdown(), Expected);
335*fa1f4cf8SSam McCall   EXPECT_EQ(L.asPlainText(), Expected);
336*fa1f4cf8SSam McCall 
337*fa1f4cf8SSam McCall   // Nested list, with a single item.
338*fa1f4cf8SSam McCall   Document &D = L.addItem();
339*fa1f4cf8SSam McCall   // First item with foo\nbaz
340*fa1f4cf8SSam McCall   D.addParagraph().appendText("foo");
341*fa1f4cf8SSam McCall   D.addParagraph().appendText("baz");
342*fa1f4cf8SSam McCall 
343*fa1f4cf8SSam McCall   // Nest one level.
344*fa1f4cf8SSam McCall   Document &Inner = D.addBulletList().addItem();
345*fa1f4cf8SSam McCall   Inner.addParagraph().appendText("foo");
346*fa1f4cf8SSam McCall 
347*fa1f4cf8SSam McCall   // Nest one more level.
348*fa1f4cf8SSam McCall   BulletList &InnerList = Inner.addBulletList();
349*fa1f4cf8SSam McCall   // Single item, baz\nbaz
350*fa1f4cf8SSam McCall   Document &DeepDoc = InnerList.addItem();
351*fa1f4cf8SSam McCall   DeepDoc.addParagraph().appendText("baz");
352*fa1f4cf8SSam McCall   DeepDoc.addParagraph().appendText("baz");
353*fa1f4cf8SSam McCall   StringRef ExpectedMarkdown = R"md(- foo
354*fa1f4cf8SSam McCall - bar
355*fa1f4cf8SSam McCall - foo
356*fa1f4cf8SSam McCall   baz
357*fa1f4cf8SSam McCall   - foo
358*fa1f4cf8SSam McCall     - baz
359*fa1f4cf8SSam McCall       baz)md";
360*fa1f4cf8SSam McCall   EXPECT_EQ(L.asMarkdown(), ExpectedMarkdown);
361*fa1f4cf8SSam McCall   StringRef ExpectedPlainText = R"pt(- foo
362*fa1f4cf8SSam McCall - bar
363*fa1f4cf8SSam McCall - foo
364*fa1f4cf8SSam McCall   baz
365*fa1f4cf8SSam McCall   - foo
366*fa1f4cf8SSam McCall     - baz
367*fa1f4cf8SSam McCall       baz)pt";
368*fa1f4cf8SSam McCall   EXPECT_EQ(L.asPlainText(), ExpectedPlainText);
369*fa1f4cf8SSam McCall 
370*fa1f4cf8SSam McCall   // Termination
371*fa1f4cf8SSam McCall   Inner.addParagraph().appendText("after");
372*fa1f4cf8SSam McCall   ExpectedMarkdown = R"md(- foo
373*fa1f4cf8SSam McCall - bar
374*fa1f4cf8SSam McCall - foo
375*fa1f4cf8SSam McCall   baz
376*fa1f4cf8SSam McCall   - foo
377*fa1f4cf8SSam McCall     - baz
378*fa1f4cf8SSam McCall       baz
379*fa1f4cf8SSam McCall 
380*fa1f4cf8SSam McCall     after)md";
381*fa1f4cf8SSam McCall   EXPECT_EQ(L.asMarkdown(), ExpectedMarkdown);
382*fa1f4cf8SSam McCall   ExpectedPlainText = R"pt(- foo
383*fa1f4cf8SSam McCall - bar
384*fa1f4cf8SSam McCall - foo
385*fa1f4cf8SSam McCall   baz
386*fa1f4cf8SSam McCall   - foo
387*fa1f4cf8SSam McCall     - baz
388*fa1f4cf8SSam McCall       baz
389*fa1f4cf8SSam McCall     after)pt";
390*fa1f4cf8SSam McCall   EXPECT_EQ(L.asPlainText(), ExpectedPlainText);
391*fa1f4cf8SSam McCall }
392*fa1f4cf8SSam McCall 
393*fa1f4cf8SSam McCall } // namespace
394*fa1f4cf8SSam McCall } // namespace markup
395*fa1f4cf8SSam McCall } // namespace clangd
396*fa1f4cf8SSam McCall } // namespace clang
397