| 1 | #include "ClangDocTest.h" |
| 2 | #include "Generators.h" |
| 3 | #include "Representation.h" |
| 4 | #include "gtest/gtest.h" |
| 5 | |
| 6 | namespace clang { |
| 7 | namespace doc { |
| 8 | |
| 9 | static std::unique_ptr<Generator> getJSONGenerator() { |
| 10 | auto G = doc::findGeneratorByName(Format: "json" ); |
| 11 | if (!G) |
| 12 | return nullptr; |
| 13 | return std::move(G.get()); |
| 14 | } |
| 15 | |
| 16 | TEST(JSONGeneratorTest, emitRecordJSON) { |
| 17 | RecordInfo I; |
| 18 | I.Name = "Foo" ; |
| 19 | // FIXME: FullName is not emitted correctly. |
| 20 | I.FullName = "" ; |
| 21 | I.IsTypeDef = false; |
| 22 | I.Namespace.emplace_back(Args: EmptySID, Args: "GlobalNamespace" , Args: InfoType::IT_namespace); |
| 23 | I.Path = "GlobalNamespace" ; |
| 24 | I.DefLoc = Location(1, 1, "main.cpp" ); |
| 25 | I.TagType = TagTypeKind::Class; |
| 26 | |
| 27 | I.Template = TemplateInfo(); |
| 28 | I.Template->Params.emplace_back(args: "class T" ); |
| 29 | |
| 30 | I.Children.Enums.emplace_back(); |
| 31 | I.Children.Enums.back().Name = "Color" ; |
| 32 | I.Children.Enums.back().Scoped = false; |
| 33 | I.Children.Enums.back().Members.emplace_back(); |
| 34 | I.Children.Enums.back().Members.back().Name = "RED" ; |
| 35 | I.Children.Enums.back().Members.back().Value = "0" ; |
| 36 | |
| 37 | I.Members.emplace_back(Args: TypeInfo("int" ), Args: "X" , Args: AccessSpecifier::AS_protected); |
| 38 | |
| 39 | I.Bases.emplace_back(args: EmptySID, args: "F" , args: "path/to/F" , args: true, |
| 40 | args: AccessSpecifier::AS_public, args: true); |
| 41 | I.Bases.back().Children.Functions.emplace_back(); |
| 42 | I.Bases.back().Children.Functions.back().Name = "InheritedFunctionOne" ; |
| 43 | I.Bases.back().Members.emplace_back(Args: TypeInfo("int" ), Args: "N" , |
| 44 | Args: AccessSpecifier::AS_public); |
| 45 | |
| 46 | // F is in the global namespace |
| 47 | I.Parents.emplace_back(Args: EmptySID, Args: "F" , Args: InfoType::IT_record, Args: "" ); |
| 48 | I.VirtualParents.emplace_back(Args: EmptySID, Args: "G" , Args: InfoType::IT_record, |
| 49 | Args: "path::to::G::G" , Args: "path/to/G" ); |
| 50 | |
| 51 | I.Children.Records.emplace_back(args: EmptySID, args: "ChildStruct" , args: InfoType::IT_record, |
| 52 | args: "path::to::A::r::ChildStruct" , args: "path/to/A/r" ); |
| 53 | I.Children.Functions.emplace_back(); |
| 54 | I.Children.Functions.back().Name = "OneFunction" ; |
| 55 | |
| 56 | auto G = getJSONGenerator(); |
| 57 | assert(G); |
| 58 | std::string Buffer; |
| 59 | llvm::raw_string_ostream Actual(Buffer); |
| 60 | auto Err = G->generateDocForInfo(I: &I, OS&: Actual, CDCtx: ClangDocContext()); |
| 61 | assert(!Err); |
| 62 | std::string Expected = R"raw({ |
| 63 | "Bases": [ |
| 64 | { |
| 65 | "Access": "public", |
| 66 | "FullName": "", |
| 67 | "IsParent": true, |
| 68 | "IsTypedef": false, |
| 69 | "IsVirtual": true, |
| 70 | "Name": "F", |
| 71 | "Path": "path/to/F", |
| 72 | "PublicFunctions": [ |
| 73 | { |
| 74 | "IsStatic": false, |
| 75 | "Name": "InheritedFunctionOne", |
| 76 | "ReturnType": { |
| 77 | "IsBuiltIn": false, |
| 78 | "IsTemplate": false, |
| 79 | "Name": "", |
| 80 | "QualName": "", |
| 81 | "USR": "0000000000000000000000000000000000000000" |
| 82 | }, |
| 83 | "USR": "0000000000000000000000000000000000000000" |
| 84 | } |
| 85 | ], |
| 86 | "PublicMembers": [ |
| 87 | { |
| 88 | "Name": "N", |
| 89 | "Type": "int" |
| 90 | } |
| 91 | ], |
| 92 | "TagType": "struct", |
| 93 | "USR": "0000000000000000000000000000000000000000" |
| 94 | } |
| 95 | ], |
| 96 | "Enums": [ |
| 97 | { |
| 98 | "Members": [ |
| 99 | { |
| 100 | "Name": "RED", |
| 101 | "Value": "0" |
| 102 | } |
| 103 | ], |
| 104 | "Name": "Color", |
| 105 | "Scoped": false, |
| 106 | "USR": "0000000000000000000000000000000000000000" |
| 107 | } |
| 108 | ], |
| 109 | "FullName": "", |
| 110 | "IsTypedef": false, |
| 111 | "Location": { |
| 112 | "Filename": "main.cpp", |
| 113 | "LineNumber": 1 |
| 114 | }, |
| 115 | "Name": "Foo", |
| 116 | "Namespace": [ |
| 117 | "GlobalNamespace" |
| 118 | ], |
| 119 | "Parents": [ |
| 120 | { |
| 121 | "Name": "F", |
| 122 | "Path": "", |
| 123 | "QualName": "", |
| 124 | "USR": "0000000000000000000000000000000000000000" |
| 125 | } |
| 126 | ], |
| 127 | "Path": "GlobalNamespace", |
| 128 | "ProtectedMembers": [ |
| 129 | { |
| 130 | "Name": "X", |
| 131 | "Type": "int" |
| 132 | } |
| 133 | ], |
| 134 | "PublicFunctions": [ |
| 135 | { |
| 136 | "IsStatic": false, |
| 137 | "Name": "OneFunction", |
| 138 | "ReturnType": { |
| 139 | "IsBuiltIn": false, |
| 140 | "IsTemplate": false, |
| 141 | "Name": "", |
| 142 | "QualName": "", |
| 143 | "USR": "0000000000000000000000000000000000000000" |
| 144 | }, |
| 145 | "USR": "0000000000000000000000000000000000000000" |
| 146 | } |
| 147 | ], |
| 148 | "Records": [ |
| 149 | { |
| 150 | "Name": "ChildStruct", |
| 151 | "Path": "path/to/A/r", |
| 152 | "QualName": "path::to::A::r::ChildStruct", |
| 153 | "USR": "0000000000000000000000000000000000000000" |
| 154 | } |
| 155 | ], |
| 156 | "TagType": "class", |
| 157 | "Template": { |
| 158 | "Parameters": [ |
| 159 | "class T" |
| 160 | ] |
| 161 | }, |
| 162 | "USR": "0000000000000000000000000000000000000000", |
| 163 | "VirtualParents": [ |
| 164 | { |
| 165 | "Name": "G", |
| 166 | "Path": "path/to/G", |
| 167 | "QualName": "path::to::G::G", |
| 168 | "USR": "0000000000000000000000000000000000000000" |
| 169 | } |
| 170 | ] |
| 171 | })raw" ; |
| 172 | EXPECT_EQ(Expected, Actual.str()); |
| 173 | } |
| 174 | |
| 175 | TEST(JSONGeneratorTest, emitNamespaceJSON) { |
| 176 | NamespaceInfo I; |
| 177 | I.Name = "Namespace" ; |
| 178 | I.Path = "path/to/A" ; |
| 179 | I.Namespace.emplace_back(Args: EmptySID, Args: "A" , Args: InfoType::IT_namespace); |
| 180 | |
| 181 | I.Children.Namespaces.emplace_back( |
| 182 | args: EmptySID, args: "ChildNamespace" , args: InfoType::IT_namespace, |
| 183 | args: "path::to::A::Namespace::ChildNamespace" , args: "path/to/A/Namespace" ); |
| 184 | I.Children.Records.emplace_back(args: EmptySID, args: "ChildStruct" , args: InfoType::IT_record, |
| 185 | args: "path::to::A::Namespace::ChildStruct" , |
| 186 | args: "path/to/A/Namespace" ); |
| 187 | I.Children.Functions.emplace_back(); |
| 188 | I.Children.Functions.back().Name = "OneFunction" ; |
| 189 | I.Children.Functions.back().Access = AccessSpecifier::AS_none; |
| 190 | I.Children.Enums.emplace_back(); |
| 191 | I.Children.Enums.back().Name = "OneEnum" ; |
| 192 | |
| 193 | auto G = getJSONGenerator(); |
| 194 | assert(G); |
| 195 | std::string Buffer; |
| 196 | llvm::raw_string_ostream Actual(Buffer); |
| 197 | auto Err = G->generateDocForInfo(I: &I, OS&: Actual, CDCtx: ClangDocContext()); |
| 198 | assert(!Err); |
| 199 | std::string Expected = R"raw({ |
| 200 | "Enums": [ |
| 201 | { |
| 202 | "Name": "OneEnum", |
| 203 | "Scoped": false, |
| 204 | "USR": "0000000000000000000000000000000000000000" |
| 205 | } |
| 206 | ], |
| 207 | "Functions": [ |
| 208 | { |
| 209 | "IsStatic": false, |
| 210 | "Name": "OneFunction", |
| 211 | "ReturnType": { |
| 212 | "IsBuiltIn": false, |
| 213 | "IsTemplate": false, |
| 214 | "Name": "", |
| 215 | "QualName": "", |
| 216 | "USR": "0000000000000000000000000000000000000000" |
| 217 | }, |
| 218 | "USR": "0000000000000000000000000000000000000000" |
| 219 | } |
| 220 | ], |
| 221 | "Name": "Namespace", |
| 222 | "Namespace": [ |
| 223 | "A" |
| 224 | ], |
| 225 | "Namespaces": [ |
| 226 | { |
| 227 | "Name": "ChildNamespace", |
| 228 | "Path": "path/to/A/Namespace", |
| 229 | "QualName": "path::to::A::Namespace::ChildNamespace", |
| 230 | "USR": "0000000000000000000000000000000000000000" |
| 231 | } |
| 232 | ], |
| 233 | "Path": "path/to/A", |
| 234 | "Records": [ |
| 235 | { |
| 236 | "Name": "ChildStruct", |
| 237 | "Path": "path/to/A/Namespace", |
| 238 | "QualName": "path::to::A::Namespace::ChildStruct", |
| 239 | "USR": "0000000000000000000000000000000000000000" |
| 240 | } |
| 241 | ], |
| 242 | "USR": "0000000000000000000000000000000000000000" |
| 243 | })raw" ; |
| 244 | EXPECT_EQ(Expected, Actual.str()); |
| 245 | } |
| 246 | } // namespace doc |
| 247 | } // namespace clang |
| 248 | |