1//===-- clang-doc/YAMLGeneratorTest.cpp
2//------------------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#include "ClangDocTest.h"
11#include "Generators.h"
12#include "Representation.h"
13#include "gtest/gtest.h"
14
15namespace clang {
16namespace doc {
17
18std::unique_ptr<Generator> getYAMLGenerator() {
19 auto G = doc::findGeneratorByName(Format: "yaml");
20 if (!G)
21 return nullptr;
22 return std::move(G.get());
23}
24
25TEST(YAMLGeneratorTest, emitNamespaceYAML) {
26 NamespaceInfo I;
27 I.Name = "Namespace";
28 I.Path = "path/to/A";
29 I.Namespace.emplace_back(Args: EmptySID, Args: "A", Args: InfoType::IT_namespace);
30
31 I.Children.Namespaces.emplace_back(
32 args: EmptySID, args: "ChildNamespace", args: InfoType::IT_namespace,
33 args: "path::to::A::Namespace::ChildNamespace", args: "path/to/A/Namespace");
34 I.Children.Records.emplace_back(args: EmptySID, args: "ChildStruct", args: InfoType::IT_record,
35 args: "path::to::A::Namespace::ChildStruct",
36 args: "path/to/A/Namespace");
37 I.Children.Functions.emplace_back();
38 I.Children.Functions.back().Name = "OneFunction";
39 I.Children.Functions.back().Access = AccessSpecifier::AS_none;
40 I.Children.Enums.emplace_back();
41 I.Children.Enums.back().Name = "OneEnum";
42
43 auto G = getYAMLGenerator();
44 assert(G);
45 std::string Buffer;
46 llvm::raw_string_ostream Actual(Buffer);
47 auto Err = G->generateDocForInfo(I: &I, OS&: Actual, CDCtx: ClangDocContext());
48 assert(!Err);
49 std::string Expected =
50 R"raw(---
51USR: '0000000000000000000000000000000000000000'
52Name: 'Namespace'
53Path: 'path/to/A'
54Namespace:
55 - Type: Namespace
56 Name: 'A'
57 QualName: 'A'
58ChildNamespaces:
59 - Type: Namespace
60 Name: 'ChildNamespace'
61 QualName: 'path::to::A::Namespace::ChildNamespace'
62 Path: 'path/to/A/Namespace'
63ChildRecords:
64 - Type: Record
65 Name: 'ChildStruct'
66 QualName: 'path::to::A::Namespace::ChildStruct'
67 Path: 'path/to/A/Namespace'
68ChildFunctions:
69 - USR: '0000000000000000000000000000000000000000'
70 Name: 'OneFunction'
71 ReturnType: {}
72ChildEnums:
73 - USR: '0000000000000000000000000000000000000000'
74 Name: 'OneEnum'
75...
76)raw";
77 EXPECT_EQ(Expected, Actual.str());
78}
79
80TEST(YAMLGeneratorTest, emitRecordYAML) {
81 RecordInfo I;
82 I.Name = "r";
83 I.Path = "path/to/A";
84 I.IsTypeDef = true;
85 I.Namespace.emplace_back(Args: EmptySID, Args: "A", Args: InfoType::IT_namespace);
86
87 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
88 I.Loc.emplace_back(Args: 12, Args: llvm::SmallString<16>{"test.cpp"});
89
90 I.Members.emplace_back(Args: TypeInfo("int"), Args: "X", Args: AccessSpecifier::AS_private);
91
92 // Member documentation.
93 CommentInfo TopComment;
94 TopComment.Kind = "FullComment";
95 TopComment.Children.emplace_back(args: std::make_unique<CommentInfo>());
96 CommentInfo *Brief = TopComment.Children.back().get();
97 Brief->Kind = "ParagraphComment";
98 Brief->Children.emplace_back(args: std::make_unique<CommentInfo>());
99 Brief->Children.back()->Kind = "TextComment";
100 Brief->Children.back()->Name = "ParagraphComment";
101 Brief->Children.back()->Text = "Value of the thing.";
102 I.Members.back().Description.push_back(x: std::move(TopComment));
103
104 I.TagType = TagTypeKind::Class;
105 I.Bases.emplace_back(args: EmptySID, args: "F", args: "path/to/F", args: true,
106 args: AccessSpecifier::AS_public, args: true);
107 I.Bases.back().Children.Functions.emplace_back();
108 I.Bases.back().Children.Functions.back().Name = "InheritedFunctionOne";
109 I.Bases.back().Members.emplace_back(Args: TypeInfo("int"), Args: "N",
110 Args: AccessSpecifier::AS_private);
111 // F is in the global namespace
112 I.Parents.emplace_back(Args: EmptySID, Args: "F", Args: InfoType::IT_record, Args: "");
113 I.VirtualParents.emplace_back(Args: EmptySID, Args: "G", Args: InfoType::IT_record,
114 Args: "path::to::G::G", Args: "path/to/G");
115
116 I.Children.Records.emplace_back(args: EmptySID, args: "ChildStruct", args: InfoType::IT_record,
117 args: "path::to::A::r::ChildStruct", args: "path/to/A/r");
118 I.Children.Functions.emplace_back();
119 I.Children.Functions.back().Name = "OneFunction";
120 I.Children.Enums.emplace_back();
121 I.Children.Enums.back().Name = "OneEnum";
122
123 auto G = getYAMLGenerator();
124 assert(G);
125 std::string Buffer;
126 llvm::raw_string_ostream Actual(Buffer);
127 auto Err = G->generateDocForInfo(I: &I, OS&: Actual, CDCtx: ClangDocContext());
128 assert(!Err);
129 std::string Expected =
130 R"raw(---
131USR: '0000000000000000000000000000000000000000'
132Name: 'r'
133Path: 'path/to/A'
134Namespace:
135 - Type: Namespace
136 Name: 'A'
137 QualName: 'A'
138DefLocation:
139 LineNumber: 10
140 Filename: 'test.cpp'
141Location:
142 - LineNumber: 12
143 Filename: 'test.cpp'
144TagType: Class
145IsTypeDef: true
146Members:
147 - Type:
148 Name: 'int'
149 QualName: 'int'
150 Name: 'X'
151 Access: Private
152 Description:
153 - Kind: 'FullComment'
154 Children:
155 - Kind: 'ParagraphComment'
156 Children:
157 - Kind: 'TextComment'
158 Text: 'Value of the thing.'
159 Name: 'ParagraphComment'
160Bases:
161 - USR: '0000000000000000000000000000000000000000'
162 Name: 'F'
163 Path: 'path/to/F'
164 TagType: Struct
165 Members:
166 - Type:
167 Name: 'int'
168 QualName: 'int'
169 Name: 'N'
170 Access: Private
171 ChildFunctions:
172 - USR: '0000000000000000000000000000000000000000'
173 Name: 'InheritedFunctionOne'
174 ReturnType: {}
175 Access: Public
176 IsVirtual: true
177 Access: Public
178 IsParent: true
179Parents:
180 - Type: Record
181 Name: 'F'
182VirtualParents:
183 - Type: Record
184 Name: 'G'
185 QualName: 'path::to::G::G'
186 Path: 'path/to/G'
187ChildRecords:
188 - Type: Record
189 Name: 'ChildStruct'
190 QualName: 'path::to::A::r::ChildStruct'
191 Path: 'path/to/A/r'
192ChildFunctions:
193 - USR: '0000000000000000000000000000000000000000'
194 Name: 'OneFunction'
195 ReturnType: {}
196 Access: Public
197ChildEnums:
198 - USR: '0000000000000000000000000000000000000000'
199 Name: 'OneEnum'
200...
201)raw";
202 EXPECT_EQ(Expected, Actual.str());
203}
204
205TEST(YAMLGeneratorTest, emitFunctionYAML) {
206 FunctionInfo I;
207 I.Name = "f";
208 I.Namespace.emplace_back(Args: EmptySID, Args: "A", Args: InfoType::IT_namespace);
209
210 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
211 I.Loc.emplace_back(Args: 12, Args: llvm::SmallString<16>{"test.cpp"});
212
213 I.Access = AccessSpecifier::AS_none;
214
215 I.ReturnType = TypeInfo(Reference(EmptySID, "void", InfoType::IT_default));
216 I.Params.emplace_back(Args: TypeInfo("int"), Args: "P");
217 I.Params.emplace_back(Args: TypeInfo("double"), Args: "D");
218 I.Params.back().DefaultValue = "2.0 * M_PI";
219 I.IsMethod = true;
220 I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
221
222 auto G = getYAMLGenerator();
223 assert(G);
224 std::string Buffer;
225 llvm::raw_string_ostream Actual(Buffer);
226 auto Err = G->generateDocForInfo(I: &I, OS&: Actual, CDCtx: ClangDocContext());
227 assert(!Err);
228 std::string Expected =
229 R"raw(---
230USR: '0000000000000000000000000000000000000000'
231Name: 'f'
232Namespace:
233 - Type: Namespace
234 Name: 'A'
235 QualName: 'A'
236DefLocation:
237 LineNumber: 10
238 Filename: 'test.cpp'
239Location:
240 - LineNumber: 12
241 Filename: 'test.cpp'
242IsMethod: true
243Parent:
244 Type: Record
245 Name: 'Parent'
246 QualName: 'Parent'
247Params:
248 - Type:
249 Name: 'int'
250 QualName: 'int'
251 Name: 'P'
252 - Type:
253 Name: 'double'
254 QualName: 'double'
255 Name: 'D'
256 DefaultValue: '2.0 * M_PI'
257ReturnType:
258 Type:
259 Name: 'void'
260 QualName: 'void'
261...
262)raw";
263 EXPECT_EQ(Expected, Actual.str());
264}
265
266// Tests the equivalent of:
267// namespace A {
268// enum e { X };
269// }
270TEST(YAMLGeneratorTest, emitSimpleEnumYAML) {
271 EnumInfo I;
272 I.Name = "e";
273 I.Namespace.emplace_back(Args: EmptySID, Args: "A", Args: InfoType::IT_namespace);
274
275 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
276 I.Loc.emplace_back(Args: 12, Args: llvm::SmallString<16>{"test.cpp"});
277
278 I.Members.emplace_back(Args: "X");
279 I.Scoped = false;
280
281 auto G = getYAMLGenerator();
282 assert(G);
283 std::string Buffer;
284 llvm::raw_string_ostream Actual(Buffer);
285 auto Err = G->generateDocForInfo(I: &I, OS&: Actual, CDCtx: ClangDocContext());
286 assert(!Err);
287 std::string Expected =
288 R"raw(---
289USR: '0000000000000000000000000000000000000000'
290Name: 'e'
291Namespace:
292 - Type: Namespace
293 Name: 'A'
294 QualName: 'A'
295DefLocation:
296 LineNumber: 10
297 Filename: 'test.cpp'
298Location:
299 - LineNumber: 12
300 Filename: 'test.cpp'
301Members:
302 - Name: 'X'
303 Value: '0'
304...
305)raw";
306 EXPECT_EQ(Expected, Actual.str());
307}
308
309// Tests the equivalent of:
310// enum class e : short { X = FOO_BAR + 2 };
311TEST(YAMLGeneratorTest, enumTypedScopedEnumYAML) {
312 EnumInfo I;
313 I.Name = "e";
314
315 I.Members.emplace_back(Args: "X", Args: "-9876", Args: "FOO_BAR + 2");
316 I.Scoped = true;
317 I.BaseType = TypeInfo("short");
318
319 auto G = getYAMLGenerator();
320 assert(G);
321 std::string Buffer;
322 llvm::raw_string_ostream Actual(Buffer);
323 auto Err = G->generateDocForInfo(I: &I, OS&: Actual, CDCtx: ClangDocContext());
324 assert(!Err);
325 std::string Expected =
326 R"raw(---
327USR: '0000000000000000000000000000000000000000'
328Name: 'e'
329Scoped: true
330BaseType:
331 Type:
332 Name: 'short'
333 QualName: 'short'
334Members:
335 - Name: 'X'
336 Value: '-9876'
337 Expr: 'FOO_BAR + 2'
338...
339)raw";
340 EXPECT_EQ(Expected, Actual.str());
341}
342
343TEST(YAMLGeneratorTest, enumTypedefYAML) {
344 TypedefInfo I;
345 I.Name = "MyUsing";
346 I.Underlying = TypeInfo("int");
347 I.IsUsing = true;
348
349 auto G = getYAMLGenerator();
350 assert(G);
351 std::string Buffer;
352 llvm::raw_string_ostream Actual(Buffer);
353 auto Err = G->generateDocForInfo(I: &I, OS&: Actual, CDCtx: ClangDocContext());
354 assert(!Err);
355 std::string Expected =
356 R"raw(---
357USR: '0000000000000000000000000000000000000000'
358Name: 'MyUsing'
359Underlying:
360 Name: 'int'
361 QualName: 'int'
362IsUsing: true
363...
364)raw";
365 EXPECT_EQ(Expected, Actual.str());
366}
367
368TEST(YAMLGeneratorTest, emitCommentYAML) {
369 FunctionInfo I;
370 I.Name = "f";
371 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
372 I.ReturnType = TypeInfo("void");
373 I.Params.emplace_back(Args: TypeInfo("int"), Args: "I");
374 I.Params.emplace_back(Args: TypeInfo("int"), Args: "J");
375 I.Access = AccessSpecifier::AS_none;
376
377 CommentInfo Top;
378 Top.Kind = "FullComment";
379
380 Top.Children.emplace_back(args: std::make_unique<CommentInfo>());
381 CommentInfo *BlankLine = Top.Children.back().get();
382 BlankLine->Kind = "ParagraphComment";
383 BlankLine->Children.emplace_back(args: std::make_unique<CommentInfo>());
384 BlankLine->Children.back()->Kind = "TextComment";
385
386 Top.Children.emplace_back(args: std::make_unique<CommentInfo>());
387 CommentInfo *Brief = Top.Children.back().get();
388 Brief->Kind = "ParagraphComment";
389 Brief->Children.emplace_back(args: std::make_unique<CommentInfo>());
390 Brief->Children.back()->Kind = "TextComment";
391 Brief->Children.back()->Name = "ParagraphComment";
392 Brief->Children.back()->Text = " Brief description.";
393
394 Top.Children.emplace_back(args: std::make_unique<CommentInfo>());
395 CommentInfo *Extended = Top.Children.back().get();
396 Extended->Kind = "ParagraphComment";
397 Extended->Children.emplace_back(args: std::make_unique<CommentInfo>());
398 Extended->Children.back()->Kind = "TextComment";
399 Extended->Children.back()->Text = " Extended description that";
400 Extended->Children.emplace_back(args: std::make_unique<CommentInfo>());
401 Extended->Children.back()->Kind = "TextComment";
402 Extended->Children.back()->Text = " continues onto the next line.";
403
404 Top.Children.emplace_back(args: std::make_unique<CommentInfo>());
405 CommentInfo *HTML = Top.Children.back().get();
406 HTML->Kind = "ParagraphComment";
407 HTML->Children.emplace_back(args: std::make_unique<CommentInfo>());
408 HTML->Children.back()->Kind = "TextComment";
409 HTML->Children.emplace_back(args: std::make_unique<CommentInfo>());
410 HTML->Children.back()->Kind = "HTMLStartTagComment";
411 HTML->Children.back()->Name = "ul";
412 HTML->Children.back()->AttrKeys.emplace_back(Args: "class");
413 HTML->Children.back()->AttrValues.emplace_back(Args: "test");
414 HTML->Children.emplace_back(args: std::make_unique<CommentInfo>());
415 HTML->Children.back()->Kind = "HTMLStartTagComment";
416 HTML->Children.back()->Name = "li";
417 HTML->Children.emplace_back(args: std::make_unique<CommentInfo>());
418 HTML->Children.back()->Kind = "TextComment";
419 HTML->Children.back()->Text = " Testing.";
420 HTML->Children.emplace_back(args: std::make_unique<CommentInfo>());
421 HTML->Children.back()->Kind = "HTMLEndTagComment";
422 HTML->Children.back()->Name = "ul";
423 HTML->Children.back()->SelfClosing = true;
424
425 Top.Children.emplace_back(args: std::make_unique<CommentInfo>());
426 CommentInfo *Verbatim = Top.Children.back().get();
427 Verbatim->Kind = "VerbatimBlockComment";
428 Verbatim->Name = "verbatim";
429 Verbatim->CloseName = "endverbatim";
430 Verbatim->Children.emplace_back(args: std::make_unique<CommentInfo>());
431 Verbatim->Children.back()->Kind = "VerbatimBlockLineComment";
432 Verbatim->Children.back()->Text = " The description continues.";
433
434 Top.Children.emplace_back(args: std::make_unique<CommentInfo>());
435 CommentInfo *ParamOut = Top.Children.back().get();
436 ParamOut->Kind = "ParamCommandComment";
437 ParamOut->Direction = "[out]";
438 ParamOut->ParamName = "I";
439 ParamOut->Explicit = true;
440 ParamOut->Children.emplace_back(args: std::make_unique<CommentInfo>());
441 ParamOut->Children.back()->Kind = "ParagraphComment";
442 ParamOut->Children.back()->Children.emplace_back(
443 args: std::make_unique<CommentInfo>());
444 ParamOut->Children.back()->Children.back()->Kind = "TextComment";
445 ParamOut->Children.back()->Children.emplace_back(
446 args: std::make_unique<CommentInfo>());
447 ParamOut->Children.back()->Children.back()->Kind = "TextComment";
448 ParamOut->Children.back()->Children.back()->Text = " is a parameter.";
449
450 Top.Children.emplace_back(args: std::make_unique<CommentInfo>());
451 CommentInfo *ParamIn = Top.Children.back().get();
452 ParamIn->Kind = "ParamCommandComment";
453 ParamIn->Direction = "[in]";
454 ParamIn->ParamName = "J";
455 ParamIn->Children.emplace_back(args: std::make_unique<CommentInfo>());
456 ParamIn->Children.back()->Kind = "ParagraphComment";
457 ParamIn->Children.back()->Children.emplace_back(
458 args: std::make_unique<CommentInfo>());
459 ParamIn->Children.back()->Children.back()->Kind = "TextComment";
460 ParamIn->Children.back()->Children.back()->Text = " is a parameter.";
461 ParamIn->Children.back()->Children.emplace_back(
462 args: std::make_unique<CommentInfo>());
463 ParamIn->Children.back()->Children.back()->Kind = "TextComment";
464
465 Top.Children.emplace_back(args: std::make_unique<CommentInfo>());
466 CommentInfo *Return = Top.Children.back().get();
467 Return->Kind = "BlockCommandComment";
468 Return->Name = "return";
469 Return->Explicit = true;
470 Return->Children.emplace_back(args: std::make_unique<CommentInfo>());
471 Return->Children.back()->Kind = "ParagraphComment";
472 Return->Children.back()->Children.emplace_back(
473 args: std::make_unique<CommentInfo>());
474 Return->Children.back()->Children.back()->Kind = "TextComment";
475 Return->Children.back()->Children.back()->Text = "void";
476
477 I.Description.emplace_back(args: std::move(Top));
478
479 auto G = getYAMLGenerator();
480 assert(G);
481 std::string Buffer;
482 llvm::raw_string_ostream Actual(Buffer);
483 auto Err = G->generateDocForInfo(I: &I, OS&: Actual, CDCtx: ClangDocContext());
484 assert(!Err);
485 std::string Expected =
486 R"raw(---
487USR: '0000000000000000000000000000000000000000'
488Name: 'f'
489Description:
490 - Kind: 'FullComment'
491 Children:
492 - Kind: 'ParagraphComment'
493 Children:
494 - Kind: 'TextComment'
495 - Kind: 'ParagraphComment'
496 Children:
497 - Kind: 'TextComment'
498 Text: ' Brief description.'
499 Name: 'ParagraphComment'
500 - Kind: 'ParagraphComment'
501 Children:
502 - Kind: 'TextComment'
503 Text: ' Extended description that'
504 - Kind: 'TextComment'
505 Text: ' continues onto the next line.'
506 - Kind: 'ParagraphComment'
507 Children:
508 - Kind: 'TextComment'
509 - Kind: 'HTMLStartTagComment'
510 Name: 'ul'
511 AttrKeys:
512 - 'class'
513 AttrValues:
514 - 'test'
515 - Kind: 'HTMLStartTagComment'
516 Name: 'li'
517 - Kind: 'TextComment'
518 Text: ' Testing.'
519 - Kind: 'HTMLEndTagComment'
520 Name: 'ul'
521 SelfClosing: true
522 - Kind: 'VerbatimBlockComment'
523 Name: 'verbatim'
524 CloseName: 'endverbatim'
525 Children:
526 - Kind: 'VerbatimBlockLineComment'
527 Text: ' The description continues.'
528 - Kind: 'ParamCommandComment'
529 Direction: '[out]'
530 ParamName: 'I'
531 Explicit: true
532 Children:
533 - Kind: 'ParagraphComment'
534 Children:
535 - Kind: 'TextComment'
536 - Kind: 'TextComment'
537 Text: ' is a parameter.'
538 - Kind: 'ParamCommandComment'
539 Direction: '[in]'
540 ParamName: 'J'
541 Children:
542 - Kind: 'ParagraphComment'
543 Children:
544 - Kind: 'TextComment'
545 Text: ' is a parameter.'
546 - Kind: 'TextComment'
547 - Kind: 'BlockCommandComment'
548 Name: 'return'
549 Explicit: true
550 Children:
551 - Kind: 'ParagraphComment'
552 Children:
553 - Kind: 'TextComment'
554 Text: 'void'
555DefLocation:
556 LineNumber: 10
557 Filename: 'test.cpp'
558Params:
559 - Type:
560 Name: 'int'
561 QualName: 'int'
562 Name: 'I'
563 - Type:
564 Name: 'int'
565 QualName: 'int'
566 Name: 'J'
567ReturnType:
568 Type:
569 Name: 'void'
570 QualName: 'void'
571...
572)raw";
573
574 EXPECT_EQ(Expected, Actual.str());
575}
576
577} // namespace doc
578} // namespace clang
579

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