1 //===-- clang-doc/BitcodeTest.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 "BitcodeReader.h" 10 #include "BitcodeWriter.h" 11 #include "ClangDocTest.h" 12 #include "Representation.h" 13 #include "llvm/Bitcode/BitstreamReader.h" 14 #include "llvm/Bitcode/BitstreamWriter.h" 15 #include "gtest/gtest.h" 16 17 namespace clang { 18 namespace doc { 19 20 template <typename T> static std::string writeInfo(T &I) { 21 SmallString<2048> Buffer; 22 llvm::BitstreamWriter Stream(Buffer); 23 ClangDocBitcodeWriter Writer(Stream); 24 Writer.emitBlock(I); 25 return Buffer.str().str(); 26 } 27 28 std::string writeInfo(Info *I) { 29 switch (I->IT) { 30 case InfoType::IT_namespace: 31 return writeInfo(*static_cast<NamespaceInfo *>(I)); 32 case InfoType::IT_record: 33 return writeInfo(*static_cast<RecordInfo *>(I)); 34 case InfoType::IT_enum: 35 return writeInfo(*static_cast<EnumInfo *>(I)); 36 case InfoType::IT_function: 37 return writeInfo(*static_cast<FunctionInfo *>(I)); 38 default: 39 return ""; 40 } 41 } 42 43 std::vector<std::unique_ptr<Info>> readInfo(StringRef Bitcode, 44 size_t NumInfos) { 45 llvm::BitstreamCursor Stream(Bitcode); 46 doc::ClangDocBitcodeReader Reader(Stream); 47 auto Infos = Reader.readBitcode(); 48 49 // Check that there was no error in the read. 50 assert(Infos); 51 EXPECT_EQ(Infos.get().size(), NumInfos); 52 return std::move(Infos.get()); 53 } 54 55 TEST(BitcodeTest, emitNamespaceInfoBitcode) { 56 NamespaceInfo I; 57 I.Name = "r"; 58 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); 59 60 I.ChildNamespaces.emplace_back(EmptySID, "ChildNamespace", 61 InfoType::IT_namespace); 62 I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record); 63 I.ChildFunctions.emplace_back(); 64 I.ChildEnums.emplace_back(); 65 66 std::string WriteResult = writeInfo(&I); 67 EXPECT_TRUE(WriteResult.size() > 0); 68 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 69 70 CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0].get())); 71 } 72 73 TEST(BitcodeTest, emitRecordInfoBitcode) { 74 RecordInfo I; 75 I.Name = "r"; 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 I.Members.emplace_back("int", "X", AccessSpecifier::AS_private); 82 I.TagType = TagTypeKind::TTK_Class; 83 I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record); 84 I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record); 85 86 I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record); 87 I.ChildFunctions.emplace_back(); 88 I.ChildEnums.emplace_back(); 89 90 std::string WriteResult = writeInfo(&I); 91 EXPECT_TRUE(WriteResult.size() > 0); 92 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 93 94 CheckRecordInfo(&I, InfoAsRecord(ReadResults[0].get())); 95 } 96 97 TEST(BitcodeTest, emitFunctionInfoBitcode) { 98 FunctionInfo I; 99 I.Name = "f"; 100 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); 101 102 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}); 103 I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); 104 105 I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 106 I.Params.emplace_back("int", "P"); 107 108 std::string WriteResult = writeInfo(&I); 109 EXPECT_TRUE(WriteResult.size() > 0); 110 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 111 112 CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get())); 113 } 114 115 TEST(BitcodeTest, emitMethodInfoBitcode) { 116 FunctionInfo I; 117 I.Name = "f"; 118 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); 119 120 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}); 121 I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); 122 123 I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 124 I.Params.emplace_back("int", "P"); 125 I.IsMethod = true; 126 I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record); 127 128 // TODO: fix access 129 // I.Access = AccessSpecifier::AS_private; 130 131 std::string WriteResult = writeInfo(&I); 132 EXPECT_TRUE(WriteResult.size() > 0); 133 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 134 135 CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get())); 136 } 137 138 TEST(BitcodeTest, emitEnumInfoBitcode) { 139 EnumInfo I; 140 I.Name = "e"; 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.Members.emplace_back("X"); 147 I.Scoped = true; 148 149 std::string WriteResult = writeInfo(&I); 150 EXPECT_TRUE(WriteResult.size() > 0); 151 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 152 153 CheckEnumInfo(&I, InfoAsEnum(ReadResults[0].get())); 154 } 155 156 TEST(SerializeTest, emitInfoWithCommentBitcode) { 157 FunctionInfo F; 158 F.Name = "F"; 159 F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 160 F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 161 F.Params.emplace_back("int", "I"); 162 163 CommentInfo Top; 164 Top.Kind = "FullComment"; 165 166 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 167 CommentInfo *BlankLine = Top.Children.back().get(); 168 BlankLine->Kind = "ParagraphComment"; 169 BlankLine->Children.emplace_back(llvm::make_unique<CommentInfo>()); 170 BlankLine->Children.back()->Kind = "TextComment"; 171 172 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 173 CommentInfo *Brief = Top.Children.back().get(); 174 Brief->Kind = "ParagraphComment"; 175 Brief->Children.emplace_back(llvm::make_unique<CommentInfo>()); 176 Brief->Children.back()->Kind = "TextComment"; 177 Brief->Children.back()->Name = "ParagraphComment"; 178 Brief->Children.back()->Text = " Brief description."; 179 180 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 181 CommentInfo *Extended = Top.Children.back().get(); 182 Extended->Kind = "ParagraphComment"; 183 Extended->Children.emplace_back(llvm::make_unique<CommentInfo>()); 184 Extended->Children.back()->Kind = "TextComment"; 185 Extended->Children.back()->Text = " Extended description that"; 186 Extended->Children.emplace_back(llvm::make_unique<CommentInfo>()); 187 Extended->Children.back()->Kind = "TextComment"; 188 Extended->Children.back()->Text = " continues onto the next line."; 189 190 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 191 CommentInfo *HTML = Top.Children.back().get(); 192 HTML->Kind = "ParagraphComment"; 193 HTML->Children.emplace_back(llvm::make_unique<CommentInfo>()); 194 HTML->Children.back()->Kind = "TextComment"; 195 HTML->Children.emplace_back(llvm::make_unique<CommentInfo>()); 196 HTML->Children.back()->Kind = "HTMLStartTagComment"; 197 HTML->Children.back()->Name = "ul"; 198 HTML->Children.back()->AttrKeys.emplace_back("class"); 199 HTML->Children.back()->AttrValues.emplace_back("test"); 200 HTML->Children.emplace_back(llvm::make_unique<CommentInfo>()); 201 HTML->Children.back()->Kind = "HTMLStartTagComment"; 202 HTML->Children.back()->Name = "li"; 203 HTML->Children.emplace_back(llvm::make_unique<CommentInfo>()); 204 HTML->Children.back()->Kind = "TextComment"; 205 HTML->Children.back()->Text = " Testing."; 206 HTML->Children.emplace_back(llvm::make_unique<CommentInfo>()); 207 HTML->Children.back()->Kind = "HTMLEndTagComment"; 208 HTML->Children.back()->Name = "ul"; 209 HTML->Children.back()->SelfClosing = true; 210 211 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 212 CommentInfo *Verbatim = Top.Children.back().get(); 213 Verbatim->Kind = "VerbatimBlockComment"; 214 Verbatim->Name = "verbatim"; 215 Verbatim->CloseName = "endverbatim"; 216 Verbatim->Children.emplace_back(llvm::make_unique<CommentInfo>()); 217 Verbatim->Children.back()->Kind = "VerbatimBlockLineComment"; 218 Verbatim->Children.back()->Text = " The description continues."; 219 220 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 221 CommentInfo *ParamOut = Top.Children.back().get(); 222 ParamOut->Kind = "ParamCommandComment"; 223 ParamOut->Direction = "[out]"; 224 ParamOut->ParamName = "I"; 225 ParamOut->Explicit = true; 226 ParamOut->Children.emplace_back(llvm::make_unique<CommentInfo>()); 227 ParamOut->Children.back()->Kind = "ParagraphComment"; 228 ParamOut->Children.back()->Children.emplace_back( 229 llvm::make_unique<CommentInfo>()); 230 ParamOut->Children.back()->Children.back()->Kind = "TextComment"; 231 ParamOut->Children.back()->Children.emplace_back( 232 llvm::make_unique<CommentInfo>()); 233 ParamOut->Children.back()->Children.back()->Kind = "TextComment"; 234 ParamOut->Children.back()->Children.back()->Text = " is a parameter."; 235 236 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 237 CommentInfo *ParamIn = Top.Children.back().get(); 238 ParamIn->Kind = "ParamCommandComment"; 239 ParamIn->Direction = "[in]"; 240 ParamIn->ParamName = "J"; 241 ParamIn->Children.emplace_back(llvm::make_unique<CommentInfo>()); 242 ParamIn->Children.back()->Kind = "ParagraphComment"; 243 ParamIn->Children.back()->Children.emplace_back( 244 llvm::make_unique<CommentInfo>()); 245 ParamIn->Children.back()->Children.back()->Kind = "TextComment"; 246 ParamIn->Children.back()->Children.back()->Text = " is a parameter."; 247 ParamIn->Children.back()->Children.emplace_back( 248 llvm::make_unique<CommentInfo>()); 249 ParamIn->Children.back()->Children.back()->Kind = "TextComment"; 250 251 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 252 CommentInfo *Return = Top.Children.back().get(); 253 Return->Kind = "BlockCommandComment"; 254 Return->Name = "return"; 255 Return->Explicit = true; 256 Return->Children.emplace_back(llvm::make_unique<CommentInfo>()); 257 Return->Children.back()->Kind = "ParagraphComment"; 258 Return->Children.back()->Children.emplace_back( 259 llvm::make_unique<CommentInfo>()); 260 Return->Children.back()->Children.back()->Kind = "TextComment"; 261 Return->Children.back()->Children.back()->Text = "void"; 262 263 F.Description.emplace_back(std::move(Top)); 264 265 std::string WriteResult = writeInfo(&F); 266 EXPECT_TRUE(WriteResult.size() > 0); 267 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 268 269 CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0].get())); 270 } 271 272 } // namespace doc 273 } // namespace clang 274