[clang][ExtractAPI] Add support for C++ classes
Add ExtractAPI support C++ classes, fields, methods, and various qualifiers and specifiers Differential Revision: https://reviews.llvm.org/D153557
This commit is contained in:
@@ -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) {
|
||||
@@ -189,9 +197,10 @@ StringRef getLanguageName(Language Lang) {
|
||||
return "c";
|
||||
case Language::ObjC:
|
||||
return "objective-c";
|
||||
case Language::CXX:
|
||||
return "c++";
|
||||
|
||||
// Unsupported language currently
|
||||
case Language::CXX:
|
||||
case Language::ObjCXX:
|
||||
case Language::OpenCL:
|
||||
case Language::OpenCLCXX:
|
||||
@@ -366,6 +375,38 @@ 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_CXXClass:
|
||||
Kind["identifier"] = AddLangPrefix("class");
|
||||
Kind["displayName"] = "Class";
|
||||
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";
|
||||
@@ -470,6 +511,31 @@ 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);
|
||||
}
|
||||
|
||||
struct PathComponent {
|
||||
StringRef USR;
|
||||
StringRef Name;
|
||||
@@ -543,7 +609,6 @@ Array generateParentContexts(const RecordTy &Record, const APISet &API,
|
||||
|
||||
return ParentContexts;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/// Defines the format version emitted by SymbolGraphSerializer.
|
||||
@@ -602,9 +667,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 +679,7 @@ SymbolGraphSerializer::serializeAPIRecord(const RecordTy &Record) const {
|
||||
serializeArray(Obj, "pathComponents", Array(PathComponentsNames));
|
||||
|
||||
serializeFunctionSignatureMixin(Obj, Record);
|
||||
serializeAccessMixin(Obj, Record);
|
||||
|
||||
return Obj;
|
||||
}
|
||||
@@ -698,6 +761,28 @@ 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));
|
||||
serializeMembers(Record, Record.Fields);
|
||||
serializeMembers(Record, Record.Methods);
|
||||
|
||||
for (const auto Base : Record.Bases)
|
||||
serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
|
||||
}
|
||||
|
||||
void SymbolGraphSerializer::visitObjCContainerRecord(
|
||||
const ObjCContainerRecord &Record) {
|
||||
auto ObjCContainer = serializeAPIRecord(Record);
|
||||
@@ -761,6 +846,12 @@ 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;
|
||||
|
||||
Reference in New Issue
Block a user