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