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
14namespace clang {
15namespace doc {
16
17std::unique_ptr<Generator> getMDGenerator() {
18 auto G = doc::findGeneratorByName(Format: "md");
19 if (!G)
20 return nullptr;
21 return std::move(G.get());
22}
23
24TEST(MDGeneratorTest, emitNamespaceMD) {
25 NamespaceInfo I;
26 I.Name = "Namespace";
27 I.Namespace.emplace_back(Args: EmptySID, Args: "A", Args: InfoType::IT_namespace);
28
29 I.Children.Namespaces.emplace_back(args: EmptySID, args: "ChildNamespace",
30 args: InfoType::IT_namespace);
31 I.Children.Records.emplace_back(args: EmptySID, args: "ChildStruct", args: InfoType::IT_record);
32 I.Children.Functions.emplace_back();
33 I.Children.Functions.back().Name = "OneFunction";
34 I.Children.Functions.back().Access = AccessSpecifier::AS_none;
35 I.Children.Enums.emplace_back();
36 I.Children.Enums.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: &I, OS&: Actual, CDCtx: 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
80TEST(MDGeneratorTest, emitRecordMD) {
81 RecordInfo I;
82 I.Name = "r";
83 I.Namespace.emplace_back(Args: EmptySID, Args: "A", Args: InfoType::IT_namespace);
84
85 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
86 I.Loc.emplace_back(Args: 12, Args: llvm::SmallString<16>{"test.cpp"});
87
88 I.Members.emplace_back(Args: TypeInfo("int"), Args: "X", Args: AccessSpecifier::AS_private);
89 I.TagType = TagTypeKind::Class;
90 I.Parents.emplace_back(Args: EmptySID, Args: "F", Args: InfoType::IT_record);
91 I.VirtualParents.emplace_back(Args: EmptySID, Args: "G", Args: InfoType::IT_record);
92
93 I.Children.Records.emplace_back(args: EmptySID, args: "ChildStruct", args: InfoType::IT_record);
94 I.Children.Functions.emplace_back();
95 I.Children.Functions.back().Name = "OneFunction";
96 I.Children.Enums.emplace_back();
97 I.Children.Enums.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: &I, OS&: Actual, CDCtx: ClangDocContext());
104 assert(!Err);
105 std::string Expected = R"raw(# class r
106
107*Defined at test.cpp#10*
108
109Inherits from F, G
110
111
112
113## Members
114
115private int X
116
117
118
119## Records
120
121ChildStruct
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
147TEST(MDGeneratorTest, emitFunctionMD) {
148 FunctionInfo I;
149 I.Name = "f";
150 I.Namespace.emplace_back(Args: EmptySID, Args: "A", Args: InfoType::IT_namespace);
151
152 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
153 I.Loc.emplace_back(Args: 12, Args: llvm::SmallString<16>{"test.cpp"});
154
155 I.Access = AccessSpecifier::AS_none;
156
157 I.ReturnType = TypeInfo("void");
158 I.Params.emplace_back(Args: TypeInfo("int"), Args: "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: &I, OS&: Actual, CDCtx: 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
179TEST(MDGeneratorTest, emitEnumMD) {
180 EnumInfo I;
181 I.Name = "e";
182 I.Namespace.emplace_back(Args: EmptySID, Args: "A", Args: InfoType::IT_namespace);
183
184 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
185 I.Loc.emplace_back(Args: 12, Args: llvm::SmallString<16>{"test.cpp"});
186
187 I.Members.emplace_back(Args: "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: &I, OS&: Actual, CDCtx: 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
210TEST(MDGeneratorTest, emitCommentMD) {
211 FunctionInfo I;
212 I.Name = "f";
213 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
214 I.ReturnType = TypeInfo("void");
215 I.Params.emplace_back(Args: TypeInfo("int"), Args: "I");
216 I.Params.emplace_back(Args: TypeInfo("int"), Args: "J");
217 I.Access = AccessSpecifier::AS_none;
218
219 CommentInfo Top;
220 Top.Kind = "FullComment";
221
222 Top.Children.emplace_back(args: std::make_unique<CommentInfo>());
223 CommentInfo *BlankLine = Top.Children.back().get();
224 BlankLine->Kind = "ParagraphComment";
225 BlankLine->Children.emplace_back(args: std::make_unique<CommentInfo>());
226 BlankLine->Children.back()->Kind = "TextComment";
227
228 Top.Children.emplace_back(args: std::make_unique<CommentInfo>());
229 CommentInfo *Brief = Top.Children.back().get();
230 Brief->Kind = "ParagraphComment";
231 Brief->Children.emplace_back(args: 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(args: std::make_unique<CommentInfo>());
237 CommentInfo *Extended = Top.Children.back().get();
238 Extended->Kind = "ParagraphComment";
239 Extended->Children.emplace_back(args: std::make_unique<CommentInfo>());
240 Extended->Children.back()->Kind = "TextComment";
241 Extended->Children.back()->Text = " Extended description that";
242 Extended->Children.emplace_back(args: 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(args: std::make_unique<CommentInfo>());
247 CommentInfo *HTML = Top.Children.back().get();
248 HTML->Kind = "ParagraphComment";
249 HTML->Children.emplace_back(args: std::make_unique<CommentInfo>());
250 HTML->Children.back()->Kind = "TextComment";
251 HTML->Children.emplace_back(args: std::make_unique<CommentInfo>());
252 HTML->Children.back()->Kind = "HTMLStartTagComment";
253 HTML->Children.back()->Name = "ul";
254 HTML->Children.back()->AttrKeys.emplace_back(Args: "class");
255 HTML->Children.back()->AttrValues.emplace_back(Args: "test");
256 HTML->Children.emplace_back(args: std::make_unique<CommentInfo>());
257 HTML->Children.back()->Kind = "HTMLStartTagComment";
258 HTML->Children.back()->Name = "li";
259 HTML->Children.emplace_back(args: std::make_unique<CommentInfo>());
260 HTML->Children.back()->Kind = "TextComment";
261 HTML->Children.back()->Text = " Testing.";
262 HTML->Children.emplace_back(args: 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(args: 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(args: std::make_unique<CommentInfo>());
273 Verbatim->Children.back()->Kind = "VerbatimBlockLineComment";
274 Verbatim->Children.back()->Text = " The description continues.";
275
276 Top.Children.emplace_back(args: 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(args: std::make_unique<CommentInfo>());
283 ParamOut->Children.back()->Kind = "ParagraphComment";
284 ParamOut->Children.back()->Children.emplace_back(
285 args: std::make_unique<CommentInfo>());
286 ParamOut->Children.back()->Children.back()->Kind = "TextComment";
287 ParamOut->Children.back()->Children.emplace_back(
288 args: 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(args: 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(args: std::make_unique<CommentInfo>());
298 ParamIn->Children.back()->Kind = "ParagraphComment";
299 ParamIn->Children.back()->Children.emplace_back(
300 args: 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 args: std::make_unique<CommentInfo>());
305 ParamIn->Children.back()->Children.back()->Kind = "TextComment";
306
307 Top.Children.emplace_back(args: 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(args: std::make_unique<CommentInfo>());
313 Return->Children.back()->Kind = "ParagraphComment";
314 Return->Children.back()->Children.emplace_back(
315 args: 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(args: 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: &I, OS&: Actual, CDCtx: 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] is a parameter.
351
352**J** is a parameter.
353
354**return**void
355
356)raw";
357
358 EXPECT_EQ(Expected, Actual.str());
359}
360
361} // namespace doc
362} // namespace clang
363

source code of clang-tools-extra/unittests/clang-doc/MDGeneratorTest.cpp