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.ChildNamespaces.emplace_back(EmptySID, "ChildNamespace",
32                                  InfoType::IT_namespace, "path/to/A/Namespace");
33   I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
34                               "path/to/A/Namespace");
35   I.ChildFunctions.emplace_back();
36   I.ChildFunctions.back().Name = "OneFunction";
37   I.ChildFunctions.back().Access = AccessSpecifier::AS_none;
38   I.ChildEnums.emplace_back();
39   I.ChildEnums.back().Name = "OneEnum";
40 
41   auto G = getYAMLGenerator();
42   assert(G);
43   std::string Buffer;
44   llvm::raw_string_ostream Actual(Buffer);
45   auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());
46   assert(!Err);
47   std::string Expected =
48       R"raw(---
49 USR:             '0000000000000000000000000000000000000000'
50 Name:            'Namespace'
51 Path:            'path/to/A'
52 Namespace:
53   - Type:            Namespace
54     Name:            'A'
55 ChildNamespaces:
56   - Type:            Namespace
57     Name:            'ChildNamespace'
58     Path:            'path/to/A/Namespace'
59 ChildRecords:
60   - Type:            Record
61     Name:            'ChildStruct'
62     Path:            'path/to/A/Namespace'
63 ChildFunctions:
64   - USR:             '0000000000000000000000000000000000000000'
65     Name:            'OneFunction'
66     ReturnType:      {}
67 ChildEnums:
68   - USR:             '0000000000000000000000000000000000000000'
69     Name:            'OneEnum'
70 ...
71 )raw";
72   EXPECT_EQ(Expected, Actual.str());
73 }
74 
TEST(YAMLGeneratorTest,emitRecordYAML)75 TEST(YAMLGeneratorTest, emitRecordYAML) {
76   RecordInfo I;
77   I.Name = "r";
78   I.Path = "path/to/A";
79   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
80 
81   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
82   I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
83 
84   I.Members.emplace_back("int", "path/to/int", "X",
85                          AccessSpecifier::AS_private);
86   I.TagType = TagTypeKind::TTK_Class;
87   I.Bases.emplace_back(EmptySID, "F", "path/to/F", true,
88                        AccessSpecifier::AS_public, true);
89   I.Bases.back().ChildFunctions.emplace_back();
90   I.Bases.back().ChildFunctions.back().Name = "InheritedFunctionOne";
91   I.Bases.back().Members.emplace_back("int", "path/to/int", "N",
92                                       AccessSpecifier::AS_private);
93   // F is in the global namespace
94   I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "");
95   I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record,
96                                 "path/to/G");
97 
98   I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
99                               "path/to/A/r");
100   I.ChildFunctions.emplace_back();
101   I.ChildFunctions.back().Name = "OneFunction";
102   I.ChildEnums.emplace_back();
103   I.ChildEnums.back().Name = "OneEnum";
104 
105   auto G = getYAMLGenerator();
106   assert(G);
107   std::string Buffer;
108   llvm::raw_string_ostream Actual(Buffer);
109   auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());
110   assert(!Err);
111   std::string Expected =
112       R"raw(---
113 USR:             '0000000000000000000000000000000000000000'
114 Name:            'r'
115 Path:            'path/to/A'
116 Namespace:
117   - Type:            Namespace
118     Name:            'A'
119 DefLocation:
120   LineNumber:      10
121   Filename:        'test.cpp'
122 Location:
123   - LineNumber:      12
124     Filename:        'test.cpp'
125 TagType:         Class
126 Members:
127   - Type:
128       Name:            'int'
129       Path:            'path/to/int'
130     Name:            'X'
131     Access:          Private
132 Bases:
133   - USR:             '0000000000000000000000000000000000000000'
134     Name:            'F'
135     Path:            'path/to/F'
136     Members:
137       - Type:
138           Name:            'int'
139           Path:            'path/to/int'
140         Name:            'N'
141         Access:          Private
142     ChildFunctions:
143       - USR:             '0000000000000000000000000000000000000000'
144         Name:            'InheritedFunctionOne'
145         ReturnType:      {}
146         Access:          Public
147     IsVirtual:       true
148     Access:          Public
149     IsParent:        true
150 Parents:
151   - Type:            Record
152     Name:            'F'
153     IsInGlobalNamespace: true
154 VirtualParents:
155   - Type:            Record
156     Name:            'G'
157     Path:            'path/to/G'
158 ChildRecords:
159   - Type:            Record
160     Name:            'ChildStruct'
161     Path:            'path/to/A/r'
162 ChildFunctions:
163   - USR:             '0000000000000000000000000000000000000000'
164     Name:            'OneFunction'
165     ReturnType:      {}
166     Access:          Public
167 ChildEnums:
168   - USR:             '0000000000000000000000000000000000000000'
169     Name:            'OneEnum'
170 ...
171 )raw";
172   EXPECT_EQ(Expected, Actual.str());
173 }
174 
TEST(YAMLGeneratorTest,emitFunctionYAML)175 TEST(YAMLGeneratorTest, emitFunctionYAML) {
176   FunctionInfo I;
177   I.Name = "f";
178   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
179 
180   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
181   I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
182 
183   I.Access = AccessSpecifier::AS_none;
184 
185   I.ReturnType =
186       TypeInfo(EmptySID, "void", InfoType::IT_default, "path/to/void");
187   I.Params.emplace_back("int", "path/to/int", "P");
188   I.IsMethod = true;
189   I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
190 
191   auto G = getYAMLGenerator();
192   assert(G);
193   std::string Buffer;
194   llvm::raw_string_ostream Actual(Buffer);
195   auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());
196   assert(!Err);
197   std::string Expected =
198       R"raw(---
199 USR:             '0000000000000000000000000000000000000000'
200 Name:            'f'
201 Namespace:
202   - Type:            Namespace
203     Name:            'A'
204 DefLocation:
205   LineNumber:      10
206   Filename:        'test.cpp'
207 Location:
208   - LineNumber:      12
209     Filename:        'test.cpp'
210 IsMethod:        true
211 Parent:
212   Type:            Record
213   Name:            'Parent'
214 Params:
215   - Type:
216       Name:            'int'
217       Path:            'path/to/int'
218     Name:            'P'
219 ReturnType:
220   Type:
221     Name:            'void'
222     Path:            'path/to/void'
223 ...
224 )raw";
225   EXPECT_EQ(Expected, Actual.str());
226 }
227 
TEST(YAMLGeneratorTest,emitEnumYAML)228 TEST(YAMLGeneratorTest, emitEnumYAML) {
229   EnumInfo I;
230   I.Name = "e";
231   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
232 
233   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
234   I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
235 
236   I.Members.emplace_back("X");
237   I.Scoped = true;
238 
239   auto G = getYAMLGenerator();
240   assert(G);
241   std::string Buffer;
242   llvm::raw_string_ostream Actual(Buffer);
243   auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());
244   assert(!Err);
245   std::string Expected =
246       R"raw(---
247 USR:             '0000000000000000000000000000000000000000'
248 Name:            'e'
249 Namespace:
250   - Type:            Namespace
251     Name:            'A'
252 DefLocation:
253   LineNumber:      10
254   Filename:        'test.cpp'
255 Location:
256   - LineNumber:      12
257     Filename:        'test.cpp'
258 Scoped:          true
259 Members:
260   - 'X'
261 ...
262 )raw";
263   EXPECT_EQ(Expected, Actual.str());
264 }
265 
TEST(YAMLGeneratorTest,emitCommentYAML)266 TEST(YAMLGeneratorTest, emitCommentYAML) {
267   FunctionInfo I;
268   I.Name = "f";
269   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
270   I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
271   I.Params.emplace_back("int", "I");
272   I.Params.emplace_back("int", "J");
273   I.Access = AccessSpecifier::AS_none;
274 
275   CommentInfo Top;
276   Top.Kind = "FullComment";
277 
278   Top.Children.emplace_back(std::make_unique<CommentInfo>());
279   CommentInfo *BlankLine = Top.Children.back().get();
280   BlankLine->Kind = "ParagraphComment";
281   BlankLine->Children.emplace_back(std::make_unique<CommentInfo>());
282   BlankLine->Children.back()->Kind = "TextComment";
283 
284   Top.Children.emplace_back(std::make_unique<CommentInfo>());
285   CommentInfo *Brief = Top.Children.back().get();
286   Brief->Kind = "ParagraphComment";
287   Brief->Children.emplace_back(std::make_unique<CommentInfo>());
288   Brief->Children.back()->Kind = "TextComment";
289   Brief->Children.back()->Name = "ParagraphComment";
290   Brief->Children.back()->Text = " Brief description.";
291 
292   Top.Children.emplace_back(std::make_unique<CommentInfo>());
293   CommentInfo *Extended = Top.Children.back().get();
294   Extended->Kind = "ParagraphComment";
295   Extended->Children.emplace_back(std::make_unique<CommentInfo>());
296   Extended->Children.back()->Kind = "TextComment";
297   Extended->Children.back()->Text = " Extended description that";
298   Extended->Children.emplace_back(std::make_unique<CommentInfo>());
299   Extended->Children.back()->Kind = "TextComment";
300   Extended->Children.back()->Text = " continues onto the next line.";
301 
302   Top.Children.emplace_back(std::make_unique<CommentInfo>());
303   CommentInfo *HTML = Top.Children.back().get();
304   HTML->Kind = "ParagraphComment";
305   HTML->Children.emplace_back(std::make_unique<CommentInfo>());
306   HTML->Children.back()->Kind = "TextComment";
307   HTML->Children.emplace_back(std::make_unique<CommentInfo>());
308   HTML->Children.back()->Kind = "HTMLStartTagComment";
309   HTML->Children.back()->Name = "ul";
310   HTML->Children.back()->AttrKeys.emplace_back("class");
311   HTML->Children.back()->AttrValues.emplace_back("test");
312   HTML->Children.emplace_back(std::make_unique<CommentInfo>());
313   HTML->Children.back()->Kind = "HTMLStartTagComment";
314   HTML->Children.back()->Name = "li";
315   HTML->Children.emplace_back(std::make_unique<CommentInfo>());
316   HTML->Children.back()->Kind = "TextComment";
317   HTML->Children.back()->Text = " Testing.";
318   HTML->Children.emplace_back(std::make_unique<CommentInfo>());
319   HTML->Children.back()->Kind = "HTMLEndTagComment";
320   HTML->Children.back()->Name = "ul";
321   HTML->Children.back()->SelfClosing = true;
322 
323   Top.Children.emplace_back(std::make_unique<CommentInfo>());
324   CommentInfo *Verbatim = Top.Children.back().get();
325   Verbatim->Kind = "VerbatimBlockComment";
326   Verbatim->Name = "verbatim";
327   Verbatim->CloseName = "endverbatim";
328   Verbatim->Children.emplace_back(std::make_unique<CommentInfo>());
329   Verbatim->Children.back()->Kind = "VerbatimBlockLineComment";
330   Verbatim->Children.back()->Text = " The description continues.";
331 
332   Top.Children.emplace_back(std::make_unique<CommentInfo>());
333   CommentInfo *ParamOut = Top.Children.back().get();
334   ParamOut->Kind = "ParamCommandComment";
335   ParamOut->Direction = "[out]";
336   ParamOut->ParamName = "I";
337   ParamOut->Explicit = true;
338   ParamOut->Children.emplace_back(std::make_unique<CommentInfo>());
339   ParamOut->Children.back()->Kind = "ParagraphComment";
340   ParamOut->Children.back()->Children.emplace_back(
341       std::make_unique<CommentInfo>());
342   ParamOut->Children.back()->Children.back()->Kind = "TextComment";
343   ParamOut->Children.back()->Children.emplace_back(
344       std::make_unique<CommentInfo>());
345   ParamOut->Children.back()->Children.back()->Kind = "TextComment";
346   ParamOut->Children.back()->Children.back()->Text = " is a parameter.";
347 
348   Top.Children.emplace_back(std::make_unique<CommentInfo>());
349   CommentInfo *ParamIn = Top.Children.back().get();
350   ParamIn->Kind = "ParamCommandComment";
351   ParamIn->Direction = "[in]";
352   ParamIn->ParamName = "J";
353   ParamIn->Children.emplace_back(std::make_unique<CommentInfo>());
354   ParamIn->Children.back()->Kind = "ParagraphComment";
355   ParamIn->Children.back()->Children.emplace_back(
356       std::make_unique<CommentInfo>());
357   ParamIn->Children.back()->Children.back()->Kind = "TextComment";
358   ParamIn->Children.back()->Children.back()->Text = " is a parameter.";
359   ParamIn->Children.back()->Children.emplace_back(
360       std::make_unique<CommentInfo>());
361   ParamIn->Children.back()->Children.back()->Kind = "TextComment";
362 
363   Top.Children.emplace_back(std::make_unique<CommentInfo>());
364   CommentInfo *Return = Top.Children.back().get();
365   Return->Kind = "BlockCommandComment";
366   Return->Name = "return";
367   Return->Explicit = true;
368   Return->Children.emplace_back(std::make_unique<CommentInfo>());
369   Return->Children.back()->Kind = "ParagraphComment";
370   Return->Children.back()->Children.emplace_back(
371       std::make_unique<CommentInfo>());
372   Return->Children.back()->Children.back()->Kind = "TextComment";
373   Return->Children.back()->Children.back()->Text = "void";
374 
375   I.Description.emplace_back(std::move(Top));
376 
377   auto G = getYAMLGenerator();
378   assert(G);
379   std::string Buffer;
380   llvm::raw_string_ostream Actual(Buffer);
381   auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());
382   assert(!Err);
383   std::string Expected =
384       R"raw(---
385 USR:             '0000000000000000000000000000000000000000'
386 Name:            'f'
387 Description:
388   - Kind:            'FullComment'
389     Children:
390       - Kind:            'ParagraphComment'
391         Children:
392           - Kind:            'TextComment'
393       - Kind:            'ParagraphComment'
394         Children:
395           - Kind:            'TextComment'
396             Text:            ' Brief description.'
397             Name:            'ParagraphComment'
398       - Kind:            'ParagraphComment'
399         Children:
400           - Kind:            'TextComment'
401             Text:            ' Extended description that'
402           - Kind:            'TextComment'
403             Text:            ' continues onto the next line.'
404       - Kind:            'ParagraphComment'
405         Children:
406           - Kind:            'TextComment'
407           - Kind:            'HTMLStartTagComment'
408             Name:            'ul'
409             AttrKeys:
410               - 'class'
411             AttrValues:
412               - 'test'
413           - Kind:            'HTMLStartTagComment'
414             Name:            'li'
415           - Kind:            'TextComment'
416             Text:            ' Testing.'
417           - Kind:            'HTMLEndTagComment'
418             Name:            'ul'
419             SelfClosing:     true
420       - Kind:            'VerbatimBlockComment'
421         Name:            'verbatim'
422         CloseName:       'endverbatim'
423         Children:
424           - Kind:            'VerbatimBlockLineComment'
425             Text:            ' The description continues.'
426       - Kind:            'ParamCommandComment'
427         Direction:       '[out]'
428         ParamName:       'I'
429         Explicit:        true
430         Children:
431           - Kind:            'ParagraphComment'
432             Children:
433               - Kind:            'TextComment'
434               - Kind:            'TextComment'
435                 Text:            ' is a parameter.'
436       - Kind:            'ParamCommandComment'
437         Direction:       '[in]'
438         ParamName:       'J'
439         Children:
440           - Kind:            'ParagraphComment'
441             Children:
442               - Kind:            'TextComment'
443                 Text:            ' is a parameter.'
444               - Kind:            'TextComment'
445       - Kind:            'BlockCommandComment'
446         Name:            'return'
447         Explicit:        true
448         Children:
449           - Kind:            'ParagraphComment'
450             Children:
451               - Kind:            'TextComment'
452                 Text:            'void'
453 DefLocation:
454   LineNumber:      10
455   Filename:        'test.cpp'
456 Params:
457   - Type:
458       Name:            'int'
459     Name:            'I'
460   - Type:
461       Name:            'int'
462     Name:            'J'
463 ReturnType:
464   Type:
465     Name:            'void'
466 ...
467 )raw";
468 
469   EXPECT_EQ(Expected, Actual.str());
470 }
471 
472 } // namespace doc
473 } // namespace clang
474