https://github.com/evelez7 created https://github.com/llvm/llvm-project/pull/149588
None >From 25f5252a6316a166a2b1e84dd385386638fe3ba1 Mon Sep 17 00:00:00 2001 From: Erick Velez <erickvel...@gmail.com> Date: Fri, 18 Jul 2025 13:58:14 -0700 Subject: [PATCH] [clang-doc] refactor JSON for better Mustache compatibility --- clang-tools-extra/clang-doc/BitcodeReader.cpp | 2 + clang-tools-extra/clang-doc/BitcodeWriter.cpp | 4 +- clang-tools-extra/clang-doc/BitcodeWriter.h | 1 + clang-tools-extra/clang-doc/JSONGenerator.cpp | 59 +++++++++++++++---- .../clang-doc/Representation.cpp | 2 + clang-tools-extra/clang-doc/Representation.h | 10 ++++ clang-tools-extra/clang-doc/Serialize.cpp | 8 ++- .../test/clang-doc/json/class-requires.cpp | 1 + .../test/clang-doc/json/class-template.cpp | 1 + .../test/clang-doc/json/class.cpp | 18 ++++++ .../clang-doc/json/compound-constraints.cpp | 4 ++ .../test/clang-doc/json/concept.cpp | 2 + .../test/clang-doc/json/function-requires.cpp | 7 +++ .../test/clang-doc/json/method-template.cpp | 2 + .../test/clang-doc/json/namespace.cpp | 17 ++++++ .../test/clang-doc/json/nested-namespace.cpp | 4 ++ .../unittests/clang-doc/JSONGeneratorTest.cpp | 25 ++++++++ 17 files changed, 154 insertions(+), 13 deletions(-) diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp index dce34a8434ff8..4efbbd34730cf 100644 --- a/clang-tools-extra/clang-doc/BitcodeReader.cpp +++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp @@ -384,6 +384,8 @@ static llvm::Error parseRecord(const Record &R, unsigned ID, return decodeRecord(R, I->Path, Blob); case REFERENCE_FIELD: return decodeRecord(R, F, Blob); + case REFERENCE_FILE: + return decodeRecord(R, I->DocumentationFileName, Blob); default: return llvm::createStringError(llvm::inconvertibleErrorCode(), "invalid field for Reference"); diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp index eed23726e17bf..e23511bf63690 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp +++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp @@ -210,6 +210,7 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> {REFERENCE_TYPE, {"RefType", &genIntAbbrev}}, {REFERENCE_PATH, {"Path", &genStringAbbrev}}, {REFERENCE_FIELD, {"Field", &genIntAbbrev}}, + {REFERENCE_FILE, {"File", &genStringAbbrev}}, {TEMPLATE_PARAM_CONTENTS, {"Contents", &genStringAbbrev}}, {TEMPLATE_SPECIALIZATION_OF, {"SpecializationOf", &genSymbolIdAbbrev}}, @@ -286,7 +287,7 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>> // Reference Block {BI_REFERENCE_BLOCK_ID, {REFERENCE_USR, REFERENCE_NAME, REFERENCE_QUAL_NAME, REFERENCE_TYPE, - REFERENCE_PATH, REFERENCE_FIELD}}, + REFERENCE_PATH, REFERENCE_FIELD, REFERENCE_FILE}}, // Template Blocks. {BI_TEMPLATE_BLOCK_ID, {}}, {BI_TEMPLATE_PARAM_BLOCK_ID, {TEMPLATE_PARAM_CONTENTS}}, @@ -479,6 +480,7 @@ void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) { emitRecord((unsigned)R.RefType, REFERENCE_TYPE); emitRecord(R.Path, REFERENCE_PATH); emitRecord((unsigned)Field, REFERENCE_FIELD); + emitRecord(R.DocumentationFileName, REFERENCE_FILE); } void ClangDocBitcodeWriter::emitBlock(const FriendInfo &R) { diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.h b/clang-tools-extra/clang-doc/BitcodeWriter.h index 501af12582a8e..688f886b45308 100644 --- a/clang-tools-extra/clang-doc/BitcodeWriter.h +++ b/clang-tools-extra/clang-doc/BitcodeWriter.h @@ -140,6 +140,7 @@ enum RecordId { REFERENCE_TYPE, REFERENCE_PATH, REFERENCE_FIELD, + REFERENCE_FILE, TEMPLATE_PARAM_CONTENTS, TEMPLATE_SPECIALIZATION_OF, TYPEDEF_USR, diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp index cc4c68346ec53..908e23d24d079 100644 --- a/clang-tools-extra/clang-doc/JSONGenerator.cpp +++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp @@ -43,6 +43,30 @@ static auto SerializeReferenceLambda = [](const auto &Ref, Object &Object) { serializeReference(Ref, Object); }; +static std::string infoTypeToString(InfoType IT) { + switch (IT) { + case InfoType::IT_default: + return "default"; + case InfoType::IT_namespace: + return "namespace"; + case InfoType::IT_record: + return "record"; + case InfoType::IT_function: + return "function"; + case InfoType::IT_enum: + return "enum"; + case InfoType::IT_typedef: + return "typedef"; + case InfoType::IT_concept: + return "concept"; + case InfoType::IT_variable: + return "variable"; + case InfoType::IT_friend: + return "friend"; + } + llvm_unreachable("Unknown InfoType encountered."); +} + static json::Object serializeLocation(const Location &Loc, const std::optional<StringRef> RepositoryUrl) { @@ -172,6 +196,9 @@ serializeCommonAttributes(const Info &I, json::Object &Obj, const std::optional<StringRef> RepositoryUrl) { Obj["Name"] = I.Name; Obj["USR"] = toHex(toStringRef(I.USR)); + Obj["InfoType"] = infoTypeToString(I.IT); + if (!I.DocumentationFileName.empty()) + Obj["DocumentationFileName"] = I.DocumentationFileName; if (!I.Path.empty()) Obj["Path"] = I.Path; @@ -205,6 +232,8 @@ static void serializeReference(const Reference &Ref, Object &ReferenceObj) { ReferenceObj["Name"] = Ref.Name; ReferenceObj["QualName"] = Ref.QualName; ReferenceObj["USR"] = toHex(toStringRef(Ref.USR)); + if (!Ref.DocumentationFileName.empty()) + ReferenceObj["DocumentationFileName"] = Ref.DocumentationFileName; } // Although namespaces and records both have ScopeChildren, they serialize them @@ -217,14 +246,18 @@ serializeCommonChildren(const ScopeChildren &Children, json::Object &Obj, serializeInfo(Info, Object, RepositoryUrl); }; - if (!Children.Enums.empty()) + if (!Children.Enums.empty()) { serializeArray(Children.Enums, Obj, "Enums", SerializeInfo); + Obj["HasEnums"] = true; + } if (!Children.Typedefs.empty()) serializeArray(Children.Typedefs, Obj, "Typedefs", SerializeInfo); - if (!Children.Records.empty()) + if (!Children.Records.empty()) { serializeArray(Children.Records, Obj, "Records", SerializeReferenceLambda); + Obj["HasRecords"] = true; + } } template <typename Container, typename SerializationFunc> @@ -234,10 +267,12 @@ static void serializeArray(const Container &Records, Object &Obj, json::Value RecordsArray = Array(); auto &RecordsArrayRef = *RecordsArray.getAsArray(); RecordsArrayRef.reserve(Records.size()); - for (const auto &Item : Records) { + for (size_t Index = 0; Index < Records.size(); ++Index) { json::Value ItemVal = Object(); auto &ItemObj = *ItemVal.getAsObject(); - SerializeInfo(Item, ItemObj); + SerializeInfo(Records[Index], ItemObj); + if (Index == Records.size() - 1) + ItemObj["End"] = true; RecordsArrayRef.push_back(ItemVal); } Obj[Key] = RecordsArray; @@ -405,8 +440,10 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj, ProtFunctionsArrayRef.push_back(FunctionVal); } - if (!PubFunctionsArrayRef.empty()) + if (!PubFunctionsArrayRef.empty()) { Obj["PublicFunctions"] = PubFunctionsArray; + Obj["HasPublicFunctions"] = true; + } if (!ProtFunctionsArrayRef.empty()) Obj["ProtectedFunctions"] = ProtFunctionsArray; } @@ -429,8 +466,10 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj, ProtMembersArrayRef.push_back(MemberVal); } - if (!PubMembersArrayRef.empty()) + if (!PubMembersArrayRef.empty()) { Obj["PublicMembers"] = PublicMembersArray; + Obj["HasPublicMembers"] = true; + } if (!ProtMembersArrayRef.empty()) Obj["ProtectedMembers"] = ProtectedMembersArray; } @@ -496,10 +535,7 @@ static SmallString<16> determineFileName(Info *I, SmallString<128> &Path) { SmallString<16> FileName; if (I->IT == InfoType::IT_record) { auto *RecordSymbolInfo = static_cast<SymbolInfo *>(I); - if (RecordSymbolInfo->MangledName.size() < 255) - FileName = RecordSymbolInfo->MangledName; - else - FileName = toStringRef(toHex(RecordSymbolInfo->USR)); + FileName = RecordSymbolInfo->MangledName; } else if (I->IT == InfoType::IT_namespace && I->Name != "") // Serialize the global namespace as index.json FileName = I->Name; @@ -527,7 +563,10 @@ Error JSONGenerator::generateDocs( } SmallString<16> FileName = determineFileName(Info, Path); + if (FileToInfos.contains(Path)) + continue; FileToInfos[Path].push_back(Info); + Info->DocumentationFileName = FileName; } for (const auto &Group : FileToInfos) { diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp index beaf314a04ae1..79850e1f90253 100644 --- a/clang-tools-extra/clang-doc/Representation.cpp +++ b/clang-tools-extra/clang-doc/Representation.cpp @@ -247,6 +247,8 @@ void Reference::merge(Reference &&Other) { Name = Other.Name; if (Path.empty()) Path = Other.Path; + if (DocumentationFileName.empty()) + DocumentationFileName = Other.DocumentationFileName; } bool FriendInfo::mergeable(const FriendInfo &Other) { diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h index 23f0e90daa27f..2a75f89696b7d 100644 --- a/clang-tools-extra/clang-doc/Representation.h +++ b/clang-tools-extra/clang-doc/Representation.h @@ -121,6 +121,10 @@ struct Reference { Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName, StringRef Path = StringRef()) : USR(USR), Name(Name), QualName(QualName), RefType(IT), Path(Path) {} + Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName, + StringRef Path, SmallString<16> DocumentationFileName) + : USR(USR), Name(Name), QualName(QualName), RefType(IT), Path(Path), + DocumentationFileName(DocumentationFileName) {} bool operator==(const Reference &Other) const { return std::tie(USR, Name, QualName, RefType) == @@ -155,6 +159,7 @@ struct Reference { // Path of directory where the clang-doc generated file will be saved // (possibly unresolved) llvm::SmallString<128> Path; + SmallString<16> DocumentationFileName; }; // Holds the children of a record or namespace. @@ -331,6 +336,11 @@ struct Info { llvm::SmallString<128> Path; // Path of directory where the clang-doc // generated file will be saved + // The name used for the file that this info is documented in. + // In the JSON generator, infos are documented in files with mangled names. + // Thus, we keep track of the physical filename for linking purposes. + SmallString<16> DocumentationFileName; + void mergeBase(Info &&I); bool mergeable(const Info &Other); diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 7a0e00c6d9c2d..3e0e54bf53419 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -495,7 +495,8 @@ static void InsertChild(ScopeChildren &Scope, const NamespaceInfo &Info) { static void InsertChild(ScopeChildren &Scope, const RecordInfo &Info) { Scope.Records.emplace_back(Info.USR, Info.Name, InfoType::IT_record, - Info.Name, getInfoRelativePath(Info.Namespace)); + Info.Name, getInfoRelativePath(Info.Namespace), + Info.MangledName); } static void InsertChild(ScopeChildren &Scope, EnumInfo Info) { @@ -777,7 +778,10 @@ static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C, Mangler->mangleCXXVTable(CXXD, MangledStream); else MangledStream << D->getNameAsString(); - I.MangledName = MangledName; + if (MangledName.size() > 255) + I.MangledName = llvm::toStringRef(llvm::toHex(I.USR)); + else + I.MangledName = MangledName; delete Mangler; } diff --git a/clang-tools-extra/test/clang-doc/json/class-requires.cpp b/clang-tools-extra/test/clang-doc/json/class-requires.cpp index 213da93a1adfa..bf6c889849a70 100644 --- a/clang-tools-extra/test/clang-doc/json/class-requires.cpp +++ b/clang-tools-extra/test/clang-doc/json/class-requires.cpp @@ -20,6 +20,7 @@ struct MyClass; // CHECK-NEXT: "Template": { // CHECK-NEXT: "Constraints": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Expression": "Addable<T>", // CHECK-NEXT: "Name": "Addable", // CHECK-NEXT: "Path": "", diff --git a/clang-tools-extra/test/clang-doc/json/class-template.cpp b/clang-tools-extra/test/clang-doc/json/class-template.cpp index 6cdc3e9175278..149248c772055 100644 --- a/clang-tools-extra/test/clang-doc/json/class-template.cpp +++ b/clang-tools-extra/test/clang-doc/json/class-template.cpp @@ -11,6 +11,7 @@ template<typename T> struct MyClass { // CHECK: "Name": "method", // CHECK: "Params": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "Param", // CHECK-NEXT: "Type": "T" // CHECK-NEXT: } diff --git a/clang-tools-extra/test/clang-doc/json/class.cpp b/clang-tools-extra/test/clang-doc/json/class.cpp index d8317eafea91a..a36358982b019 100644 --- a/clang-tools-extra/test/clang-doc/json/class.cpp +++ b/clang-tools-extra/test/clang-doc/json/class.cpp @@ -60,8 +60,11 @@ struct MyClass { // CHECK-NEXT: "TextComment": " This is a brief description." // CHECK-NEXT: } // CHECK: "Command": "brief" +// CHECK: "DocumentationFileName": "_ZTV7MyClass", // CHECK: "Enums": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "InfoType": "enum", // CHECK-NEXT: "Location": { // CHECK-NEXT: "Filename": "{{.*}}class.cpp", // CHECK-NEXT: "LineNumber": 17 @@ -76,6 +79,7 @@ struct MyClass { // CHECK-NEXT: "Value": "1" // CHECK-NEXT: }, // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "BLUE", // CHECK-NEXT: "ValueExpr": "5" // CHECK-NEXT: } @@ -94,6 +98,7 @@ struct MyClass { // CHECK-NEXT: "IsClass": false, // CHECK-NEXT: "Params": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "", // CHECK-NEXT: "Type": "int" // CHECK-NEXT: } @@ -118,6 +123,7 @@ struct MyClass { // CHECK-NEXT: } // CHECK-NEXT: }, // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "IsClass": true, // CHECK-NEXT: "Reference": { // CHECK-NEXT: "Name": "Foo", @@ -129,6 +135,11 @@ struct MyClass { // CHECK-NEXT: ], // COM: FIXME: FullName is not emitted correctly. // CHECK-NEXT: "FullName": "", +// CHECK-NEXT: "HasEnums": true, +// CHECK-NEXT: "HasPublicFunctions": true, +// CHECK-NEXT: "HasPublicMembers": true, +// CHECK-NEXT: "HasRecords": true, +// CHECK-NEXT: "InfoType": "record", // CHECK-NEXT: "IsTypedef": false, // CHECK-NEXT: "Location": { // CHECK-NEXT: "Filename": "{{.*}}class.cpp", @@ -142,6 +153,7 @@ struct MyClass { // CHECK-NEXT: "Path": "GlobalNamespace", // CHECK-NEXT: "ProtectedFunctions": [ // CHECK-NEXT: { +// CHECK-NEXT: "InfoType": "function", // CHECK-NEXT: "IsStatic": false, // CHECK-NEXT: "Name": "protectedMethod", // CHECK-NEXT: "Namespace": [ @@ -166,6 +178,7 @@ struct MyClass { // CHECK-NEXT: ], // CHECK-NEXT: "PublicFunctions": [ // CHECK-NEXT: { +// CHECK-NEXT: "InfoType": "function", // CHECK-NEXT: "IsStatic": false, // CHECK-NEXT: "Name": "myMethod", // CHECK-NEXT: "Namespace": [ @@ -174,6 +187,7 @@ struct MyClass { // CHECK-NEXT: ], // CHECK-NEXT: "Params": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "MyParam", // CHECK-NEXT: "Type": "int" // CHECK-NEXT: } @@ -204,6 +218,8 @@ struct MyClass { // CHECK-NEXT: ], // CHECK-NEXT: "Records": [ // CHECK-NEXT: { +// CHECK-NEXT: "DocumentationFileName": "_ZTVN7MyClass11NestedClassE", +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "NestedClass", // CHECK-NEXT: "Path": "GlobalNamespace{{[\/]+}}MyClass", // CHECK-NEXT: "QualName": "NestedClass", @@ -213,6 +229,8 @@ struct MyClass { // CHECK-NEXT: "TagType": "struct", // CHECK-NEXT: "Typedefs": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "InfoType": "typedef", // CHECK-NEXT: "IsUsing": false, // CHECK-NEXT: "Location": { // CHECK-NEXT: "Filename": "{{.*}}class.cpp", diff --git a/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp b/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp index 34acb6808409d..bb2b4ca770fc0 100644 --- a/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp +++ b/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp @@ -37,6 +37,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" // CHECK-NEXT: }, // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Expression": "Decrementable<T>", // CHECK-NEXT: "Name": "Decrementable", // CHECK-NEXT: "Path": "", @@ -55,6 +56,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" // CHECK-NEXT: }, // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Expression": "Decrementable<T>", // CHECK-NEXT: "Name": "Decrementable", // CHECK-NEXT: "Path": "", @@ -87,6 +89,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" // CHECK-NEXT: }, // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Expression": "PreDecrementable<T>", // CHECK-NEXT: "Name": "PreDecrementable", // CHECK-NEXT: "Path": "", @@ -112,6 +115,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" // CHECK-NEXT: }, // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Expression": "PreIncrementable<T>", // CHECK-NEXT: "Name": "PreIncrementable", // CHECK-NEXT: "Path": "", diff --git a/clang-tools-extra/test/clang-doc/json/concept.cpp b/clang-tools-extra/test/clang-doc/json/concept.cpp index b946393274c85..766415bbbeecd 100644 --- a/clang-tools-extra/test/clang-doc/json/concept.cpp +++ b/clang-tools-extra/test/clang-doc/json/concept.cpp @@ -23,6 +23,8 @@ concept Incrementable = requires(T x) { // CHECK-NEXT: { // CHECK-NEXT: "TextComment": " Requires that T suports post and pre-incrementing." // CHECK: ], +// CHECK: "End": true, +// CHECK-NEXT: "InfoType": "concept", // CHECK-NEXT: "IsType": true, // CHECK-NEXT: "Name": "Incrementable", // CHECK-NEXT: "Template": { diff --git a/clang-tools-extra/test/clang-doc/json/function-requires.cpp b/clang-tools-extra/test/clang-doc/json/function-requires.cpp index 08ac4c7ed2ca3..59ed39ee61fda 100644 --- a/clang-tools-extra/test/clang-doc/json/function-requires.cpp +++ b/clang-tools-extra/test/clang-doc/json/function-requires.cpp @@ -14,10 +14,12 @@ template<Incrementable T> Incrementable auto incrementTwo(T t); // CHECK: "Functions": [ // CHECK-NEXT: { +// CHECK-NEXT: "InfoType": "function", // CHECK-NEXT: "IsStatic": false, // CHECK-NEXT: "Name": "increment", // CHECK-NEXT: "Params": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "t", // CHECK-NEXT: "Type": "T" // CHECK-NEXT: } @@ -32,6 +34,7 @@ template<Incrementable T> Incrementable auto incrementTwo(T t); // CHECK-NEXT: "Template": { // CHECK-NEXT: "Constraints": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Expression": "Incrementable<T>", // CHECK-NEXT: "Name": "Incrementable", // CHECK-NEXT: "Path": "", @@ -46,10 +49,13 @@ template<Incrementable T> Incrementable auto incrementTwo(T t); // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" // CHECK-NEXT: }, // CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "InfoType": "function", // CHECK-NEXT: "IsStatic": false, // CHECK-NEXT: "Name": "incrementTwo", // CHECK-NEXT: "Params": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "t", // CHECK-NEXT: "Type": "T" // CHECK-NEXT: } @@ -64,6 +70,7 @@ template<Incrementable T> Incrementable auto incrementTwo(T t); // CHECK-NEXT: "Template": { // CHECK-NEXT: "Constraints": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Expression": "Incrementable<T>", // CHECK-NEXT: "Name": "Incrementable", // CHECK-NEXT: "Path": "", diff --git a/clang-tools-extra/test/clang-doc/json/method-template.cpp b/clang-tools-extra/test/clang-doc/json/method-template.cpp index ac8450a72d3a7..14232d00e277a 100644 --- a/clang-tools-extra/test/clang-doc/json/method-template.cpp +++ b/clang-tools-extra/test/clang-doc/json/method-template.cpp @@ -9,6 +9,7 @@ struct MyClass { // CHECK: "PublicFunctions": [ // CHECK-NEXT: { +// CHECK-NEXT: "InfoType": "function", // CHECK-NEXT: "IsStatic": false, // CHECK-NEXT: "Location": { // CHECK-NEXT: "Filename": "{{.*}}method-template.cpp", @@ -21,6 +22,7 @@ struct MyClass { // CHECK-NEXT: ], // CHECK-NEXT: "Params": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "param", // CHECK-NEXT: "Type": "T" // CHECK-NEXT: } diff --git a/clang-tools-extra/test/clang-doc/json/namespace.cpp b/clang-tools-extra/test/clang-doc/json/namespace.cpp index 779d7b49f5581..4b6b38869f714 100644 --- a/clang-tools-extra/test/clang-doc/json/namespace.cpp +++ b/clang-tools-extra/test/clang-doc/json/namespace.cpp @@ -20,8 +20,11 @@ enum Color { typedef int MyTypedef; // CHECK: { +// CHECK-NEXT: "DocumentationFileName": "index", // CHECK-NEXT: "Enums": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "InfoType": "enum", // CHECK-NEXT: "Location": { // CHECK-NEXT: "Filename": "{{.*}}namespace.cpp", // CHECK-NEXT: "LineNumber": 14 @@ -36,6 +39,7 @@ typedef int MyTypedef; // CHECK-NEXT: "Value": "1" // CHECK-NEXT: }, // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "BLUE", // CHECK-NEXT: "ValueExpr": "5" // CHECK-NEXT: } @@ -47,10 +51,13 @@ typedef int MyTypedef; // CHECK-NEXT: ], // CHECK-NEXT: "Functions": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "InfoType": "function", // CHECK-NEXT: "IsStatic": false, // CHECK-NEXT: "Name": "myFunction", // CHECK-NEXT: "Params": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "Param", // CHECK-NEXT: "Type": "int" // CHECK-NEXT: } @@ -65,9 +72,13 @@ typedef int MyTypedef; // CHECK-NEXT: "USR": "{{[0-9A-F]*}}" // CHECK-NEXT: } // CHECK-NEXT: ], +// CHECK-NEXT: "HasEnums": true, +// CHECK-NEXT: "HasRecords": true, +// CHECK-NEXT: "InfoType": "namespace", // CHECK-NEXT: "Name": "", // CHECK-NEXT: "Namespaces": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "NestedNamespace", // CHECK-NEXT: "Path": "", // CHECK-NEXT: "QualName": "NestedNamespace", @@ -76,6 +87,8 @@ typedef int MyTypedef; // CHECK-NEXT: ], // CHECK-NEXT: "Records": [ // CHECK-NEXT: { +// CHECK-NEXT: "DocumentationFileName": "_ZTV7MyClass", +// CHECK-NEXT: "End": true, // CHECK-NEXT: "Name": "MyClass", // CHECK-NEXT: "Path": "GlobalNamespace", // CHECK-NEXT: "QualName": "MyClass", @@ -84,6 +97,8 @@ typedef int MyTypedef; // CHECK-NEXT: ], // CHECK-NEXT: "Typedefs": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "InfoType": "typedef", // CHECK-NEXT: "IsUsing": false, // CHECK-NEXT: "Location": { // CHECK-NEXT: "Filename": "{{.*}}namespace.cpp", @@ -104,6 +119,8 @@ typedef int MyTypedef; // CHECK-NEXT: "USR": "0000000000000000000000000000000000000000" // CHECK-NEXT: "Variables": [ // CHECK-NEXT: { +// CHECK-NEXT: "End": true, +// CHECK-NEXT: "InfoType": "variable", // CHECK-NEXT: "IsStatic": true, // CHECK-NEXT: "Location": { // CHECK-NEXT: "Filename": "{{.*}}namespace.cpp", diff --git a/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp b/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp index 54f95c4d041ca..255e540bd6c7c 100644 --- a/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp +++ b/clang-tools-extra/test/clang-doc/json/nested-namespace.cpp @@ -12,6 +12,8 @@ namespace nested { // NESTED: "Variables": [ // NESTED-NEXT: { +// NESTED-NEXT: "End": true, +// NESTED-NEXT: "InfoType": "variable", // NESTED-NEXT: "IsStatic": false, // NESTED-NEXT: "Location": { // NESTED-NEXT: "Filename": "{{.*}}nested-namespace.cpp", @@ -24,6 +26,8 @@ namespace nested { // INNER: "Variables": [ // INNER-NEXT: { +// INNER-NEXT: "End": true, +// INNER-NEXT: "InfoType": "variable", // INNER-NEXT: "IsStatic": false, // INNER-NEXT: "Location": { // INNER-NEXT: "Filename": "{{.*}}nested-namespace.cpp", diff --git a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp index 5927235b3bd93..07c761fcd0685 100644 --- a/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp +++ b/clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp @@ -63,7 +63,11 @@ TEST(JSONGeneratorTest, emitRecordJSON) { "Bases": [ { "Access": "public", + "End": true, "FullName": "", + "HasPublicFunctions": true, + "HasPublicMembers": true, + "InfoType": "record", "IsParent": true, "IsTypedef": false, "IsVirtual": true, @@ -72,6 +76,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) { "Path": "path/to/F", "PublicFunctions": [ { + "InfoType": "function", "IsStatic": false, "Name": "InheritedFunctionOne", "ReturnType": { @@ -96,8 +101,11 @@ TEST(JSONGeneratorTest, emitRecordJSON) { ], "Enums": [ { + "End": true, + "InfoType": "enum", "Members": [ { + "End": true, "Name": "RED", "Value": "0" } @@ -108,6 +116,10 @@ TEST(JSONGeneratorTest, emitRecordJSON) { } ], "FullName": "", + "HasEnums": true, + "HasPublicFunctions": true, + "HasRecords": true, + "InfoType": "record", "IsTypedef": false, "Location": { "Filename": "main.cpp", @@ -120,6 +132,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) { ], "Parents": [ { + "End": true, "Name": "F", "Path": "", "QualName": "", @@ -135,6 +148,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) { ], "PublicFunctions": [ { + "InfoType": "function", "IsStatic": false, "Name": "OneFunction", "ReturnType": { @@ -149,6 +163,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) { ], "Records": [ { + "End": true, "Name": "ChildStruct", "Path": "path/to/A/r", "QualName": "path::to::A::r::ChildStruct", @@ -164,6 +179,7 @@ TEST(JSONGeneratorTest, emitRecordJSON) { "USR": "0000000000000000000000000000000000000000", "VirtualParents": [ { + "End": true, "Name": "G", "Path": "path/to/G", "QualName": "path::to::G::G", @@ -201,6 +217,8 @@ TEST(JSONGeneratorTest, emitNamespaceJSON) { std::string Expected = R"raw({ "Enums": [ { + "End": true, + "InfoType": "enum", "Name": "OneEnum", "Scoped": false, "USR": "0000000000000000000000000000000000000000" @@ -208,6 +226,8 @@ TEST(JSONGeneratorTest, emitNamespaceJSON) { ], "Functions": [ { + "End": true, + "InfoType": "function", "IsStatic": false, "Name": "OneFunction", "ReturnType": { @@ -220,12 +240,16 @@ TEST(JSONGeneratorTest, emitNamespaceJSON) { "USR": "0000000000000000000000000000000000000000" } ], + "HasEnums": true, + "HasRecords": true, + "InfoType": "namespace", "Name": "Namespace", "Namespace": [ "A" ], "Namespaces": [ { + "End": true, "Name": "ChildNamespace", "Path": "path/to/A/Namespace", "QualName": "path::to::A::Namespace::ChildNamespace", @@ -235,6 +259,7 @@ TEST(JSONGeneratorTest, emitNamespaceJSON) { "Path": "path/to/A", "Records": [ { + "End": true, "Name": "ChildStruct", "Path": "path/to/A/Namespace", "QualName": "path::to::A::Namespace::ChildStruct", _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits