[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang-tools-extra / unittests / clang-doc / HTMLGeneratorTest.cpp
blob51412591616533b281da364edec36c35971e9f93
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 //===----------------------------------------------------------------------===//
9 #include "ClangDocTest.h"
10 #include "Generators.h"
11 #include "Representation.h"
12 #include "Serialize.h"
13 #include "clang/Basic/Version.h"
14 #include "gtest/gtest.h"
16 namespace clang {
17 namespace doc {
19 static const std::string ClangDocVersion =
20 clang::getClangToolFullVersion("clang-doc");
22 std::unique_ptr<Generator> getHTMLGenerator() {
23 auto G = doc::findGeneratorByName("html");
24 if (!G)
25 return nullptr;
26 return std::move(G.get());
29 ClangDocContext
30 getClangDocContext(std::vector<std::string> UserStylesheets = {},
31 StringRef RepositoryUrl = "") {
32 ClangDocContext CDCtx{
33 {}, "test-project", {}, {}, {}, RepositoryUrl, UserStylesheets, {}};
34 CDCtx.UserStylesheets.insert(
35 CDCtx.UserStylesheets.begin(),
36 "../share/clang/clang-doc-default-stylesheet.css");
37 CDCtx.JsScripts.emplace_back("index.js");
38 return CDCtx;
41 TEST(HTMLGeneratorTest, emitNamespaceHTML) {
42 NamespaceInfo I;
43 I.Name = "Namespace";
44 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
46 I.Children.Namespaces.emplace_back(EmptySID, "ChildNamespace",
47 InfoType::IT_namespace,
48 "Namespace::ChildNamespace", "Namespace");
49 I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
50 "Namespace::ChildStruct", "Namespace");
51 I.Children.Functions.emplace_back();
52 I.Children.Functions.back().Access = AccessSpecifier::AS_none;
53 I.Children.Functions.back().Name = "OneFunction";
54 I.Children.Enums.emplace_back();
55 I.Children.Enums.back().Name = "OneEnum";
57 auto G = getHTMLGenerator();
58 assert(G);
59 std::string Buffer;
60 llvm::raw_string_ostream Actual(Buffer);
61 ClangDocContext CDCtx = getClangDocContext({"user-provided-stylesheet.css"});
62 auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
63 assert(!Err);
64 std::string Expected = R"raw(<!DOCTYPE html>
65 <meta charset="utf-8"/>
66 <title>namespace Namespace</title>
67 <link rel="stylesheet" href="../clang-doc-default-stylesheet.css"/>
68 <link rel="stylesheet" href="../user-provided-stylesheet.css"/>
69 <script src="../index.js"></script>
70 <header id="project-title">test-project</header>
71 <main>
72 <div id="sidebar-left" path="Namespace" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
73 <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
74 <h1>namespace Namespace</h1>
75 <h2 id="Namespaces">Namespaces</h2>
76 <ul>
77 <li>
78 <a href="ChildNamespace/index.html">ChildNamespace</a>
79 </li>
80 </ul>
81 <h2 id="Records">Records</h2>
82 <ul>
83 <li>
84 <a href="ChildStruct.html">ChildStruct</a>
85 </li>
86 </ul>
87 <h2 id="Functions">Functions</h2>
88 <div>
89 <h3 id="0000000000000000000000000000000000000000">OneFunction</h3>
90 <p>OneFunction()</p>
91 </div>
92 <h2 id="Enums">Enums</h2>
93 <div>
94 <h3 id="0000000000000000000000000000000000000000">enum OneEnum</h3>
95 </div>
96 </div>
97 <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right">
98 <ol>
99 <li>
100 <span>
101 <a href="#Namespaces">Namespaces</a>
102 </span>
103 </li>
104 <li>
105 <span>
106 <a href="#Records">Records</a>
107 </span>
108 </li>
109 <li>
110 <span>
111 <a href="#Functions">Functions</a>
112 </span>
113 <ul>
114 <li>
115 <span>
116 <a href="#0000000000000000000000000000000000000000">OneFunction</a>
117 </span>
118 </li>
119 </ul>
120 </li>
121 <li>
122 <span>
123 <a href="#Enums">Enums</a>
124 </span>
125 <ul>
126 <li>
127 <span>
128 <a href="#0000000000000000000000000000000000000000">OneEnum</a>
129 </span>
130 </li>
131 </ul>
132 </li>
133 </ol>
134 </div>
135 </main>
136 <footer>
137 <span class="no-break">)raw" +
138 ClangDocVersion + R"raw(</span>
139 </footer>
140 )raw";
142 EXPECT_EQ(Expected, Actual.str());
145 TEST(HTMLGeneratorTest, emitRecordHTML) {
146 RecordInfo I;
147 I.Name = "r";
148 I.Path = "X/Y/Z";
149 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
151 I.DefLoc = Location(10, llvm::SmallString<16>{"dir/test.cpp"}, true);
152 I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
154 SmallString<16> PathTo;
155 llvm::sys::path::native("path/to", PathTo);
156 I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
157 I.TagType = TagTypeKind::TTK_Class;
158 I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "F", PathTo);
159 I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
161 I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
162 "X::Y::Z::r::ChildStruct", "X/Y/Z/r");
163 I.Children.Functions.emplace_back();
164 I.Children.Functions.back().Name = "OneFunction";
165 I.Children.Enums.emplace_back();
166 I.Children.Enums.back().Name = "OneEnum";
168 auto G = getHTMLGenerator();
169 assert(G);
170 std::string Buffer;
171 llvm::raw_string_ostream Actual(Buffer);
172 ClangDocContext CDCtx = getClangDocContext({}, "http://www.repository.com");
173 auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
174 assert(!Err);
175 std::string Expected = R"raw(<!DOCTYPE html>
176 <meta charset="utf-8"/>
177 <title>class r</title>
178 <link rel="stylesheet" href="../../../clang-doc-default-stylesheet.css"/>
179 <script src="../../../index.js"></script>
180 <header id="project-title">test-project</header>
181 <main>
182 <div id="sidebar-left" path="X/Y/Z" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
183 <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
184 <h1>class r</h1>
186 Defined at line
187 <a href="http://www.repository.com/dir/test.cpp#10">10</a>
188 of file
189 <a href="http://www.repository.com/dir/test.cpp">test.cpp</a>
190 </p>
192 Inherits from
193 <a href="../../../path/to/F.html">F</a>
195 </p>
196 <h2 id="Members">Members</h2>
197 <ul>
198 <li>private int X</li>
199 </ul>
200 <h2 id="Records">Records</h2>
201 <ul>
202 <li>
203 <a href="../../../X/Y/Z/r/ChildStruct.html">ChildStruct</a>
204 </li>
205 </ul>
206 <h2 id="Functions">Functions</h2>
207 <div>
208 <h3 id="0000000000000000000000000000000000000000">OneFunction</h3>
209 <p>public OneFunction()</p>
210 </div>
211 <h2 id="Enums">Enums</h2>
212 <div>
213 <h3 id="0000000000000000000000000000000000000000">enum OneEnum</h3>
214 </div>
215 </div>
216 <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right">
217 <ol>
218 <li>
219 <span>
220 <a href="#Members">Members</a>
221 </span>
222 </li>
223 <li>
224 <span>
225 <a href="#Records">Records</a>
226 </span>
227 </li>
228 <li>
229 <span>
230 <a href="#Functions">Functions</a>
231 </span>
232 <ul>
233 <li>
234 <span>
235 <a href="#0000000000000000000000000000000000000000">OneFunction</a>
236 </span>
237 </li>
238 </ul>
239 </li>
240 <li>
241 <span>
242 <a href="#Enums">Enums</a>
243 </span>
244 <ul>
245 <li>
246 <span>
247 <a href="#0000000000000000000000000000000000000000">OneEnum</a>
248 </span>
249 </li>
250 </ul>
251 </li>
252 </ol>
253 </div>
254 </main>
255 <footer>
256 <span class="no-break">)raw" +
257 ClangDocVersion + R"raw(</span>
258 </footer>
259 )raw";
261 EXPECT_EQ(Expected, Actual.str());
264 TEST(HTMLGeneratorTest, emitFunctionHTML) {
265 FunctionInfo I;
266 I.Name = "f";
267 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
269 I.DefLoc = Location(10, llvm::SmallString<16>{"dir/test.cpp"}, false);
270 I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
272 I.Access = AccessSpecifier::AS_none;
274 SmallString<16> PathTo;
275 llvm::sys::path::native("path/to", PathTo);
276 I.ReturnType = TypeInfo(
277 Reference(EmptySID, "float", InfoType::IT_default, "float", PathTo));
278 I.Params.emplace_back(TypeInfo("int", PathTo), "P");
279 I.IsMethod = true;
280 I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
282 auto G = getHTMLGenerator();
283 assert(G);
284 std::string Buffer;
285 llvm::raw_string_ostream Actual(Buffer);
286 ClangDocContext CDCtx = getClangDocContext({}, "https://www.repository.com");
287 auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
288 assert(!Err);
289 std::string Expected = R"raw(<!DOCTYPE html>
290 <meta charset="utf-8"/>
291 <title></title>
292 <link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
293 <script src="index.js"></script>
294 <header id="project-title">test-project</header>
295 <main>
296 <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
297 <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
298 <h3 id="0000000000000000000000000000000000000000">f</h3>
300 <a href="path/to/float.html">float</a>
302 <a href="path/to/int.html">int</a>
304 </p>
305 <p>Defined at line 10 of file dir/test.cpp</p>
306 </div>
307 <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"></div>
308 </main>
309 <footer>
310 <span class="no-break">)raw" +
311 ClangDocVersion + R"raw(</span>
312 </footer>
313 )raw";
315 EXPECT_EQ(Expected, Actual.str());
318 TEST(HTMLGeneratorTest, emitEnumHTML) {
319 EnumInfo I;
320 I.Name = "e";
321 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
323 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}, true);
324 I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"});
326 I.Members.emplace_back("X");
327 I.Scoped = true;
329 auto G = getHTMLGenerator();
330 assert(G);
331 std::string Buffer;
332 llvm::raw_string_ostream Actual(Buffer);
333 ClangDocContext CDCtx = getClangDocContext({}, "www.repository.com");
334 auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
335 assert(!Err);
336 std::string Expected = R"raw(<!DOCTYPE html>
337 <meta charset="utf-8"/>
338 <title></title>
339 <link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
340 <script src="index.js"></script>
341 <header id="project-title">test-project</header>
342 <main>
343 <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
344 <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
345 <h3 id="0000000000000000000000000000000000000000">enum class e</h3>
346 <ul>
347 <li>X</li>
348 </ul>
350 Defined at line
351 <a href="https://www.repository.com/test.cpp#10">10</a>
352 of file
353 <a href="https://www.repository.com/test.cpp">test.cpp</a>
354 </p>
355 </div>
356 <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"></div>
357 </main>
358 <footer>
359 <span class="no-break">)raw" +
360 ClangDocVersion + R"raw(</span>
361 </footer>
362 )raw";
364 EXPECT_EQ(Expected, Actual.str());
367 TEST(HTMLGeneratorTest, emitCommentHTML) {
368 FunctionInfo I;
369 I.Name = "f";
370 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"});
371 I.ReturnType = TypeInfo("void");
372 I.Params.emplace_back(TypeInfo("int"), "I");
373 I.Params.emplace_back(TypeInfo("int"), "J");
374 I.Access = AccessSpecifier::AS_none;
376 CommentInfo Top;
377 Top.Kind = "FullComment";
379 Top.Children.emplace_back(std::make_unique<CommentInfo>());
380 CommentInfo *BlankLine = Top.Children.back().get();
381 BlankLine->Kind = "ParagraphComment";
382 BlankLine->Children.emplace_back(std::make_unique<CommentInfo>());
383 BlankLine->Children.back()->Kind = "TextComment";
385 Top.Children.emplace_back(std::make_unique<CommentInfo>());
386 CommentInfo *Brief = Top.Children.back().get();
387 Brief->Kind = "ParagraphComment";
388 Brief->Children.emplace_back(std::make_unique<CommentInfo>());
389 Brief->Children.back()->Kind = "TextComment";
390 Brief->Children.back()->Name = "ParagraphComment";
391 Brief->Children.back()->Text = " Brief description.";
393 Top.Children.emplace_back(std::make_unique<CommentInfo>());
394 CommentInfo *Extended = Top.Children.back().get();
395 Extended->Kind = "ParagraphComment";
396 Extended->Children.emplace_back(std::make_unique<CommentInfo>());
397 Extended->Children.back()->Kind = "TextComment";
398 Extended->Children.back()->Text = " Extended description that";
399 Extended->Children.emplace_back(std::make_unique<CommentInfo>());
400 Extended->Children.back()->Kind = "TextComment";
401 Extended->Children.back()->Text = " continues onto the next line.";
403 Top.Children.emplace_back(std::make_unique<CommentInfo>());
404 CommentInfo *Entities = Top.Children.back().get();
405 Entities->Kind = "ParagraphComment";
406 Entities->Children.emplace_back(std::make_unique<CommentInfo>());
407 Entities->Children.back()->Kind = "TextComment";
408 Entities->Children.back()->Name = "ParagraphComment";
409 Entities->Children.back()->Text =
410 " Comment with html entities: &, <, >, \", \'.";
412 I.Description.emplace_back(std::move(Top));
414 auto G = getHTMLGenerator();
415 assert(G);
416 std::string Buffer;
417 llvm::raw_string_ostream Actual(Buffer);
418 ClangDocContext CDCtx = getClangDocContext();
419 auto Err = G->generateDocForInfo(&I, Actual, CDCtx);
420 assert(!Err);
421 std::string Expected = R"raw(<!DOCTYPE html>
422 <meta charset="utf-8"/>
423 <title></title>
424 <link rel="stylesheet" href="clang-doc-default-stylesheet.css"/>
425 <script src="index.js"></script>
426 <header id="project-title">test-project</header>
427 <main>
428 <div id="sidebar-left" path="" class="col-xs-6 col-sm-3 col-md-2 sidebar sidebar-offcanvas-left"></div>
429 <div id="main-content" class="col-xs-12 col-sm-9 col-md-8 main-content">
430 <h3 id="0000000000000000000000000000000000000000">f</h3>
431 <p>void f(int I, int J)</p>
432 <p>Defined at line 10 of file test.cpp</p>
433 <div>
434 <div>
435 <p> Brief description.</p>
436 <p> Extended description that continues onto the next line.</p>
437 <p> Comment with html entities: &amp;, &lt;, &gt;, &quot;, &apos;.</p>
438 </div>
439 </div>
440 </div>
441 <div id="sidebar-right" class="col-xs-6 col-sm-6 col-md-2 sidebar sidebar-offcanvas-right"></div>
442 </main>
443 <footer>
444 <span class="no-break">)raw" +
445 ClangDocVersion + R"raw(</span>
446 </footer>
447 )raw";
449 EXPECT_EQ(Expected, Actual.str());
452 } // namespace doc
453 } // namespace clang