diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-18 20:30:12 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-19 21:12:03 +0000 |
| commit | c9157d925c489f07ba9c0b2ce47e5149b75969a5 (patch) | |
| tree | 08bc4a3d9cad3f9ebffa558ddf140b9d9257b219 /contrib/llvm-project/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp | |
| parent | 2a66844f606a35d68ad8a8061f4bea204274b3bc (diff) | |
Diffstat (limited to 'contrib/llvm-project/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp')
| -rw-r--r-- | contrib/llvm-project/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp | 470 |
1 files changed, 445 insertions, 25 deletions
diff --git a/contrib/llvm-project/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/contrib/llvm-project/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 534e9288cc71..53b22297ee0e 100644 --- a/contrib/llvm-project/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/contrib/llvm-project/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -38,6 +38,14 @@ void serializeObject(Object &Paren, StringRef Key, std::optional<Object> Obj) { Paren[Key] = std::move(*Obj); } +/// Helper function to inject a StringRef \p String into an object \p Paren at +/// position \p Key +void serializeString(Object &Paren, StringRef Key, + std::optional<std::string> String) { + if (String) + Paren[Key] = std::move(*String); +} + /// Helper function to inject a JSON array \p Array into object \p Paren at /// position \p Key. void serializeArray(Object &Paren, StringRef Key, std::optional<Array> Array) { @@ -101,8 +109,8 @@ Object serializeSourcePosition(const PresumedLoc &Loc) { assert(Loc.isValid() && "invalid source position"); Object SourcePosition; - SourcePosition["line"] = Loc.getLine(); - SourcePosition["character"] = Loc.getColumn(); + SourcePosition["line"] = Loc.getLine() - 1; + SourcePosition["character"] = Loc.getColumn() - 1; return SourcePosition; } @@ -169,11 +177,11 @@ serializeAvailability(const AvailabilitySet &Availabilities) { if (AvailInfo.Unavailable) Availability["isUnconditionallyUnavailable"] = true; else { - serializeObject(Availability, "introducedVersion", + serializeObject(Availability, "introduced", serializeSemanticVersion(AvailInfo.Introduced)); - serializeObject(Availability, "deprecatedVersion", + serializeObject(Availability, "deprecated", serializeSemanticVersion(AvailInfo.Deprecated)); - serializeObject(Availability, "obsoletedVersion", + serializeObject(Availability, "obsoleted", serializeSemanticVersion(AvailInfo.Obsoleted)); } AvailabilityArray.emplace_back(std::move(Availability)); @@ -189,10 +197,12 @@ StringRef getLanguageName(Language Lang) { return "c"; case Language::ObjC: return "objective-c"; - - // Unsupported language currently case Language::CXX: + return "c++"; case Language::ObjCXX: + return "objective-c++"; + + // Unsupported language currently case Language::OpenCL: case Language::OpenCLCXX: case Language::CUDA: @@ -319,7 +329,13 @@ serializeDeclarationFragments(const DeclarationFragments &DF) { /// Objective-C methods). Can be used as sub-headings for documentation. Object serializeNames(const APIRecord &Record) { Object Names; - Names["title"] = Record.Name; + if (auto *CategoryRecord = + dyn_cast_or_null<const ObjCCategoryRecord>(&Record)) + Names["title"] = + (CategoryRecord->Interface.Name + " (" + Record.Name + ")").str(); + else + Names["title"] = Record.Name; + serializeArray(Names, "subHeading", serializeDeclarationFragments(Record.SubHeading)); DeclarationFragments NavigatorFragments; @@ -342,10 +358,34 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) { case APIRecord::RK_Unknown: llvm_unreachable("Records should have an explicit kind"); break; + case APIRecord::RK_Namespace: + Kind["identifier"] = AddLangPrefix("namespace"); + Kind["displayName"] = "Namespace"; + break; case APIRecord::RK_GlobalFunction: Kind["identifier"] = AddLangPrefix("func"); Kind["displayName"] = "Function"; break; + case APIRecord::RK_GlobalFunctionTemplate: + Kind["identifier"] = AddLangPrefix("func"); + Kind["displayName"] = "Function Template"; + break; + case APIRecord::RK_GlobalFunctionTemplateSpecialization: + Kind["identifier"] = AddLangPrefix("func"); + Kind["displayName"] = "Function Template Specialization"; + break; + case APIRecord::RK_GlobalVariableTemplate: + Kind["identifier"] = AddLangPrefix("var"); + Kind["displayName"] = "Global Variable Template"; + break; + case APIRecord::RK_GlobalVariableTemplateSpecialization: + Kind["identifier"] = AddLangPrefix("var"); + Kind["displayName"] = "Global Variable Template Specialization"; + break; + case APIRecord::RK_GlobalVariableTemplatePartialSpecialization: + Kind["identifier"] = AddLangPrefix("var"); + Kind["displayName"] = "Global Variable Template Partial Specialization"; + break; case APIRecord::RK_GlobalVariable: Kind["identifier"] = AddLangPrefix("var"); Kind["displayName"] = "Global Variable"; @@ -366,6 +406,57 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) { Kind["identifier"] = AddLangPrefix("struct"); Kind["displayName"] = "Structure"; break; + case APIRecord::RK_CXXField: + Kind["identifier"] = AddLangPrefix("property"); + Kind["displayName"] = "Instance Property"; + break; + case APIRecord::RK_Union: + Kind["identifier"] = AddLangPrefix("union"); + Kind["displayName"] = "Union"; + break; + case APIRecord::RK_StaticField: + Kind["identifier"] = AddLangPrefix("type.property"); + Kind["displayName"] = "Type Property"; + break; + case APIRecord::RK_ClassTemplate: + case APIRecord::RK_ClassTemplateSpecialization: + case APIRecord::RK_ClassTemplatePartialSpecialization: + case APIRecord::RK_CXXClass: + Kind["identifier"] = AddLangPrefix("class"); + Kind["displayName"] = "Class"; + break; + case APIRecord::RK_CXXMethodTemplate: + Kind["identifier"] = AddLangPrefix("method"); + Kind["displayName"] = "Method Template"; + break; + case APIRecord::RK_CXXMethodTemplateSpecialization: + Kind["identifier"] = AddLangPrefix("method"); + Kind["displayName"] = "Method Template Specialization"; + break; + case APIRecord::RK_CXXFieldTemplate: + Kind["identifier"] = AddLangPrefix("property"); + Kind["displayName"] = "Template Property"; + break; + case APIRecord::RK_Concept: + Kind["identifier"] = AddLangPrefix("concept"); + Kind["displayName"] = "Concept"; + break; + case APIRecord::RK_CXXStaticMethod: + Kind["identifier"] = AddLangPrefix("type.method"); + Kind["displayName"] = "Static Method"; + break; + case APIRecord::RK_CXXInstanceMethod: + Kind["identifier"] = AddLangPrefix("method"); + Kind["displayName"] = "Instance Method"; + break; + case APIRecord::RK_CXXConstructorMethod: + Kind["identifier"] = AddLangPrefix("method"); + Kind["displayName"] = "Constructor"; + break; + case APIRecord::RK_CXXDestructorMethod: + Kind["identifier"] = AddLangPrefix("method"); + Kind["displayName"] = "Destructor"; + break; case APIRecord::RK_ObjCIvar: Kind["identifier"] = AddLangPrefix("ivar"); Kind["displayName"] = "Instance Variable"; @@ -391,9 +482,12 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) { Kind["displayName"] = "Class"; break; case APIRecord::RK_ObjCCategory: - // We don't serialize out standalone Objective-C category symbols yet. - llvm_unreachable("Serializing standalone Objective-C category symbols is " - "not supported."); + Kind["identifier"] = AddLangPrefix("class.extension"); + Kind["displayName"] = "Class Extension"; + break; + case APIRecord::RK_ObjCCategoryModule: + Kind["identifier"] = AddLangPrefix("module.extension"); + Kind["displayName"] = "Module Extension"; break; case APIRecord::RK_ObjCProtocol: Kind["identifier"] = AddLangPrefix("protocol"); @@ -470,6 +564,77 @@ void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) { Record, has_function_signature<RecordTy>())); } +template <typename RecordTy> +std::optional<std::string> serializeAccessMixinImpl(const RecordTy &Record, + std::true_type) { + const auto &AccessControl = Record.Access; + std::string Access; + if (AccessControl.empty()) + return std::nullopt; + Access = AccessControl.getAccess(); + return Access; +} + +template <typename RecordTy> +std::optional<std::string> serializeAccessMixinImpl(const RecordTy &Record, + std::false_type) { + return std::nullopt; +} + +template <typename RecordTy> +void serializeAccessMixin(Object &Paren, const RecordTy &Record) { + auto accessLevel = serializeAccessMixinImpl(Record, has_access<RecordTy>()); + if (!accessLevel.has_value()) + accessLevel = "public"; + serializeString(Paren, "accessLevel", accessLevel); +} + +template <typename RecordTy> +std::optional<Object> serializeTemplateMixinImpl(const RecordTy &Record, + std::true_type) { + const auto &Template = Record.Templ; + if (Template.empty()) + return std::nullopt; + + Object Generics; + Array GenericParameters; + for (const auto &Param : Template.getParameters()) { + Object Parameter; + Parameter["name"] = Param.Name; + Parameter["index"] = Param.Index; + Parameter["depth"] = Param.Depth; + GenericParameters.emplace_back(std::move(Parameter)); + } + if (!GenericParameters.empty()) + Generics["parameters"] = std::move(GenericParameters); + + Array GenericConstraints; + for (const auto &Constr : Template.getConstraints()) { + Object Constraint; + Constraint["kind"] = Constr.Kind; + Constraint["lhs"] = Constr.LHS; + Constraint["rhs"] = Constr.RHS; + GenericConstraints.emplace_back(std::move(Constraint)); + } + + if (!GenericConstraints.empty()) + Generics["constraints"] = std::move(GenericConstraints); + + return Generics; +} + +template <typename RecordTy> +std::optional<Object> serializeTemplateMixinImpl(const RecordTy &Record, + std::false_type) { + return std::nullopt; +} + +template <typename RecordTy> +void serializeTemplateMixin(Object &Paren, const RecordTy &Record) { + serializeObject(Paren, "swiftGenerics", + serializeTemplateMixinImpl(Record, has_template<RecordTy>())); +} + struct PathComponent { StringRef USR; StringRef Name; @@ -497,14 +662,16 @@ bool generatePathComponents( if (!ParentRecord) ParentRecord = API.findRecordForUSR(CurrentParent->ParentUSR); - // If the parent is a category then we need to pretend this belongs to the - // associated interface. + // If the parent is a category extended from internal module then we need to + // pretend this belongs to the associated interface. if (auto *CategoryRecord = dyn_cast_or_null<ObjCCategoryRecord>(ParentRecord)) { - ParentRecord = API.findRecordForUSR(CategoryRecord->Interface.USR); - CurrentParentComponent = PathComponent(CategoryRecord->Interface.USR, - CategoryRecord->Interface.Name, - APIRecord::RK_ObjCInterface); + if (!CategoryRecord->IsFromExternalModule) { + ParentRecord = API.findRecordForUSR(CategoryRecord->Interface.USR); + CurrentParentComponent = PathComponent(CategoryRecord->Interface.USR, + CategoryRecord->Interface.Name, + APIRecord::RK_ObjCInterface); + } } // The parent record doesn't exist which means the symbol shouldn't be @@ -543,7 +710,6 @@ Array generateParentContexts(const RecordTy &Record, const APISet &API, return ParentContexts; } - } // namespace /// Defines the format version emitted by SymbolGraphSerializer. @@ -577,7 +743,7 @@ bool SymbolGraphSerializer::shouldSkip(const APIRecord &Record) const { // Filter out symbols prefixed with an underscored as they are understood to // be symbols clients should not use. - if (Record.Name.startswith("_")) + if (Record.Name.starts_with("_")) return true; return false; @@ -602,9 +768,6 @@ SymbolGraphSerializer::serializeAPIRecord(const RecordTy &Record) const { serializeObject(Obj, "docComment", serializeDocComment(Record.Comment)); serializeArray(Obj, "declarationFragments", serializeDeclarationFragments(Record.Declaration)); - // TODO: Once we keep track of symbol access information serialize it - // correctly here. - Obj["accessLevel"] = "public"; SmallVector<StringRef, 4> PathComponentsNames; // If this returns true it indicates that we couldn't find a symbol in the // hierarchy. @@ -617,6 +780,8 @@ SymbolGraphSerializer::serializeAPIRecord(const RecordTy &Record) const { serializeArray(Obj, "pathComponents", Array(PathComponentsNames)); serializeFunctionSignatureMixin(Obj, Record); + serializeAccessMixin(Obj, Record); + serializeTemplateMixin(Obj, Record); return Obj; } @@ -646,10 +811,22 @@ StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) { return "inheritsFrom"; case RelationshipKind::ConformsTo: return "conformsTo"; + case RelationshipKind::ExtensionTo: + return "extensionTo"; } llvm_unreachable("Unhandled relationship kind"); } +StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) { + switch (Kind) { + case ConstraintKind::Conformance: + return "conformance"; + case ConstraintKind::ConditionalConformance: + return "conditionalConformance"; + } + llvm_unreachable("Unhandled constraint kind"); +} + void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind, SymbolReference Source, SymbolReference Target) { @@ -662,6 +839,17 @@ void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind, Relationships.emplace_back(std::move(Relationship)); } +void SymbolGraphSerializer::visitNamespaceRecord( + const NamespaceRecord &Record) { + auto Namespace = serializeAPIRecord(Record); + if (!Namespace) + return; + Symbols.emplace_back(std::move(*Namespace)); + if (!Record.ParentInformation.empty()) + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + void SymbolGraphSerializer::visitGlobalFunctionRecord( const GlobalFunctionRecord &Record) { auto Obj = serializeAPIRecord(Record); @@ -698,6 +886,193 @@ void SymbolGraphSerializer::visitStructRecord(const StructRecord &Record) { serializeMembers(Record, Record.Fields); } +void SymbolGraphSerializer::visitStaticFieldRecord( + const StaticFieldRecord &Record) { + auto StaticField = serializeAPIRecord(Record); + if (!StaticField) + return; + Symbols.emplace_back(std::move(*StaticField)); + serializeRelationship(RelationshipKind::MemberOf, Record, Record.Context); +} + +void SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord &Record) { + auto Class = serializeAPIRecord(Record); + if (!Class) + return; + + Symbols.emplace_back(std::move(*Class)); + for (const auto &Base : Record.Bases) + serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); + if (!Record.ParentInformation.empty()) + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + +void SymbolGraphSerializer::visitClassTemplateRecord( + const ClassTemplateRecord &Record) { + auto Class = serializeAPIRecord(Record); + if (!Class) + return; + + Symbols.emplace_back(std::move(*Class)); + for (const auto &Base : Record.Bases) + serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); + if (!Record.ParentInformation.empty()) + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + +void SymbolGraphSerializer::visitClassTemplateSpecializationRecord( + const ClassTemplateSpecializationRecord &Record) { + auto Class = serializeAPIRecord(Record); + if (!Class) + return; + + Symbols.emplace_back(std::move(*Class)); + + for (const auto &Base : Record.Bases) + serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); + if (!Record.ParentInformation.empty()) + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + +void SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord( + const ClassTemplatePartialSpecializationRecord &Record) { + auto Class = serializeAPIRecord(Record); + if (!Class) + return; + + Symbols.emplace_back(std::move(*Class)); + + for (const auto &Base : Record.Bases) + serializeRelationship(RelationshipKind::InheritsFrom, Record, Base); + if (!Record.ParentInformation.empty()) + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + +void SymbolGraphSerializer::visitCXXInstanceMethodRecord( + const CXXInstanceMethodRecord &Record) { + auto InstanceMethod = serializeAPIRecord(Record); + if (!InstanceMethod) + return; + + Symbols.emplace_back(std::move(*InstanceMethod)); + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + +void SymbolGraphSerializer::visitCXXStaticMethodRecord( + const CXXStaticMethodRecord &Record) { + auto StaticMethod = serializeAPIRecord(Record); + if (!StaticMethod) + return; + + Symbols.emplace_back(std::move(*StaticMethod)); + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + +void SymbolGraphSerializer::visitMethodTemplateRecord( + const CXXMethodTemplateRecord &Record) { + if (!ShouldRecurse) + // Ignore child symbols + return; + auto MethodTemplate = serializeAPIRecord(Record); + if (!MethodTemplate) + return; + Symbols.emplace_back(std::move(*MethodTemplate)); + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + +void SymbolGraphSerializer::visitMethodTemplateSpecializationRecord( + const CXXMethodTemplateSpecializationRecord &Record) { + if (!ShouldRecurse) + // Ignore child symbols + return; + auto MethodTemplateSpecialization = serializeAPIRecord(Record); + if (!MethodTemplateSpecialization) + return; + Symbols.emplace_back(std::move(*MethodTemplateSpecialization)); + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + +void SymbolGraphSerializer::visitCXXFieldRecord(const CXXFieldRecord &Record) { + if (!ShouldRecurse) + return; + auto CXXField = serializeAPIRecord(Record); + if (!CXXField) + return; + Symbols.emplace_back(std::move(*CXXField)); + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + +void SymbolGraphSerializer::visitCXXFieldTemplateRecord( + const CXXFieldTemplateRecord &Record) { + if (!ShouldRecurse) + // Ignore child symbols + return; + auto CXXFieldTemplate = serializeAPIRecord(Record); + if (!CXXFieldTemplate) + return; + Symbols.emplace_back(std::move(*CXXFieldTemplate)); + serializeRelationship(RelationshipKind::MemberOf, Record, + Record.ParentInformation.ParentRecord); +} + +void SymbolGraphSerializer::visitConceptRecord(const ConceptRecord &Record) { + auto Concept = serializeAPIRecord(Record); + if (!Concept) + return; + + Symbols.emplace_back(std::move(*Concept)); +} + +void SymbolGraphSerializer::visitGlobalVariableTemplateRecord( + const GlobalVariableTemplateRecord &Record) { + auto GlobalVariableTemplate = serializeAPIRecord(Record); + if (!GlobalVariableTemplate) + return; + Symbols.emplace_back(std::move(*GlobalVariableTemplate)); +} + +void SymbolGraphSerializer::visitGlobalVariableTemplateSpecializationRecord( + const GlobalVariableTemplateSpecializationRecord &Record) { + auto GlobalVariableTemplateSpecialization = serializeAPIRecord(Record); + if (!GlobalVariableTemplateSpecialization) + return; + Symbols.emplace_back(std::move(*GlobalVariableTemplateSpecialization)); +} + +void SymbolGraphSerializer:: + visitGlobalVariableTemplatePartialSpecializationRecord( + const GlobalVariableTemplatePartialSpecializationRecord &Record) { + auto GlobalVariableTemplatePartialSpecialization = serializeAPIRecord(Record); + if (!GlobalVariableTemplatePartialSpecialization) + return; + Symbols.emplace_back(std::move(*GlobalVariableTemplatePartialSpecialization)); +} + +void SymbolGraphSerializer::visitGlobalFunctionTemplateRecord( + const GlobalFunctionTemplateRecord &Record) { + auto GlobalFunctionTemplate = serializeAPIRecord(Record); + if (!GlobalFunctionTemplate) + return; + Symbols.emplace_back(std::move(*GlobalFunctionTemplate)); +} + +void SymbolGraphSerializer::visitGlobalFunctionTemplateSpecializationRecord( + const GlobalFunctionTemplateSpecializationRecord &Record) { + auto GlobalFunctionTemplateSpecialization = serializeAPIRecord(Record); + if (!GlobalFunctionTemplateSpecialization) + return; + Symbols.emplace_back(std::move(*GlobalFunctionTemplateSpecialization)); +} + void SymbolGraphSerializer::visitObjCContainerRecord( const ObjCContainerRecord &Record) { auto ObjCContainer = serializeAPIRecord(Record); @@ -735,6 +1110,45 @@ void SymbolGraphSerializer::visitObjCContainerRecord( } } +void SymbolGraphSerializer::visitObjCCategoryRecord( + const ObjCCategoryRecord &Record) { + if (!Record.IsFromExternalModule) + return; + + // Check if the current Category' parent has been visited before, if so skip. + if (!visitedCategories.contains(Record.Interface.Name)) { + visitedCategories.insert(Record.Interface.Name); + Object Obj; + serializeObject(Obj, "identifier", + serializeIdentifier(Record, API.getLanguage())); + serializeObject(Obj, "kind", + serializeSymbolKind(APIRecord::RK_ObjCCategoryModule, + API.getLanguage())); + Obj["accessLevel"] = "public"; + Symbols.emplace_back(std::move(Obj)); + } + + Object Relationship; + Relationship["source"] = Record.USR; + Relationship["target"] = Record.Interface.USR; + Relationship["targetFallback"] = Record.Interface.Name; + Relationship["kind"] = getRelationshipString(RelationshipKind::ExtensionTo); + Relationships.emplace_back(std::move(Relationship)); + + auto ObjCCategory = serializeAPIRecord(Record); + + if (!ObjCCategory) + return; + + Symbols.emplace_back(std::move(*ObjCCategory)); + serializeMembers(Record, Record.Methods); + serializeMembers(Record, Record.Properties); + + // Surface the protocols of the category to the interface. + for (const auto &Protocol : Record.Protocols) + serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol); +} + void SymbolGraphSerializer::visitMacroDefinitionRecord( const MacroDefinitionRecord &Record) { auto Macro = serializeAPIRecord(Record); @@ -761,12 +1175,21 @@ void SymbolGraphSerializer::serializeSingleRecord(const APIRecord *Record) { case APIRecord::RK_Struct: visitStructRecord(*cast<StructRecord>(Record)); break; + case APIRecord::RK_StaticField: + visitStaticFieldRecord(*cast<StaticFieldRecord>(Record)); + break; + case APIRecord::RK_CXXClass: + visitCXXClassRecord(*cast<CXXClassRecord>(Record)); + break; case APIRecord::RK_ObjCInterface: visitObjCContainerRecord(*cast<ObjCInterfaceRecord>(Record)); break; case APIRecord::RK_ObjCProtocol: visitObjCContainerRecord(*cast<ObjCProtocolRecord>(Record)); break; + case APIRecord::RK_ObjCCategory: + visitObjCCategoryRecord(*cast<ObjCCategoryRecord>(Record)); + break; case APIRecord::RK_MacroDefinition: visitMacroDefinitionRecord(*cast<MacroDefinitionRecord>(Record)); break; @@ -835,9 +1258,6 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR, if (!Record) return {}; - if (isa<ObjCCategoryRecord>(Record)) - return {}; - Object Root; APIIgnoresList EmptyIgnores; SymbolGraphSerializer Serializer(API, EmptyIgnores, |
