xref: /llvm-project/clang-tools-extra/unittests/clang-doc/HTMLGeneratorTest.cpp (revision db5d8e3db253f5e3a946ccffe714fbf32c062b39)
1 //===-- clang-doc/HTMLGeneratorTest.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 
17 std::unique_ptr<Generator> getHTMLGenerator() {
18   auto G = doc::findGeneratorByName("html");
19   if (!G)
20     return nullptr;
21   return std::move(G.get());
22 }
23 
24 TEST(HTMLGeneratorTest, emitNamespaceHTML) {
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.ChildEnums.emplace_back();
35   I.ChildEnums.back().Name = "OneEnum";
36 
37   auto G = getHTMLGenerator();
38   assert(G);
39   std::string Buffer;
40   llvm::raw_string_ostream Actual(Buffer);
41   auto Err = G->generateDocForInfo(&I, Actual);
42   assert(!Err);
43   std::string Expected = R"raw(<!DOCTYPE html>
44 <meta charset="utf-8"/>
45 <title>namespace Namespace</title>
46 <link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
47 <div>
48   <h1>namespace Namespace</h1>
49   <h2>Namespaces</h2>
50   <ul>
51     <li>ChildNamespace</li>
52   </ul>
53   <h2>Records</h2>
54   <ul>
55     <li>ChildStruct</li>
56   </ul>
57   <h2>Functions</h2>
58   <div>
59     <h3>OneFunction</h3>
60     <p>OneFunction()</p>
61   </div>
62   <h2>Enums</h2>
63   <div>
64     <h3>enum OneEnum</h3>
65   </div>
66 </div>
67 )raw";
68 
69   EXPECT_EQ(Expected, Actual.str());
70 }
71 
72 TEST(HTMLGeneratorTest, emitRecordHTML) {
73   RecordInfo I;
74   I.Name = "r";
75   I.Path = "X/Y/Z";
76   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
77 
78   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
79   I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
80 
81   SmallString<16> PathTo;
82   llvm::sys::path::native("path/to", PathTo);
83   I.Members.emplace_back("int", "X/Y", "X", AccessSpecifier::AS_private);
84   I.TagType = TagTypeKind::TTK_Class;
85   I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, PathTo);
86   I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
87 
88   I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
89   I.ChildFunctions.emplace_back();
90   I.ChildFunctions.back().Name = "OneFunction";
91   I.ChildEnums.emplace_back();
92   I.ChildEnums.back().Name = "OneEnum";
93 
94   auto G = getHTMLGenerator();
95   assert(G);
96   std::string Buffer;
97   llvm::raw_string_ostream Actual(Buffer);
98   auto Err = G->generateDocForInfo(&I, Actual);
99   assert(!Err);
100   SmallString<16> PathToF;
101   llvm::sys::path::native("../../../path/to/F.html", PathToF);
102   SmallString<16> PathToInt;
103   llvm::sys::path::native("../int.html", PathToInt);
104   std::string Expected = R"raw(<!DOCTYPE html>
105 <meta charset="utf-8"/>
106 <title>class r</title>
107 <link rel="stylesheet" href="../../../clang-doc-default-stylesheet.css"/>
108 <div>
109   <h1>class r</h1>
110   <p>Defined at line 10 of test.cpp</p>
111   <p>
112     Inherits from
113     <a href=")raw" + std::string(PathToF.str()) +
114                          R"raw(">F</a>
115     , G
116   </p>
117   <h2>Members</h2>
118   <ul>
119     <li>
120       private
121       <a href=")raw" + std::string(PathToInt.str()) +
122                          R"raw(">int</a>
123        X
124     </li>
125   </ul>
126   <h2>Records</h2>
127   <ul>
128     <li>ChildStruct</li>
129   </ul>
130   <h2>Functions</h2>
131   <div>
132     <h3>OneFunction</h3>
133     <p>OneFunction()</p>
134   </div>
135   <h2>Enums</h2>
136   <div>
137     <h3>enum OneEnum</h3>
138   </div>
139 </div>
140 )raw";
141 
142   EXPECT_EQ(Expected, Actual.str());
143 }
144 
145 TEST(HTMLGeneratorTest, emitFunctionHTML) {
146   FunctionInfo I;
147   I.Name = "f";
148   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
149 
150   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
151   I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
152 
153   SmallString<16> PathTo;
154   llvm::sys::path::native("path/to", PathTo);
155   I.ReturnType = TypeInfo(EmptySID, "float", InfoType::IT_default, PathTo);
156   I.Params.emplace_back("int", PathTo, "P");
157   I.IsMethod = true;
158   I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
159 
160   auto G = getHTMLGenerator();
161   assert(G);
162   std::string Buffer;
163   llvm::raw_string_ostream Actual(Buffer);
164   auto Err = G->generateDocForInfo(&I, Actual);
165   assert(!Err);
166   SmallString<16> PathToFloat;
167   llvm::sys::path::native("path/to/float.html", PathToFloat);
168   SmallString<16> PathToInt;
169   llvm::sys::path::native("path/to/int.html", PathToInt);
170   std::string Expected = R"raw(<!DOCTYPE html>
171 <meta charset="utf-8"/>
172 <title></title>
173 <link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
174 <div>
175   <h3>f</h3>
176   <p>
177     <a href=")raw" + std::string(PathToFloat.str()) +
178                          R"raw(">float</a>
179      f(
180     <a href=")raw" + std::string(PathToInt.str()) +
181                          R"raw(">int</a>
182      P)
183   </p>
184   <p>Defined at line 10 of test.cpp</p>
185 </div>
186 )raw";
187 
188   EXPECT_EQ(Expected, Actual.str());
189 }
190 
191 TEST(HTMLGeneratorTest, emitEnumHTML) {
192   EnumInfo I;
193   I.Name = "e";
194   I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
195 
196   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
197   I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
198 
199   I.Members.emplace_back("X");
200   I.Scoped = true;
201 
202   auto G = getHTMLGenerator();
203   assert(G);
204   std::string Buffer;
205   llvm::raw_string_ostream Actual(Buffer);
206   auto Err = G->generateDocForInfo(&I, Actual);
207   assert(!Err);
208   std::string Expected = R"raw(<!DOCTYPE html>
209 <meta charset="utf-8"/>
210 <title></title>
211 <link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
212 <div>
213   <h3>enum class e</h3>
214   <ul>
215     <li>X</li>
216   </ul>
217   <p>Defined at line 10 of test.cpp</p>
218 </div>
219 )raw";
220 
221   EXPECT_EQ(Expected, Actual.str());
222 }
223 
224 TEST(HTMLGeneratorTest, emitCommentHTML) {
225   FunctionInfo I;
226   I.Name = "f";
227   I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
228   I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
229   I.Params.emplace_back("int", "I");
230   I.Params.emplace_back("int", "J");
231 
232   CommentInfo Top;
233   Top.Kind = "FullComment";
234 
235   Top.Children.emplace_back(llvm::make_unique<CommentInfo>());
236   CommentInfo *BlankLine = Top.Children.back().get();
237   BlankLine->Kind = "ParagraphComment";
238   BlankLine->Children.emplace_back(llvm::make_unique<CommentInfo>());
239   BlankLine->Children.back()->Kind = "TextComment";
240 
241   Top.Children.emplace_back(llvm::make_unique<CommentInfo>());
242   CommentInfo *Brief = Top.Children.back().get();
243   Brief->Kind = "ParagraphComment";
244   Brief->Children.emplace_back(llvm::make_unique<CommentInfo>());
245   Brief->Children.back()->Kind = "TextComment";
246   Brief->Children.back()->Name = "ParagraphComment";
247   Brief->Children.back()->Text = " Brief description.";
248 
249   Top.Children.emplace_back(llvm::make_unique<CommentInfo>());
250   CommentInfo *Extended = Top.Children.back().get();
251   Extended->Kind = "ParagraphComment";
252   Extended->Children.emplace_back(llvm::make_unique<CommentInfo>());
253   Extended->Children.back()->Kind = "TextComment";
254   Extended->Children.back()->Text = " Extended description that";
255   Extended->Children.emplace_back(llvm::make_unique<CommentInfo>());
256   Extended->Children.back()->Kind = "TextComment";
257   Extended->Children.back()->Text = " continues onto the next line.";
258 
259   Top.Children.emplace_back(llvm::make_unique<CommentInfo>());
260   CommentInfo *Entities = Top.Children.back().get();
261   Entities->Kind = "ParagraphComment";
262   Entities->Children.emplace_back(llvm::make_unique<CommentInfo>());
263   Entities->Children.back()->Kind = "TextComment";
264   Entities->Children.back()->Name = "ParagraphComment";
265   Entities->Children.back()->Text =
266       " Comment with html entities: &, <, >, \", \'.";
267 
268   I.Description.emplace_back(std::move(Top));
269 
270   auto G = getHTMLGenerator();
271   assert(G);
272   std::string Buffer;
273   llvm::raw_string_ostream Actual(Buffer);
274   auto Err = G->generateDocForInfo(&I, Actual);
275   assert(!Err);
276   std::string Expected = R"raw(<!DOCTYPE html>
277 <meta charset="utf-8"/>
278 <title></title>
279 <link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
280 <div>
281   <h3>f</h3>
282   <p>void f(int I, int J)</p>
283   <p>Defined at line 10 of test.cpp</p>
284   <div>
285     <div>
286       <p> Brief description.</p>
287       <p> Extended description that continues onto the next line.</p>
288       <p> Comment with html entities: &amp;, &lt;, &gt;, &quot;, &apos;.</p>
289     </div>
290   </div>
291 </div>
292 )raw";
293 
294   EXPECT_EQ(Expected, Actual.str());
295 }
296 
297 } // namespace doc
298 } // namespace clang
299