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: &, <, >, ", '.</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