1 //===-- clang-doc/MDGeneratorTest.cpp -------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "ClangDocTest.h"
10 #include "Generators.h"
11 #include "Representation.h"
12 #include "gtest/gtest.h"
13
14 namespace clang {
15 namespace doc {
16
getMDGenerator()17 std::unique_ptr<Generator> getMDGenerator() {
18 auto G = doc::findGeneratorByName("md");
19 if (!G)
20 return nullptr;
21 return std::move(G.get());
22 }
23
TEST(MDGeneratorTest,emitNamespaceMD)24 TEST(MDGeneratorTest, emitNamespaceMD) {
25 NamespaceInfo I;
26 I.Name = "Namespace";
27 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
28
29 I.ChildNamespaces.emplace_back(EmptySID, "ChildNamespace",
30 InfoType::IT_namespace);
31 I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
32 I.ChildFunctions.emplace_back();
33 I.ChildFunctions.back().Name = "OneFunction";
34 I.ChildFunctions.back().Access = AccessSpecifier::AS_none;
35 I.ChildEnums.emplace_back();
36 I.ChildEnums.back().Name = "OneEnum";
37
38 auto G = getMDGenerator();
39 assert(G);
40 std::string Buffer;
41 llvm::raw_string_ostream Actual(Buffer);
42 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());
43 assert(!Err);
44 std::string Expected = R"raw(# namespace Namespace
45
46
47
48 ## Namespaces
49
50 * [ChildNamespace](../ChildNamespace/index.md)
51
52
53 ## Records
54
55 * [ChildStruct](../ChildStruct.md)
56
57
58 ## Functions
59
60 ### OneFunction
61
62 * OneFunction()*
63
64
65
66 ## Enums
67
68 | enum OneEnum |
69
70 --
71
72
73
74
75
76 )raw";
77 EXPECT_EQ(Expected, Actual.str());
78 }
79
TEST(MDGeneratorTest,emitRecordMD)80 TEST(MDGeneratorTest, emitRecordMD) {
81 RecordInfo I;
82 I.Name = "r";
83 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
84
85 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
86 I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
87
88 I.Members.emplace_back("int", "X", AccessSpecifier::AS_private);
89 I.TagType = TagTypeKind::TTK_Class;
90 I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
91 I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
92
93 I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
94 I.ChildFunctions.emplace_back();
95 I.ChildFunctions.back().Name = "OneFunction";
96 I.ChildEnums.emplace_back();
97 I.ChildEnums.back().Name = "OneEnum";
98
99 auto G = getMDGenerator();
100 assert(G);
101 std::string Buffer;
102 llvm::raw_string_ostream Actual(Buffer);
103 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());
104 assert(!Err);
105 std::string Expected = R"raw(# class r
106
107 *Defined at test.cpp#10*
108
109 Inherits from F, G
110
111
112
113 ## Members
114
115 private int X
116
117
118
119 ## Records
120
121 ChildStruct
122
123
124
125 ## Functions
126
127 ### OneFunction
128
129 *public OneFunction()*
130
131
132
133 ## Enums
134
135 | enum OneEnum |
136
137 --
138
139
140
141
142
143 )raw";
144 EXPECT_EQ(Expected, Actual.str());
145 }
146
TEST(MDGeneratorTest,emitFunctionMD)147 TEST(MDGeneratorTest, emitFunctionMD) {
148 FunctionInfo I;
149 I.Name = "f";
150 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
151
152 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
153 I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
154
155 I.Access = AccessSpecifier::AS_none;
156
157 I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
158 I.Params.emplace_back("int", "P");
159 I.IsMethod = true;
160 I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
161
162 auto G = getMDGenerator();
163 assert(G);
164 std::string Buffer;
165 llvm::raw_string_ostream Actual(Buffer);
166 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());
167 assert(!Err);
168 std::string Expected = R"raw(### f
169
170 *void f(int P)*
171
172 *Defined at test.cpp#10*
173
174 )raw";
175
176 EXPECT_EQ(Expected, Actual.str());
177 }
178
TEST(MDGeneratorTest,emitEnumMD)179 TEST(MDGeneratorTest, emitEnumMD) {
180 EnumInfo I;
181 I.Name = "e";
182 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
183
184 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
185 I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
186
187 I.Members.emplace_back("X");
188 I.Scoped = true;
189
190 auto G = getMDGenerator();
191 assert(G);
192 std::string Buffer;
193 llvm::raw_string_ostream Actual(Buffer);
194 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());
195 assert(!Err);
196 std::string Expected = R"raw(| enum class e |
197
198 --
199
200 | X |
201
202
203 *Defined at test.cpp#10*
204
205 )raw";
206
207 EXPECT_EQ(Expected, Actual.str());
208 }
209
TEST(MDGeneratorTest,emitCommentMD)210 TEST(MDGeneratorTest, emitCommentMD) {
211 FunctionInfo I;
212 I.Name = "f";
213 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
214 I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
215 I.Params.emplace_back("int", "I");
216 I.Params.emplace_back("int", "J");
217 I.Access = AccessSpecifier::AS_none;
218
219 CommentInfo Top;
220 Top.Kind = "FullComment";
221
222 Top.Children.emplace_back(std::make_unique<CommentInfo>());
223 CommentInfo *BlankLine = Top.Children.back().get();
224 BlankLine->Kind = "ParagraphComment";
225 BlankLine->Children.emplace_back(std::make_unique<CommentInfo>());
226 BlankLine->Children.back()->Kind = "TextComment";
227
228 Top.Children.emplace_back(std::make_unique<CommentInfo>());
229 CommentInfo *Brief = Top.Children.back().get();
230 Brief->Kind = "ParagraphComment";
231 Brief->Children.emplace_back(std::make_unique<CommentInfo>());
232 Brief->Children.back()->Kind = "TextComment";
233 Brief->Children.back()->Name = "ParagraphComment";
234 Brief->Children.back()->Text = " Brief description.";
235
236 Top.Children.emplace_back(std::make_unique<CommentInfo>());
237 CommentInfo *Extended = Top.Children.back().get();
238 Extended->Kind = "ParagraphComment";
239 Extended->Children.emplace_back(std::make_unique<CommentInfo>());
240 Extended->Children.back()->Kind = "TextComment";
241 Extended->Children.back()->Text = " Extended description that";
242 Extended->Children.emplace_back(std::make_unique<CommentInfo>());
243 Extended->Children.back()->Kind = "TextComment";
244 Extended->Children.back()->Text = " continues onto the next line.";
245
246 Top.Children.emplace_back(std::make_unique<CommentInfo>());
247 CommentInfo *HTML = Top.Children.back().get();
248 HTML->Kind = "ParagraphComment";
249 HTML->Children.emplace_back(std::make_unique<CommentInfo>());
250 HTML->Children.back()->Kind = "TextComment";
251 HTML->Children.emplace_back(std::make_unique<CommentInfo>());
252 HTML->Children.back()->Kind = "HTMLStartTagComment";
253 HTML->Children.back()->Name = "ul";
254 HTML->Children.back()->AttrKeys.emplace_back("class");
255 HTML->Children.back()->AttrValues.emplace_back("test");
256 HTML->Children.emplace_back(std::make_unique<CommentInfo>());
257 HTML->Children.back()->Kind = "HTMLStartTagComment";
258 HTML->Children.back()->Name = "li";
259 HTML->Children.emplace_back(std::make_unique<CommentInfo>());
260 HTML->Children.back()->Kind = "TextComment";
261 HTML->Children.back()->Text = " Testing.";
262 HTML->Children.emplace_back(std::make_unique<CommentInfo>());
263 HTML->Children.back()->Kind = "HTMLEndTagComment";
264 HTML->Children.back()->Name = "ul";
265 HTML->Children.back()->SelfClosing = true;
266
267 Top.Children.emplace_back(std::make_unique<CommentInfo>());
268 CommentInfo *Verbatim = Top.Children.back().get();
269 Verbatim->Kind = "VerbatimBlockComment";
270 Verbatim->Name = "verbatim";
271 Verbatim->CloseName = "endverbatim";
272 Verbatim->Children.emplace_back(std::make_unique<CommentInfo>());
273 Verbatim->Children.back()->Kind = "VerbatimBlockLineComment";
274 Verbatim->Children.back()->Text = " The description continues.";
275
276 Top.Children.emplace_back(std::make_unique<CommentInfo>());
277 CommentInfo *ParamOut = Top.Children.back().get();
278 ParamOut->Kind = "ParamCommandComment";
279 ParamOut->Direction = "[out]";
280 ParamOut->ParamName = "I";
281 ParamOut->Explicit = true;
282 ParamOut->Children.emplace_back(std::make_unique<CommentInfo>());
283 ParamOut->Children.back()->Kind = "ParagraphComment";
284 ParamOut->Children.back()->Children.emplace_back(
285 std::make_unique<CommentInfo>());
286 ParamOut->Children.back()->Children.back()->Kind = "TextComment";
287 ParamOut->Children.back()->Children.emplace_back(
288 std::make_unique<CommentInfo>());
289 ParamOut->Children.back()->Children.back()->Kind = "TextComment";
290 ParamOut->Children.back()->Children.back()->Text = " is a parameter.";
291
292 Top.Children.emplace_back(std::make_unique<CommentInfo>());
293 CommentInfo *ParamIn = Top.Children.back().get();
294 ParamIn->Kind = "ParamCommandComment";
295 ParamIn->Direction = "[in]";
296 ParamIn->ParamName = "J";
297 ParamIn->Children.emplace_back(std::make_unique<CommentInfo>());
298 ParamIn->Children.back()->Kind = "ParagraphComment";
299 ParamIn->Children.back()->Children.emplace_back(
300 std::make_unique<CommentInfo>());
301 ParamIn->Children.back()->Children.back()->Kind = "TextComment";
302 ParamIn->Children.back()->Children.back()->Text = " is a parameter.";
303 ParamIn->Children.back()->Children.emplace_back(
304 std::make_unique<CommentInfo>());
305 ParamIn->Children.back()->Children.back()->Kind = "TextComment";
306
307 Top.Children.emplace_back(std::make_unique<CommentInfo>());
308 CommentInfo *Return = Top.Children.back().get();
309 Return->Kind = "BlockCommandComment";
310 Return->Name = "return";
311 Return->Explicit = true;
312 Return->Children.emplace_back(std::make_unique<CommentInfo>());
313 Return->Children.back()->Kind = "ParagraphComment";
314 Return->Children.back()->Children.emplace_back(
315 std::make_unique<CommentInfo>());
316 Return->Children.back()->Children.back()->Kind = "TextComment";
317 Return->Children.back()->Children.back()->Text = "void";
318
319 I.Description.emplace_back(std::move(Top));
320
321 auto G = getMDGenerator();
322 assert(G);
323 std::string Buffer;
324 llvm::raw_string_ostream Actual(Buffer);
325 auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());
326 assert(!Err);
327 std::string Expected =
328 R"raw(### f
329
330 *void f(int I, int J)*
331
332 *Defined at test.cpp#10*
333
334
335
336 Brief description.
337
338 Extended description that continues onto the next line.
339
340 <ul "class=test">
341
342 <li>
343
344 Testing.</ul>
345
346
347
348 The description continues.
349
350 **I** [out]
351
352 **J**
353
354 **return**void
355
356 )raw";
357
358 EXPECT_EQ(Expected, Actual.str());
359 }
360
361 } // namespace doc
362 } // namespace clang
363