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/Bitstream/BitstreamReader.h" 14 #include "llvm/Bitstream/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.IsTypeDef = true; 84 I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record); 85 I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record); 86 87 I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record); 88 I.ChildFunctions.emplace_back(); 89 I.ChildEnums.emplace_back(); 90 91 std::string WriteResult = writeInfo(&I); 92 EXPECT_TRUE(WriteResult.size() > 0); 93 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 94 95 CheckRecordInfo(&I, InfoAsRecord(ReadResults[0].get())); 96 } 97 98 TEST(BitcodeTest, emitFunctionInfoBitcode) { 99 FunctionInfo I; 100 I.Name = "f"; 101 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); 102 103 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}); 104 I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); 105 106 I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 107 I.Params.emplace_back("int", "P"); 108 109 std::string WriteResult = writeInfo(&I); 110 EXPECT_TRUE(WriteResult.size() > 0); 111 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 112 113 CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get())); 114 } 115 116 TEST(BitcodeTest, emitMethodInfoBitcode) { 117 FunctionInfo I; 118 I.Name = "f"; 119 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); 120 121 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}); 122 I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); 123 124 I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 125 I.Params.emplace_back("int", "P"); 126 I.IsMethod = true; 127 I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record); 128 129 // TODO: fix access 130 // I.Access = AccessSpecifier::AS_private; 131 132 std::string WriteResult = writeInfo(&I); 133 EXPECT_TRUE(WriteResult.size() > 0); 134 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 135 136 CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get())); 137 } 138 139 TEST(BitcodeTest, emitEnumInfoBitcode) { 140 EnumInfo I; 141 I.Name = "e"; 142 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); 143 144 I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}); 145 I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); 146 147 I.Members.emplace_back("X"); 148 I.Scoped = true; 149 150 std::string WriteResult = writeInfo(&I); 151 EXPECT_TRUE(WriteResult.size() > 0); 152 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 153 154 CheckEnumInfo(&I, InfoAsEnum(ReadResults[0].get())); 155 } 156 157 TEST(SerializeTest, emitInfoWithCommentBitcode) { 158 FunctionInfo F; 159 F.Name = "F"; 160 F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); 161 F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"}); 162 F.Params.emplace_back("int", "I"); 163 164 CommentInfo Top; 165 Top.Kind = "FullComment"; 166 167 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 168 CommentInfo *BlankLine = Top.Children.back().get(); 169 BlankLine->Kind = "ParagraphComment"; 170 BlankLine->Children.emplace_back(llvm::make_unique<CommentInfo>()); 171 BlankLine->Children.back()->Kind = "TextComment"; 172 173 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 174 CommentInfo *Brief = Top.Children.back().get(); 175 Brief->Kind = "ParagraphComment"; 176 Brief->Children.emplace_back(llvm::make_unique<CommentInfo>()); 177 Brief->Children.back()->Kind = "TextComment"; 178 Brief->Children.back()->Name = "ParagraphComment"; 179 Brief->Children.back()->Text = " Brief description."; 180 181 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 182 CommentInfo *Extended = Top.Children.back().get(); 183 Extended->Kind = "ParagraphComment"; 184 Extended->Children.emplace_back(llvm::make_unique<CommentInfo>()); 185 Extended->Children.back()->Kind = "TextComment"; 186 Extended->Children.back()->Text = " Extended description that"; 187 Extended->Children.emplace_back(llvm::make_unique<CommentInfo>()); 188 Extended->Children.back()->Kind = "TextComment"; 189 Extended->Children.back()->Text = " continues onto the next line."; 190 191 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 192 CommentInfo *HTML = Top.Children.back().get(); 193 HTML->Kind = "ParagraphComment"; 194 HTML->Children.emplace_back(llvm::make_unique<CommentInfo>()); 195 HTML->Children.back()->Kind = "TextComment"; 196 HTML->Children.emplace_back(llvm::make_unique<CommentInfo>()); 197 HTML->Children.back()->Kind = "HTMLStartTagComment"; 198 HTML->Children.back()->Name = "ul"; 199 HTML->Children.back()->AttrKeys.emplace_back("class"); 200 HTML->Children.back()->AttrValues.emplace_back("test"); 201 HTML->Children.emplace_back(llvm::make_unique<CommentInfo>()); 202 HTML->Children.back()->Kind = "HTMLStartTagComment"; 203 HTML->Children.back()->Name = "li"; 204 HTML->Children.emplace_back(llvm::make_unique<CommentInfo>()); 205 HTML->Children.back()->Kind = "TextComment"; 206 HTML->Children.back()->Text = " Testing."; 207 HTML->Children.emplace_back(llvm::make_unique<CommentInfo>()); 208 HTML->Children.back()->Kind = "HTMLEndTagComment"; 209 HTML->Children.back()->Name = "ul"; 210 HTML->Children.back()->SelfClosing = true; 211 212 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 213 CommentInfo *Verbatim = Top.Children.back().get(); 214 Verbatim->Kind = "VerbatimBlockComment"; 215 Verbatim->Name = "verbatim"; 216 Verbatim->CloseName = "endverbatim"; 217 Verbatim->Children.emplace_back(llvm::make_unique<CommentInfo>()); 218 Verbatim->Children.back()->Kind = "VerbatimBlockLineComment"; 219 Verbatim->Children.back()->Text = " The description continues."; 220 221 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 222 CommentInfo *ParamOut = Top.Children.back().get(); 223 ParamOut->Kind = "ParamCommandComment"; 224 ParamOut->Direction = "[out]"; 225 ParamOut->ParamName = "I"; 226 ParamOut->Explicit = true; 227 ParamOut->Children.emplace_back(llvm::make_unique<CommentInfo>()); 228 ParamOut->Children.back()->Kind = "ParagraphComment"; 229 ParamOut->Children.back()->Children.emplace_back( 230 llvm::make_unique<CommentInfo>()); 231 ParamOut->Children.back()->Children.back()->Kind = "TextComment"; 232 ParamOut->Children.back()->Children.emplace_back( 233 llvm::make_unique<CommentInfo>()); 234 ParamOut->Children.back()->Children.back()->Kind = "TextComment"; 235 ParamOut->Children.back()->Children.back()->Text = " is a parameter."; 236 237 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 238 CommentInfo *ParamIn = Top.Children.back().get(); 239 ParamIn->Kind = "ParamCommandComment"; 240 ParamIn->Direction = "[in]"; 241 ParamIn->ParamName = "J"; 242 ParamIn->Children.emplace_back(llvm::make_unique<CommentInfo>()); 243 ParamIn->Children.back()->Kind = "ParagraphComment"; 244 ParamIn->Children.back()->Children.emplace_back( 245 llvm::make_unique<CommentInfo>()); 246 ParamIn->Children.back()->Children.back()->Kind = "TextComment"; 247 ParamIn->Children.back()->Children.back()->Text = " is a parameter."; 248 ParamIn->Children.back()->Children.emplace_back( 249 llvm::make_unique<CommentInfo>()); 250 ParamIn->Children.back()->Children.back()->Kind = "TextComment"; 251 252 Top.Children.emplace_back(llvm::make_unique<CommentInfo>()); 253 CommentInfo *Return = Top.Children.back().get(); 254 Return->Kind = "BlockCommandComment"; 255 Return->Name = "return"; 256 Return->Explicit = true; 257 Return->Children.emplace_back(llvm::make_unique<CommentInfo>()); 258 Return->Children.back()->Kind = "ParagraphComment"; 259 Return->Children.back()->Children.emplace_back( 260 llvm::make_unique<CommentInfo>()); 261 Return->Children.back()->Children.back()->Kind = "TextComment"; 262 Return->Children.back()->Children.back()->Text = "void"; 263 264 F.Description.emplace_back(std::move(Top)); 265 266 std::string WriteResult = writeInfo(&F); 267 EXPECT_TRUE(WriteResult.size() > 0); 268 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 269 270 CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0].get())); 271 } 272 273 } // namespace doc 274 } // namespace clang 275