[clang] 3bb4855 - [clang][ExtractAPI] Refactor C++ method and field visitation
Erick Velez via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 21 10:38:12 PDT 2023
Author: Erick Velez
Date: 2023-08-21T10:38:01-07:00
New Revision: 3bb485530869d3ea43458b24df5a2d5302553bf9
URL: https://github.com/llvm/llvm-project/commit/3bb485530869d3ea43458b24df5a2d5302553bf9
DIFF: https://github.com/llvm/llvm-project/commit/3bb485530869d3ea43458b24df5a2d5302553bf9.diff
LOG: [clang][ExtractAPI] Refactor C++ method and field visitation
Refactor visitation for C++ record children by following the Visitor's CRTP.
Expand VisitCXXField, VisitCXXMethod for non-templates and introduce VisitCXXConstructor, VisitCXXDestructor.
Handle relationships by finding the parent's Record via USR from DeclContext.
Depends on D158029
Reviewed By: dang
Differential Revision: https://reviews.llvm.org/D158031
Added:
Modified:
clang/include/clang/ExtractAPI/API.h
clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
clang/lib/ExtractAPI/API.cpp
clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
clang/test/ExtractAPI/constructor_destructor.cpp
clang/test/ExtractAPI/methods.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h
index b855f460b9c7c1..7b2d28f738e260 100644
--- a/clang/include/clang/ExtractAPI/API.h
+++ b/clang/include/clang/ExtractAPI/API.h
@@ -1117,7 +1117,9 @@ struct has_function_signature<ObjCInstanceMethodRecord>
template <>
struct has_function_signature<ObjCClassMethodRecord> : public std::true_type {};
template <>
-struct has_function_signature<CXXMethodRecord> : public std::true_type {};
+struct has_function_signature<CXXInstanceMethodRecord> : public std::true_type {};
+template <>
+struct has_function_signature<CXXStaticMethodRecord> : public std::true_type {};
template <>
struct has_function_signature<CXXMethodTemplateRecord> : public std::true_type {
};
@@ -1126,7 +1128,8 @@ struct has_function_signature<CXXMethodTemplateSpecializationRecord>
: public std::true_type {};
template <typename RecordTy> struct has_access : public std::false_type {};
-template <> struct has_access<CXXMethodRecord> : public std::true_type {};
+template <> struct has_access<CXXInstanceMethodRecord> : public std::true_type {};
+template <> struct has_access<CXXStaticMethodRecord> : public std::true_type {};
template <> struct has_access<CXXFieldRecord> : public std::true_type {};
template <>
struct has_access<CXXMethodTemplateRecord> : public std::true_type {};
@@ -1267,7 +1270,7 @@ class APISet {
DeclarationFragments SubHeading, SymbolReference Context,
AccessControl Access, bool IsFromSystemHeaderg);
- CXXFieldRecord *addCXXField(CXXClassRecord *CXXClass, StringRef Name,
+ CXXFieldRecord *addCXXField(APIRecord *CXXClass, StringRef Name,
StringRef USR, PresumedLoc Loc,
AvailabilitySet Availabilities,
const DocComment &Comment,
@@ -1322,18 +1325,25 @@ class APISet {
DeclarationFragments SubHeading, Template Template,
bool IsFromSystemHeader);
- CXXMethodRecord *
- addCXXMethod(CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilitySet Availability,
- const DocComment &Comment, DeclarationFragments Declaration,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- bool IsStatic, AccessControl Access, bool IsFromSystemHeader);
+ CXXMethodRecord *addCXXInstanceMethod(
+ APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilitySet Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ FunctionSignature Signature, AccessControl Access,
+ bool IsFromSystemHeader);
+
+ CXXMethodRecord *addCXXStaticMethod(
+ APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilitySet Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ FunctionSignature Signature, AccessControl Access,
+ bool IsFromSystemHeader);
CXXMethodRecord *addCXXSpecialMethod(
- CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment,
+ APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilitySet Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, bool IsConstructor, AccessControl Access,
+ FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader);
CXXMethodTemplateRecord *addCXXMethodTemplate(
@@ -1508,6 +1518,13 @@ class APISet {
const RecordMap<CXXMethodTemplateRecord> &getCXXMethodTemplates() const {
return CXXMethodTemplates;
}
+ const RecordMap<CXXInstanceMethodRecord> &getCXXInstanceMethods() const {
+ return CXXInstanceMethods;
+ }
+ const RecordMap<CXXStaticMethodRecord> &getCXXStaticMethods() const {
+ return CXXStaticMethods;
+ }
+ const RecordMap<CXXFieldRecord> &getCXXFields() const { return CXXFields; }
const RecordMap<CXXMethodTemplateSpecializationRecord> &
getCXXMethodTemplateSpecializations() const {
return CXXMethodTemplateSpecializations;
@@ -1594,6 +1611,10 @@ class APISet {
RecordMap<EnumRecord> Enums;
RecordMap<StructRecord> Structs;
RecordMap<CXXClassRecord> CXXClasses;
+ RecordMap<CXXFieldRecord> CXXFields;
+ RecordMap<CXXMethodRecord> CXXMethods;
+ RecordMap<CXXInstanceMethodRecord> CXXInstanceMethods;
+ RecordMap<CXXStaticMethodRecord> CXXStaticMethods;
RecordMap<CXXMethodTemplateRecord> CXXMethodTemplates;
RecordMap<CXXMethodTemplateSpecializationRecord>
CXXMethodTemplateSpecializations;
diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
index dbe7f78cd33430..38239b09dd484f 100644
--- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
+++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
@@ -50,6 +50,8 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
bool VisitEnumDecl(const EnumDecl *Decl);
+ bool WalkUpFromFunctionDecl(const FunctionDecl *Decl);
+
bool WalkUpFromRecordDecl(const RecordDecl *Decl);
bool WalkUpFromCXXRecordDecl(const CXXRecordDecl *Decl);
@@ -78,6 +80,14 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
bool VisitCXXMethodDecl(const CXXMethodDecl *Decl);
+ bool VisitFieldDecl(const FieldDecl *Decl);
+
+ bool VisitCXXConversionDecl(const CXXConversionDecl *Decl);
+
+ bool VisitCXXConstructorDecl(const CXXConstructorDecl *Decl);
+
+ bool VisitCXXDestructorDecl(const CXXDestructorDecl *Decl);
+
bool VisitConceptDecl(const ConceptDecl *Decl);
bool VisitClassTemplateSpecializationDecl(
@@ -119,20 +129,6 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
void recordStructFields(StructRecord *StructRecord,
const RecordDecl::field_range Fields);
- /// Collect API information for the class fields and associate with the parent
- /// struct
- void recordCXXFields(CXXClassRecord *CXXClassRecord,
- const RecordDecl::field_range Fields);
-
- void recordCXXMethods(CXXClassRecord *CXXClassRecord,
- const CXXRecordDecl::method_range Methods);
-
- void recordConversionMethod(CXXClassRecord *CXXClassRecord,
- const CXXMethodDecl *SpecialCXXMethod);
-
- void recordSpecialCXXMethod(CXXClassRecord *CXXClassRecord,
- const CXXMethodDecl *SpecialCXXMethod);
-
/// Collect API information for the Objective-C methods and associate with the
/// parent container.
void recordObjCMethods(ObjCContainerRecord *Container,
@@ -378,6 +374,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
return true;
}
+template <typename Derived>
+bool ExtractAPIVisitorBase<Derived>::WalkUpFromFunctionDecl(
+ const FunctionDecl *Decl) {
+ getDerivedExtractAPIVisitor().VisitFunctionDecl(Decl);
+ return true;
+}
+
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::WalkUpFromRecordDecl(
const RecordDecl *Decl) {
@@ -527,9 +530,6 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
CXXClassRecord->Bases = getBases(Decl);
- getDerivedExtractAPIVisitor().recordCXXFields(CXXClassRecord, Decl->fields());
- getDerivedExtractAPIVisitor().recordCXXMethods(CXXClassRecord,
- Decl->methods());
return true;
}
@@ -539,18 +539,12 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
Decl->isImplicit())
return true;
- switch (Decl->getTemplatedKind()) {
- case FunctionDecl::TK_MemberSpecialization:
- case FunctionDecl::TK_FunctionTemplateSpecialization:
- case FunctionDecl::TK_FunctionTemplate:
- case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
- break;
- case FunctionDecl::TK_NonTemplate:
- case FunctionDecl::TK_DependentNonTemplate:
+
+ if (isa<CXXConversionDecl>(Decl))
+ return true;
+ if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
return true;
- }
- StringRef Name = Decl->getName();
StringRef USR = API.recordUSR(Decl);
PresumedLoc Loc =
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
@@ -561,15 +555,18 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
Context.getDiagnostics());
DeclarationFragments SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);
+ auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
+ auto Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl);
SmallString<128> ParentUSR;
index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
ParentUSR);
+ auto *Parent = API.findRecordForUSR(ParentUSR);
if (Decl->isTemplated()) {
FunctionTemplateDecl *TemplateDecl = Decl->getDescribedFunctionTemplate();
API.addCXXMethodTemplate(
- API.findRecordForUSR(ParentUSR), Name, USR, Loc, AvailabilitySet(Decl),
- Comment,
+ API.findRecordForUSR(ParentUSR), Decl->getName(), USR, Loc,
+ AvailabilitySet(Decl), Comment,
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
TemplateDecl),
SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl),
@@ -577,13 +574,93 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
Template(TemplateDecl), isInSystemHeader(Decl));
} else if (Decl->getTemplateSpecializationInfo())
API.addCXXMethodTemplateSpec(
- API.findRecordForUSR(ParentUSR), Name, USR, Loc, AvailabilitySet(Decl),
- Comment,
+ Parent, Decl->getName(), USR, Loc, AvailabilitySet(Decl), Comment,
DeclarationFragmentsBuilder::
getFragmentsForFunctionTemplateSpecialization(Decl),
- SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl),
- DeclarationFragmentsBuilder::getAccessControl(Decl),
- isInSystemHeader(Decl));
+ SubHeading, Signature, Access, isInSystemHeader(Decl));
+ else if (Decl->isOverloadedOperator())
+ API.addCXXInstanceMethod(
+ Parent, API.copyString(Decl->getNameAsString()), USR, Loc,
+ AvailabilitySet(Decl), Comment,
+ DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(Decl),
+ SubHeading, Signature, Access, isInSystemHeader(Decl));
+ else if (Decl->isStatic())
+ API.addCXXStaticMethod(
+ Parent, Decl->getName(), USR, Loc, AvailabilitySet(Decl), Comment,
+ DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
+ Signature, Access, isInSystemHeader(Decl));
+ else
+ API.addCXXInstanceMethod(
+ Parent, Decl->getName(), USR, Loc, AvailabilitySet(Decl), Comment,
+ DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
+ Signature, Access, isInSystemHeader(Decl));
+
+ return true;
+}
+
+template <typename Derived>
+bool ExtractAPIVisitorBase<Derived>::VisitCXXConstructorDecl(
+ const CXXConstructorDecl *Decl) {
+
+ StringRef Name = API.copyString(Decl->getNameAsString());
+ StringRef USR = API.recordUSR(Decl);
+ PresumedLoc Loc =
+ Context.getSourceManager().getPresumedLoc(Decl->getLocation());
+ DocComment Comment;
+ if (auto *RawComment =
+ getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
+ Comment = RawComment->getFormattedLines(Context.getSourceManager(),
+ Context.getDiagnostics());
+
+ // Build declaration fragments, sub-heading, and signature for the method.
+ DeclarationFragments Declaration =
+ DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(Decl);
+ DeclarationFragments SubHeading =
+ DeclarationFragmentsBuilder::getSubHeading(Decl);
+ FunctionSignature Signature =
+ DeclarationFragmentsBuilder::getFunctionSignature(Decl);
+ AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
+
+ SmallString<128> ParentUSR;
+ index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
+ ParentUSR);
+ API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
+ AvailabilitySet(Decl), Comment, Declaration,
+ SubHeading, Signature, Access,
+ isInSystemHeader(Decl));
+ return true;
+}
+
+template <typename Derived>
+bool ExtractAPIVisitorBase<Derived>::VisitCXXDestructorDecl(
+ const CXXDestructorDecl *Decl) {
+
+ StringRef Name = API.copyString(Decl->getNameAsString());
+ StringRef USR = API.recordUSR(Decl);
+ PresumedLoc Loc =
+ Context.getSourceManager().getPresumedLoc(Decl->getLocation());
+ DocComment Comment;
+ if (auto *RawComment =
+ getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
+ Comment = RawComment->getFormattedLines(Context.getSourceManager(),
+ Context.getDiagnostics());
+
+ // Build declaration fragments, sub-heading, and signature for the method.
+ DeclarationFragments Declaration =
+ DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(Decl);
+ DeclarationFragments SubHeading =
+ DeclarationFragmentsBuilder::getSubHeading(Decl);
+ FunctionSignature Signature =
+ DeclarationFragmentsBuilder::getFunctionSignature(Decl);
+ AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
+
+ SmallString<128> ParentUSR;
+ index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
+ ParentUSR);
+ API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
+ AvailabilitySet(Decl), Comment, Declaration,
+ SubHeading, Signature, Access,
+ isInSystemHeader(Decl));
return true;
}
@@ -636,10 +713,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitClassTemplateSpecializationDecl(
isInSystemHeader(Decl));
ClassTemplateSpecializationRecord->Bases = getBases(Decl);
- getDerivedExtractAPIVisitor().recordCXXFields(
- ClassTemplateSpecializationRecord, Decl->fields());
- getDerivedExtractAPIVisitor().recordCXXMethods(
- ClassTemplateSpecializationRecord, Decl->methods());
+
return true;
}
@@ -671,10 +745,6 @@ bool ExtractAPIVisitorBase<Derived>::
ClassTemplatePartialSpecRecord->Bases = getBases(Decl);
- getDerivedExtractAPIVisitor().recordCXXFields(ClassTemplatePartialSpecRecord,
- Decl->fields());
- getDerivedExtractAPIVisitor().recordCXXMethods(ClassTemplatePartialSpecRecord,
- Decl->methods());
return true;
}
@@ -1063,155 +1133,74 @@ void ExtractAPIVisitorBase<Derived>::recordStructFields(
}
template <typename Derived>
-void ExtractAPIVisitorBase<Derived>::recordCXXFields(
- CXXClassRecord *CXXClassRecord, const RecordDecl::field_range Fields) {
- for (const auto *Field : Fields) {
- // Collect symbol information.
- StringRef Name = Field->getName();
- StringRef USR = API.recordUSR(Field);
- PresumedLoc Loc =
- Context.getSourceManager().getPresumedLoc(Field->getLocation());
- Context.getSourceManager().getPresumedLoc(Field->getLocation());
- DocComment Comment;
- if (auto *RawComment =
- getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Field))
- Comment = RawComment->getFormattedLines(Context.getSourceManager(),
- Context.getDiagnostics());
-
- // Build declaration fragments and sub-heading for the struct field.
- DeclarationFragments Declaration =
- DeclarationFragmentsBuilder::getFragmentsForField(Field);
- DeclarationFragments SubHeading =
- DeclarationFragmentsBuilder::getSubHeading(Field);
- AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Field);
-
- API.addCXXField(CXXClassRecord, Name, USR, Loc, AvailabilitySet(Field),
- Comment, Declaration, SubHeading, Access,
- isInSystemHeader(Field));
- }
-}
-
-/// Collect API information for constructors and destructors and associate with
-/// the parent class.
-template <typename Derived>
-void ExtractAPIVisitorBase<Derived>::recordSpecialCXXMethod(
- CXXClassRecord *CXXClassRecord, const CXXMethodDecl *CXXSpecialMethod) {
- StringRef Name;
- bool isConstructor = false;
- if (isa<CXXConstructorDecl>(CXXSpecialMethod)) {
- isConstructor = true;
- Name = CXXClassRecord->Name;
- } else if (isa<CXXDestructorDecl>(CXXSpecialMethod)) {
- // Copy string to get name with '~'.
- Name = API.copyString(CXXSpecialMethod->getNameAsString());
- }
-
- StringRef USR = API.recordUSR(CXXSpecialMethod);
- PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(
- CXXSpecialMethod->getLocation());
+bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
+ if (Decl->getDeclContext()->getDeclKind() == Decl::Record)
+ return true;
+ if (isa<ObjCIvarDecl>(Decl))
+ return true;
+ // Collect symbol information.
+ StringRef Name = Decl->getName();
+ StringRef USR = API.recordUSR(Decl);
+ PresumedLoc Loc =
+ Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
- if (auto *RawComment = getDerivedExtractAPIVisitor().fetchRawCommentForDecl(
- CXXSpecialMethod))
+ if (auto *RawComment =
+ getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
Context.getDiagnostics());
- // Build declaration fragments, sub-heading, and signature for the method.
+ // Build declaration fragments and sub-heading for the struct field.
DeclarationFragments Declaration =
- DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
- CXXSpecialMethod);
+ DeclarationFragmentsBuilder::getFragmentsForField(Decl);
DeclarationFragments SubHeading =
- DeclarationFragmentsBuilder::getSubHeading(CXXSpecialMethod);
- FunctionSignature Signature =
- DeclarationFragmentsBuilder::getFunctionSignature(CXXSpecialMethod);
- AccessControl Access =
- DeclarationFragmentsBuilder::getAccessControl(CXXSpecialMethod);
-
- API.addCXXSpecialMethod(CXXClassRecord, Name, USR, Loc,
- AvailabilitySet(CXXSpecialMethod), Comment,
- Declaration, SubHeading, Signature, isConstructor,
- Access, isInSystemHeader(CXXSpecialMethod));
+ DeclarationFragmentsBuilder::getSubHeading(Decl);
+ AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
+
+ SmallString<128> ParentUSR;
+ index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
+ ParentUSR);
+ API.addCXXField(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
+ AvailabilitySet(Decl), Comment, Declaration, SubHeading,
+ Access, isInSystemHeader(Decl));
+ return true;
}
template <typename Derived>
-void ExtractAPIVisitorBase<Derived>::recordConversionMethod(
- CXXClassRecord *CXXClassRecord, const CXXMethodDecl *SpecialCXXMethod) {
- StringRef Name = API.copyString(SpecialCXXMethod->getNameAsString());
- StringRef USR = API.recordUSR(SpecialCXXMethod);
- PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(
- SpecialCXXMethod->getLocation());
+bool ExtractAPIVisitorBase<Derived>::VisitCXXConversionDecl(
+ const CXXConversionDecl *Decl) {
+ StringRef Name = API.copyString(Decl->getNameAsString());
+ StringRef USR = API.recordUSR(Decl);
+ PresumedLoc Loc =
+ Context.getSourceManager().getPresumedLoc(Decl->getLocation());
DocComment Comment;
- if (auto *RawComment = getDerivedExtractAPIVisitor().fetchRawCommentForDecl(
- SpecialCXXMethod))
+ if (auto *RawComment =
+ getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
Context.getDiagnostics());
// Build declaration fragments, sub-heading, and signature for the method.
DeclarationFragments Declaration =
- DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
- cast<CXXConversionDecl>(SpecialCXXMethod));
+ DeclarationFragmentsBuilder::getFragmentsForConversionFunction(Decl);
DeclarationFragments SubHeading =
- DeclarationFragmentsBuilder::getSubHeading(SpecialCXXMethod);
+ DeclarationFragmentsBuilder::getSubHeading(Decl);
FunctionSignature Signature =
- DeclarationFragmentsBuilder::getFunctionSignature(SpecialCXXMethod);
- AccessControl Access =
- DeclarationFragmentsBuilder::getAccessControl(SpecialCXXMethod);
-
- API.addCXXMethod(CXXClassRecord, Name, USR, Loc,
- AvailabilitySet(SpecialCXXMethod), Comment, Declaration,
- SubHeading, Signature, SpecialCXXMethod->isStatic(), Access,
- isInSystemHeader(SpecialCXXMethod));
-}
-
-template <typename Derived>
-void ExtractAPIVisitorBase<Derived>::recordCXXMethods(
- CXXClassRecord *CXXClassRecord, const CXXRecordDecl::method_range Methods) {
- for (const auto *Method : Methods) {
- if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method)) {
- recordSpecialCXXMethod(CXXClassRecord, Method);
- continue;
- }
-
- if (isa<CXXConversionDecl>(Method)) {
- recordConversionMethod(CXXClassRecord, Method);
- continue;
- }
-
- if (Method->isFunctionTemplateSpecialization())
- return;
-
- StringRef Name;
- DeclarationFragments Declaration;
- if (Method->isOverloadedOperator()) {
- Name = API.copyString(Method->getNameAsString());
- Declaration =
- DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
- Method);
- } else {
- Name = API.copyString(Method->getNameAsString());
- Declaration =
- DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Method);
- }
- StringRef USR = API.recordUSR(Method);
- PresumedLoc Loc =
- Context.getSourceManager().getPresumedLoc(Method->getLocation());
- DocComment Comment;
- if (auto *RawComment =
- getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Method))
- Comment = RawComment->getFormattedLines(Context.getSourceManager(),
- Context.getDiagnostics());
-
- // Build declaration fragments, sub-heading, and signature for the method.
- DeclarationFragments SubHeading =
- DeclarationFragmentsBuilder::getSubHeading(Method);
- FunctionSignature Signature =
- DeclarationFragmentsBuilder::getFunctionSignature(Method);
- AccessControl Access =
- DeclarationFragmentsBuilder::getAccessControl(Method);
+ DeclarationFragmentsBuilder::getFunctionSignature(Decl);
+ AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
- API.addCXXMethod(CXXClassRecord, Name, USR, Loc, AvailabilitySet(Method),
- Comment, Declaration, SubHeading, Signature,
- Method->isStatic(), Access, isInSystemHeader(Method));
- }
+ SmallString<128> ParentUSR;
+ index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
+ ParentUSR);
+ if (Decl->isStatic())
+ API.addCXXStaticMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
+ AvailabilitySet(Decl), Comment, Declaration,
+ SubHeading, Signature, Access,
+ isInSystemHeader(Decl));
+ else
+ API.addCXXInstanceMethod(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
+ AvailabilitySet(Decl), Comment, Declaration,
+ SubHeading, Signature, Access,
+ isInSystemHeader(Decl));
+ return true;
}
/// Collect API information for the Objective-C methods and associate with the
diff --git a/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h b/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
index 34bb83a1382339..269333245c8363 100644
--- a/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
+++ b/clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
@@ -39,10 +39,16 @@ template <typename Derived> class APISetVisitor {
getDerived()->traverseClassTemplatePartialSpecializationRecords();
+ getDerived()->traverseCXXInstanceMethods();
+
+ getDerived()->traverseCXXStaticMethods();
+
getDerived()->traverseCXXMethodTemplates();
getDerived()->traverseCXXMethodTemplateSpecializations();
+ getDerived()->traverseCXXFields();
+
getDerived()->traverseCXXFieldTemplates();
getDerived()->traverseConcepts();
@@ -131,6 +137,21 @@ template <typename Derived> class APISetVisitor {
*ClassTemplatePartialSpecialization.second);
}
+ void traverseCXXInstanceMethods() {
+ for (const auto &InstanceMethod : API.getCXXInstanceMethods())
+ getDerived()->visitCXXInstanceMethodRecord(*InstanceMethod.second);
+ }
+
+ void traverseCXXStaticMethods() {
+ for (const auto &InstanceMethod : API.getCXXStaticMethods())
+ getDerived()->visitCXXStaticMethodRecord(*InstanceMethod.second);
+ }
+
+ void traverseCXXFields() {
+ for (const auto &CXXField : API.getCXXFields())
+ getDerived()->visitCXXFieldRecord(*CXXField.second);
+ }
+
void traverseCXXFieldTemplates() {
for (const auto &CXXFieldTemplate : API.getCXXFieldTemplates())
getDerived()->visitCXXFieldTemplateRecord(*CXXFieldTemplate.second);
@@ -223,6 +244,10 @@ template <typename Derived> class APISetVisitor {
void visitClassTemplatePartialSpecializationRecord(
const ClassTemplatePartialSpecializationRecord &Record){};
+ void visitCXXInstanceRecord(const CXXInstanceMethodRecord &Record){};
+
+ void visitCXXStaticRecord(const CXXStaticMethodRecord &Record){};
+
void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record){};
void visitMethodTemplateSpecializationRecord(
diff --git a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
index ca12c8f7a9b013..05cc33a0cb8c08 100644
--- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
+++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
@@ -183,11 +183,17 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
void visitClassTemplatePartialSpecializationRecord(
const ClassTemplatePartialSpecializationRecord &Record);
+ void visitCXXInstanceMethodRecord(const CXXInstanceMethodRecord &Record);
+
+ void visitCXXStaticMethodRecord(const CXXStaticMethodRecord &Record);
+
void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record);
void visitMethodTemplateSpecializationRecord(
const CXXMethodTemplateSpecializationRecord &Record);
+ void visitCXXFieldRecord(const CXXFieldRecord &Record);
+
void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record);
void visitConceptRecord(const ConceptRecord &Record);
diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp
index 6cc00bc939c79c..9e4cfe6dbab308 100644
--- a/clang/lib/ExtractAPI/API.cpp
+++ b/clang/lib/ExtractAPI/API.cpp
@@ -171,18 +171,17 @@ APISet::addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc,
}
CXXFieldRecord *
-APISet::addCXXField(CXXClassRecord *CXXClass, StringRef Name, StringRef USR,
+APISet::addCXXField(APIRecord *CXXClass, StringRef Name, StringRef USR,
PresumedLoc Loc, AvailabilitySet Availabilities,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader) {
- auto Record = std::make_unique<CXXFieldRecord>(
- USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
- SubHeading, Access, IsFromSystemHeader);
+ auto *Record = addTopLevelRecord(
+ USRBasedLookupTable, CXXFields, USR, Name, Loc, std::move(Availabilities),
+ Comment, Declaration, SubHeading, Access, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
CXXClass->USR, CXXClass->Name, CXXClass->getKind(), CXXClass);
- USRBasedLookupTable.insert({USR, Record.get()});
- return CXXClass->Fields.emplace_back(std::move(Record)).get();
+ return Record;
}
CXXFieldTemplateRecord *APISet::addCXXFieldTemplate(
@@ -280,50 +279,38 @@ ConceptRecord *APISet::addConcept(StringRef Name, StringRef USR,
SubHeading, Template, IsFromSystemHeader);
}
-CXXMethodRecord *APISet::addCXXMethod(
- CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment,
+CXXMethodRecord *APISet::addCXXInstanceMethod(
+ APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilitySet Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, bool IsStatic, AccessControl Access,
+ FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader) {
- std::unique_ptr<CXXMethodRecord> Record;
- if (IsStatic)
- Record = std::make_unique<CXXStaticMethodRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader);
- else
- Record = std::make_unique<CXXInstanceMethodRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader);
+ CXXMethodRecord *Record =
+ addTopLevelRecord(USRBasedLookupTable, CXXInstanceMethods, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, Signature, Access, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
CXXClassRecord);
- USRBasedLookupTable.insert({USR, Record.get()});
- return CXXClassRecord->Methods.emplace_back(std::move(Record)).get();
+ return Record;
}
-CXXMethodRecord *APISet::addCXXSpecialMethod(
- CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment,
+CXXMethodRecord *APISet::addCXXStaticMethod(
+ APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilitySet Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, bool IsConstructor, AccessControl Access,
+ FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader) {
- std::unique_ptr<CXXMethodRecord> Record;
- if (IsConstructor)
- Record = std::make_unique<CXXConstructorRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader);
- else
- Record = std::make_unique<CXXDestructorRecord>(
- USR, Name, Loc, std::move(Availability), Comment, Declaration,
- SubHeading, Signature, Access, IsFromSystemHeader);
+ CXXMethodRecord *Record =
+ addTopLevelRecord(USRBasedLookupTable, CXXStaticMethods, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, Signature, Access, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
CXXClassRecord);
- USRBasedLookupTable.insert({USR, Record.get()});
- return CXXClassRecord->Methods.emplace_back(std::move(Record)).get();
+ return Record;
}
CXXMethodTemplateRecord *APISet::addCXXMethodTemplate(
diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
index 6782483681a0b1..e1b5f652764f11 100644
--- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -885,9 +885,6 @@ void SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord &Record) {
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);
}
@@ -899,9 +896,6 @@ void SymbolGraphSerializer::visitClassTemplateRecord(
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);
}
@@ -913,8 +907,6 @@ void SymbolGraphSerializer::visitClassTemplateSpecializationRecord(
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);
@@ -927,13 +919,33 @@ void SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord(
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::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)
@@ -960,6 +972,17 @@ void SymbolGraphSerializer::visitMethodTemplateSpecializationRecord(
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)
diff --git a/clang/test/ExtractAPI/constructor_destructor.cpp b/clang/test/ExtractAPI/constructor_destructor.cpp
index 63048d1a4baed6..65a924b53d69cb 100644
--- a/clang/test/ExtractAPI/constructor_destructor.cpp
+++ b/clang/test/ExtractAPI/constructor_destructor.cpp
@@ -137,7 +137,7 @@ class Foo {
"precise": "c:@S at Foo@F at Foo#"
},
"kind": {
- "displayName": "Constructor",
+ "displayName": "Instance Method",
"identifier": "c++.method"
},
"location": {
@@ -193,7 +193,7 @@ class Foo {
"precise": "c:@S at Foo@F@~Foo#"
},
"kind": {
- "displayName": "Destructor",
+ "displayName": "Instance Method",
"identifier": "c++.method"
},
"location": {
diff --git a/clang/test/ExtractAPI/methods.cpp b/clang/test/ExtractAPI/methods.cpp
index aed21c6afba82e..f25f9ecf0605c0 100644
--- a/clang/test/ExtractAPI/methods.cpp
+++ b/clang/test/ExtractAPI/methods.cpp
@@ -64,13 +64,13 @@ class Foo {
},
{
"kind": "memberOf",
- "source": "c:@S at Foo@F at getFoo#S",
+ "source": "c:@S at Foo@F at getBar#1",
"target": "c:@S at Foo",
"targetFallback": "Foo"
},
{
"kind": "memberOf",
- "source": "c:@S at Foo@F at getBar#1",
+ "source": "c:@S at Foo@F at getFoo#S",
"target": "c:@S at Foo",
"targetFallback": "Foo"
}
@@ -310,11 +310,11 @@ class Foo {
]
},
{
- "accessLevel": "public",
+ "accessLevel": "protected",
"declarationFragments": [
{
"kind": "keyword",
- "spelling": "static"
+ "spelling": "constexpr"
},
{
"kind": "text",
@@ -322,8 +322,8 @@ class Foo {
},
{
"kind": "typeIdentifier",
- "preciseIdentifier": "c:d",
- "spelling": "double"
+ "preciseIdentifier": "c:I",
+ "spelling": "int"
},
{
"kind": "text",
@@ -331,34 +331,42 @@ class Foo {
},
{
"kind": "identifier",
- "spelling": "getFoo"
+ "spelling": "getBar"
},
{
"kind": "text",
- "spelling": "();"
+ "spelling": "() "
+ },
+ {
+ "kind": "keyword",
+ "spelling": "const"
+ },
+ {
+ "kind": "text",
+ "spelling": ";"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
- "preciseIdentifier": "c:d",
- "spelling": "double"
+ "preciseIdentifier": "c:I",
+ "spelling": "int"
}
]
},
"identifier": {
"interfaceLanguage": "c++",
- "precise": "c:@S at Foo@F at getFoo#S"
+ "precise": "c:@S at Foo@F at getBar#1"
},
"kind": {
- "displayName": "Static Method",
- "identifier": "c++.type.method"
+ "displayName": "Instance Method",
+ "identifier": "c++.method"
},
"location": {
"position": {
"character": 17,
- "line": 7
+ "line": 10
},
"uri": "file://INPUT_DIR/input.h"
},
@@ -366,28 +374,28 @@ class Foo {
"navigator": [
{
"kind": "identifier",
- "spelling": "getFoo"
+ "spelling": "getBar"
}
],
"subHeading": [
{
"kind": "identifier",
- "spelling": "getFoo"
+ "spelling": "getBar"
}
],
- "title": "getFoo"
+ "title": "getBar"
},
"pathComponents": [
"Foo",
- "getFoo"
+ "getBar"
]
},
{
- "accessLevel": "protected",
+ "accessLevel": "public",
"declarationFragments": [
{
"kind": "keyword",
- "spelling": "constexpr"
+ "spelling": "static"
},
{
"kind": "text",
@@ -395,8 +403,8 @@ class Foo {
},
{
"kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
+ "preciseIdentifier": "c:d",
+ "spelling": "double"
},
{
"kind": "text",
@@ -404,42 +412,34 @@ class Foo {
},
{
"kind": "identifier",
- "spelling": "getBar"
- },
- {
- "kind": "text",
- "spelling": "() "
- },
- {
- "kind": "keyword",
- "spelling": "const"
+ "spelling": "getFoo"
},
{
"kind": "text",
- "spelling": ";"
+ "spelling": "();"
}
],
"functionSignature": {
"returns": [
{
"kind": "typeIdentifier",
- "preciseIdentifier": "c:I",
- "spelling": "int"
+ "preciseIdentifier": "c:d",
+ "spelling": "double"
}
]
},
"identifier": {
"interfaceLanguage": "c++",
- "precise": "c:@S at Foo@F at getBar#1"
+ "precise": "c:@S at Foo@F at getFoo#S"
},
"kind": {
- "displayName": "Instance Method",
- "identifier": "c++.method"
+ "displayName": "Static Method",
+ "identifier": "c++.type.method"
},
"location": {
"position": {
"character": 17,
- "line": 10
+ "line": 7
},
"uri": "file://INPUT_DIR/input.h"
},
@@ -447,20 +447,20 @@ class Foo {
"navigator": [
{
"kind": "identifier",
- "spelling": "getBar"
+ "spelling": "getFoo"
}
],
"subHeading": [
{
"kind": "identifier",
- "spelling": "getBar"
+ "spelling": "getFoo"
}
],
- "title": "getBar"
+ "title": "getFoo"
},
"pathComponents": [
"Foo",
- "getBar"
+ "getFoo"
]
}
]
More information about the cfe-commits
mailing list