aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp470
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,