aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
diff options
context:
space:
mode:
authorruturaj4 <ruturajkvaidya@ku.edu>2023-07-04 07:29:06 -0500
committerruturaj4 <ruturajkvaidya@ku.edu>2023-08-15 10:34:21 -0500
commit184931853924b53f5f07602229b9d129540ab02a (patch)
tree58c4ce7557a53002727631443697a11285f70f7e /clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
parentb0a77af4f19a4f6b49ac4aadd0a9c89d287b74ce (diff)
downloadllvm-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.cpp78
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,