xref: /llvm-project/clang-tools-extra/unittests/clang-doc/YAMLGeneratorTest.cpp (revision edd690b02e16e991393bf7f67631196942369aed)
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 
15 namespace clang {
16 namespace doc {
17 
getYAMLGenerator()18 std::unique_ptr<Generator> getYAMLGenerator() {
19   auto G = doc::findGeneratorByName("yaml");
20   if (!G)
21     return nullptr;
22   return std::move(G.get());
23 }
24 
TEST(YAMLGeneratorTest,emitNamespaceYAML)25 TEST(YAMLGeneratorTest, emitNamespaceYAML) {
26   NamespaceInfo I;
27   I.Name = "Namespace";
28   I.Path = "path/to/A";
29   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
30 
31   I.Children.Namespaces.emplace_back(
32       EmptySID, "ChildNamespace", InfoType::IT_namespace,
33       "path::to::A::Namespace::ChildNamespace", "path/to/A/Namespace");
34   I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
35                                   "path::to::A::Namespace::ChildStruct",
36                                   "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, Actual, ClangDocContext());
48   assert(!Err);
49   std::string Expected =
50       R"raw(---
51 USR:             '0000000000000000000000000000000000000000'
52 Name:            'Namespace'
53 Path:            'path/to/A'
54 Namespace:
55   - Type:            Namespace
56     Name:            'A'
57     QualName:        'A'
58 ChildNamespaces:
59   - Type:            Namespace
60     Name:            'ChildNamespace'
61     QualName:        'path::to::A::Namespace::ChildNamespace'
62     Path:            'path/to/A/Namespace'
63 ChildRecords:
64   - Type:            Record
65     Name:            'ChildStruct'
66     QualName:        'path::to::A::Namespace::ChildStruct'
67     Path:            'path/to/A/Namespace'
68 ChildFunctions:
69   - USR:             '0000000000000000000000000000000000000000'
70     Name:            'OneFunction'
71     ReturnType:      {}
72 ChildEnums:
73   - USR:             '0000000000000000000000000000000000000000'
74     Name:            'OneEnum'
75 ...
76 )raw";
77   EXPECT_EQ(Expected, Actual.str());
78 }
79 
TEST(YAMLGeneratorTest,emitRecordYAML)80 TEST(YAMLGeneratorTest, emitRecordYAML) {
81   RecordInfo I;
82   I.Name = "r";
83   I.Path = "path/to/A";
84   I.IsTypeDef = true;
85   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
86 
87   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
88   I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
89 
90   I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
91 
92   // Member documentation.
93   CommentInfo TopComment;
94   TopComment.Kind = "FullComment";
95   TopComment.Children.emplace_back(std::make_unique<CommentInfo>());
96   CommentInfo *Brief = TopComment.Children.back().get();
97   Brief->Kind = "ParagraphComment";
98   Brief->Children.emplace_back(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(std::move(TopComment));
103 
104   I.TagType = TagTypeKind::Class;
105   I.Bases.emplace_back(EmptySID, "F", "path/to/F", true,
106                        AccessSpecifier::AS_public, 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(TypeInfo("int"), "N",
110                                       AccessSpecifier::AS_private);
111   // F is in the global namespace
112   I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "");
113   I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record,
114                                 "path::to::G::G", "path/to/G");
115 
116   I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
117                                   "path::to::A::r::ChildStruct", "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, Actual, ClangDocContext());
128   assert(!Err);
129   std::string Expected =
130       R"raw(---
131 USR:             '0000000000000000000000000000000000000000'
132 Name:            'r'
133 Path:            'path/to/A'
134 Namespace:
135   - Type:            Namespace
136     Name:            'A'
137     QualName:        'A'
138 DefLocation:
139   LineNumber:      10
140   Filename:        'test.cpp'
141 Location:
142   - LineNumber:      12
143     Filename:        'test.cpp'
144 TagType:         Class
145 IsTypeDef:       true
146 Members:
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'
160 Bases:
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
179 Parents:
180   - Type:            Record
181     Name:            'F'
182 VirtualParents:
183   - Type:            Record
184     Name:            'G'
185     QualName:        'path::to::G::G'
186     Path:            'path/to/G'
187 ChildRecords:
188   - Type:            Record
189     Name:            'ChildStruct'
190     QualName:        'path::to::A::r::ChildStruct'
191     Path:            'path/to/A/r'
192 ChildFunctions:
193   - USR:             '0000000000000000000000000000000000000000'
194     Name:            'OneFunction'
195     ReturnType:      {}
196     Access:          Public
197 ChildEnums:
198   - USR:             '0000000000000000000000000000000000000000'
199     Name:            'OneEnum'
200 ...
201 )raw";
202   EXPECT_EQ(Expected, Actual.str());
203 }
204 
TEST(YAMLGeneratorTest,emitFunctionYAML)205 TEST(YAMLGeneratorTest, emitFunctionYAML) {
206   FunctionInfo I;
207   I.Name = "f";
208   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
209 
210   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
211   I.Loc.emplace_back(12, 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(TypeInfo("int"), "P");
217   I.Params.emplace_back(TypeInfo("double"), "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, Actual, ClangDocContext());
227   assert(!Err);
228   std::string Expected =
229       R"raw(---
230 USR:             '0000000000000000000000000000000000000000'
231 Name:            'f'
232 Namespace:
233   - Type:            Namespace
234     Name:            'A'
235     QualName:        'A'
236 DefLocation:
237   LineNumber:      10
238   Filename:        'test.cpp'
239 Location:
240   - LineNumber:      12
241     Filename:        'test.cpp'
242 IsMethod:        true
243 Parent:
244   Type:            Record
245   Name:            'Parent'
246   QualName:        'Parent'
247 Params:
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'
257 ReturnType:
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 // }
TEST(YAMLGeneratorTest,emitSimpleEnumYAML)270 TEST(YAMLGeneratorTest, emitSimpleEnumYAML) {
271   EnumInfo I;
272   I.Name = "e";
273   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
274 
275   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
276   I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
277 
278   I.Members.emplace_back("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, Actual, ClangDocContext());
286   assert(!Err);
287   std::string Expected =
288       R"raw(---
289 USR:             '0000000000000000000000000000000000000000'
290 Name:            'e'
291 Namespace:
292   - Type:            Namespace
293     Name:            'A'
294     QualName:        'A'
295 DefLocation:
296   LineNumber:      10
297   Filename:        'test.cpp'
298 Location:
299   - LineNumber:      12
300     Filename:        'test.cpp'
301 Members:
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 };
TEST(YAMLGeneratorTest,enumTypedScopedEnumYAML)311 TEST(YAMLGeneratorTest, enumTypedScopedEnumYAML) {
312   EnumInfo I;
313   I.Name = "e";
314 
315   I.Members.emplace_back("X", "-9876", "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, Actual, ClangDocContext());
324   assert(!Err);
325   std::string Expected =
326       R"raw(---
327 USR:             '0000000000000000000000000000000000000000'
328 Name:            'e'
329 Scoped:          true
330 BaseType:
331   Type:
332     Name:            'short'
333     QualName:        'short'
334 Members:
335   - Name:            'X'
336     Value:           '-9876'
337     Expr:            'FOO_BAR + 2'
338 ...
339 )raw";
340   EXPECT_EQ(Expected, Actual.str());
341 }
342 
TEST(YAMLGeneratorTest,enumTypedefYAML)343 TEST(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, Actual, ClangDocContext());
354   assert(!Err);
355   std::string Expected =
356       R"raw(---
357 USR:             '0000000000000000000000000000000000000000'
358 Name:            'MyUsing'
359 Underlying:
360   Name:            'int'
361   QualName:        'int'
362 IsUsing:         true
363 ...
364 )raw";
365   EXPECT_EQ(Expected, Actual.str());
366 }
367 
TEST(YAMLGeneratorTest,emitCommentYAML)368 TEST(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(TypeInfo("int"), "I");
374   I.Params.emplace_back(TypeInfo("int"), "J");
375   I.Access = AccessSpecifier::AS_none;
376 
377   CommentInfo Top;
378   Top.Kind = "FullComment";
379 
380   Top.Children.emplace_back(std::make_unique<CommentInfo>());
381   CommentInfo *BlankLine = Top.Children.back().get();
382   BlankLine->Kind = "ParagraphComment";
383   BlankLine->Children.emplace_back(std::make_unique<CommentInfo>());
384   BlankLine->Children.back()->Kind = "TextComment";
385 
386   Top.Children.emplace_back(std::make_unique<CommentInfo>());
387   CommentInfo *Brief = Top.Children.back().get();
388   Brief->Kind = "ParagraphComment";
389   Brief->Children.emplace_back(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(std::make_unique<CommentInfo>());
395   CommentInfo *Extended = Top.Children.back().get();
396   Extended->Kind = "ParagraphComment";
397   Extended->Children.emplace_back(std::make_unique<CommentInfo>());
398   Extended->Children.back()->Kind = "TextComment";
399   Extended->Children.back()->Text = " Extended description that";
400   Extended->Children.emplace_back(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(std::make_unique<CommentInfo>());
405   CommentInfo *HTML = Top.Children.back().get();
406   HTML->Kind = "ParagraphComment";
407   HTML->Children.emplace_back(std::make_unique<CommentInfo>());
408   HTML->Children.back()->Kind = "TextComment";
409   HTML->Children.emplace_back(std::make_unique<CommentInfo>());
410   HTML->Children.back()->Kind = "HTMLStartTagComment";
411   HTML->Children.back()->Name = "ul";
412   HTML->Children.back()->AttrKeys.emplace_back("class");
413   HTML->Children.back()->AttrValues.emplace_back("test");
414   HTML->Children.emplace_back(std::make_unique<CommentInfo>());
415   HTML->Children.back()->Kind = "HTMLStartTagComment";
416   HTML->Children.back()->Name = "li";
417   HTML->Children.emplace_back(std::make_unique<CommentInfo>());
418   HTML->Children.back()->Kind = "TextComment";
419   HTML->Children.back()->Text = " Testing.";
420   HTML->Children.emplace_back(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(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(std::make_unique<CommentInfo>());
431   Verbatim->Children.back()->Kind = "VerbatimBlockLineComment";
432   Verbatim->Children.back()->Text = " The description continues.";
433 
434   Top.Children.emplace_back(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(std::make_unique<CommentInfo>());
441   ParamOut->Children.back()->Kind = "ParagraphComment";
442   ParamOut->Children.back()->Children.emplace_back(
443       std::make_unique<CommentInfo>());
444   ParamOut->Children.back()->Children.back()->Kind = "TextComment";
445   ParamOut->Children.back()->Children.emplace_back(
446       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(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(std::make_unique<CommentInfo>());
456   ParamIn->Children.back()->Kind = "ParagraphComment";
457   ParamIn->Children.back()->Children.emplace_back(
458       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       std::make_unique<CommentInfo>());
463   ParamIn->Children.back()->Children.back()->Kind = "TextComment";
464 
465   Top.Children.emplace_back(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(std::make_unique<CommentInfo>());
471   Return->Children.back()->Kind = "ParagraphComment";
472   Return->Children.back()->Children.emplace_back(
473       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(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, Actual, ClangDocContext());
484   assert(!Err);
485   std::string Expected =
486       R"raw(---
487 USR:             '0000000000000000000000000000000000000000'
488 Name:            'f'
489 Description:
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'
555 DefLocation:
556   LineNumber:      10
557   Filename:        'test.cpp'
558 Params:
559   - Type:
560       Name:            'int'
561       QualName:        'int'
562     Name:            'I'
563   - Type:
564       Name:            'int'
565       QualName:        'int'
566     Name:            'J'
567 ReturnType:
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