diff options
author | ruturaj4 <ruturajkvaidya@ku.edu> | 2023-07-04 07:29:06 -0500 |
---|---|---|
committer | ruturaj4 <ruturajkvaidya@ku.edu> | 2023-08-15 10:34:21 -0500 |
commit | 184931853924b53f5f07602229b9d129540ab02a (patch) | |
tree | 58c4ce7557a53002727631443697a11285f70f7e /clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp | |
parent | b0a77af4f19a4f6b49ac4aadd0a9c89d287b74ce (diff) | |
download | llvm-184931853924b53f5f07602229b9d129540ab02a.zip llvm-184931853924b53f5f07602229b9d129540ab02a.tar.gz llvm-184931853924b53f5f07602229b9d129540ab02a.tar.bz2 |
[clang][ExtractAPI] Add support for Objective-C categories
Differential Revision: https://reviews.llvm.org/D152770
Diffstat (limited to 'clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp')
-rw-r--r-- | clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp | 78 |
1 files changed, 65 insertions, 13 deletions
diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index c9fbf0d..7783035 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -328,7 +328,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; @@ -432,9 +438,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"); @@ -563,14 +572,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 @@ -709,6 +720,8 @@ StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) { return "inheritsFrom"; case RelationshipKind::ConformsTo: return "conformsTo"; + case RelationshipKind::ExtensionTo: + return "extensionTo"; } llvm_unreachable("Unhandled relationship kind"); } @@ -820,6 +833,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) > 0)) { + 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); @@ -858,6 +910,9 @@ void SymbolGraphSerializer::serializeSingleRecord(const APIRecord *Record) { 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; @@ -926,9 +981,6 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR, if (!Record) return {}; - if (isa<ObjCCategoryRecord>(Record)) - return {}; - Object Root; APIIgnoresList EmptyIgnores; SymbolGraphSerializer Serializer(API, EmptyIgnores, |