[clang][extract-api] Add Objective-C interface support

Add support for Objective-C interface declarations in ExtractAPI.

Depends on D122495

Differential Revision: https://reviews.llvm.org/D122446
This commit is contained in:
Zixu Wang
2022-03-24 18:19:30 -07:00
parent 686dcbe8b0
commit 9b36e126fd
8 changed files with 1147 additions and 19 deletions

View File

@@ -372,6 +372,27 @@ Object serializeSymbolKind(const APIRecord &Record, Language Lang) {
Kind["identifier"] = AddLangPrefix("struct");
Kind["displayName"] = "Structure";
break;
case APIRecord::RK_ObjCIvar:
Kind["identifier"] = AddLangPrefix("ivar");
Kind["displayName"] = "Instance Variable";
break;
case APIRecord::RK_ObjCMethod:
if (dyn_cast<ObjCMethodRecord>(&Record)->IsInstanceMethod) {
Kind["identifier"] = AddLangPrefix("method");
Kind["displayName"] = "Instance Method";
} else {
Kind["identifier"] = AddLangPrefix("type.method");
Kind["displayName"] = "Type Method";
}
break;
case APIRecord::RK_ObjCProperty:
Kind["identifier"] = AddLangPrefix("property");
Kind["displayName"] = "Instance Property";
break;
case APIRecord::RK_ObjCInterface:
Kind["identifier"] = AddLangPrefix("class");
Kind["displayName"] = "Class";
break;
}
return Kind;
@@ -435,13 +456,17 @@ StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
switch (Kind) {
case RelationshipKind::MemberOf:
return "memberOf";
case RelationshipKind::InheritsFrom:
return "inheritsFrom";
case RelationshipKind::ConformsTo:
return "conformsTo";
}
llvm_unreachable("Unhandled relationship kind");
}
void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
const APIRecord &Source,
const APIRecord &Target) {
SymbolReference Source,
SymbolReference Target) {
Object Relationship;
Relationship["source"] = Source.USR;
Relationship["target"] = Target.USR;
@@ -496,6 +521,57 @@ void SymbolGraphSerializer::serializeStructRecord(const StructRecord &Record) {
}
}
void SymbolGraphSerializer::serializeObjCContainerRecord(
const ObjCContainerRecord &Record) {
auto ObjCContainer = serializeAPIRecord(Record);
if (!ObjCContainer)
return;
Symbols.emplace_back(std::move(*ObjCContainer));
// Record instance variables and that the instance variables are members of
// the container.
for (const auto &Ivar : Record.Ivars) {
auto ObjCIvar = serializeAPIRecord(*Ivar);
if (!ObjCIvar)
continue;
Symbols.emplace_back(std::move(*ObjCIvar));
serializeRelationship(RelationshipKind::MemberOf, *Ivar, Record);
}
// Record methods and that the methods are members of the container.
for (const auto &Method : Record.Methods) {
auto ObjCMethod = serializeAPIRecord(*Method);
if (!ObjCMethod)
continue;
Symbols.emplace_back(std::move(*ObjCMethod));
serializeRelationship(RelationshipKind::MemberOf, *Method, Record);
}
// Record properties and that the properties are members of the container.
for (const auto &Property : Record.Properties) {
auto ObjCProperty = serializeAPIRecord(*Property);
if (!ObjCProperty)
continue;
Symbols.emplace_back(std::move(*ObjCProperty));
serializeRelationship(RelationshipKind::MemberOf, *Property, Record);
}
for (const auto &Protocol : Record.Protocols)
// Record that Record conforms to Protocol.
serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
if (auto *ObjCInterface = dyn_cast<ObjCInterfaceRecord>(&Record))
if (!ObjCInterface->SuperClass.empty())
// If Record is an Objective-C interface record and it has a super class,
// record that Record is inherited from SuperClass.
serializeRelationship(RelationshipKind::InheritsFrom, Record,
ObjCInterface->SuperClass);
}
Object SymbolGraphSerializer::serialize() {
Object Root;
serializeObject(Root, "metadata", serializeMetadata());
@@ -513,6 +589,10 @@ Object SymbolGraphSerializer::serialize() {
for (const auto &Struct : API.getStructs())
serializeStructRecord(*Struct.second);
// Serialize Objective-C interface records in the API set.
for (const auto &ObjCInterface : API.getObjCInterfaces())
serializeObjCContainerRecord(*ObjCInterface.second);
Root["symbols"] = std::move(Symbols);
Root["relationhips"] = std::move(Relationships);