1 //===-- clang-doc/BitcodeTest.cpp -----------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "BitcodeReader.h" 11 #include "BitcodeWriter.h" 12 #include "ClangDocTest.h" 13 #include "Representation.h" 14 #include "llvm/Bitcode/BitstreamReader.h" 15 #include "llvm/Bitcode/BitstreamWriter.h" 16 #include "gtest/gtest.h" 17 18 namespace clang { 19 namespace doc { 20 21 template <typename T> static std::string writeInfo(T &I) { 22 SmallString<2048> Buffer; 23 llvm::BitstreamWriter Stream(Buffer); 24 ClangDocBitcodeWriter Writer(Stream); 25 Writer.emitBlock(I); 26 return Buffer.str().str(); 27 } 28 29 std::string writeInfo(Info *I) { 30 switch (I->IT) { 31 case InfoType::IT_namespace: 32 return writeInfo(*static_cast<NamespaceInfo *>(I)); 33 case InfoType::IT_record: 34 return writeInfo(*static_cast<RecordInfo *>(I)); 35 case InfoType::IT_enum: 36 return writeInfo(*static_cast<EnumInfo *>(I)); 37 case InfoType::IT_function: 38 return writeInfo(*static_cast<FunctionInfo *>(I)); 39 default: 40 return ""; 41 } 42 } 43 44 std::vector<std::unique_ptr<Info>> readInfo(StringRef Bitcode, 45 size_t NumInfos) { 46 llvm::BitstreamCursor Stream(Bitcode); 47 doc::ClangDocBitcodeReader Reader(Stream); 48 auto Infos = Reader.readBitcode(); 49 50 // Check that there was no error in the read. 51 assert(Infos); 52 EXPECT_EQ(Infos.get().size(), NumInfos); 53 return std::move(Infos.get()); 54 } 55 56 TEST(BitcodeTest, emitNamespaceInfoBitcode) { 57 NamespaceInfo I; 58 I.Name = "r"; 59 I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); 60 61 I.ChildNamespaces.emplace_back(EmptySID, "ChildNamespace", 62 InfoType::IT_namespace); 63 I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record); 64 I.ChildFunctions.emplace_back(); 65 I.ChildEnums.emplace_back(); 66 67 std::string WriteResult = writeInfo(&I); 68 EXPECT_TRUE(WriteResult.size() > 0); 69 std::vector<std::unique_ptr<Info>> ReadResults = readInfo(WriteResult, 1); 70 71 CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0].get())); 72 } 73 74 TEST(BitcodeTest, emitRecordInfoBitcode) { 75 RecordInfo I; 76 I.Name = "r"; 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", AccessSpecifier::AS_private); 83 I.TagType = TagTypeKind::TTK_Class; 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