evelez7 created this revision.
evelez7 added a reviewer: dang.
Herald added a reviewer: ributzka.
Herald added a project: All.
evelez7 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

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 <https://reviews.llvm.org/D158029>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158031

Files:
  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

Index: clang/test/ExtractAPI/methods.cpp
===================================================================
--- clang/test/ExtractAPI/methods.cpp
+++ clang/test/ExtractAPI/methods.cpp
@@ -64,13 +64,13 @@
     },
     {
       "kind": "memberOf",
-      "source": "c:@S@Foo@F@getFoo#S",
+      "source": "c:@S@Foo@F@getBar#1",
       "target": "c:@S@Foo",
       "targetFallback": "Foo"
     },
     {
       "kind": "memberOf",
-      "source": "c:@S@Foo@F@getBar#1",
+      "source": "c:@S@Foo@F@getFoo#S",
       "target": "c:@S@Foo",
       "targetFallback": "Foo"
     }
@@ -310,11 +310,11 @@
       ]
     },
     {
-      "accessLevel": "public",
+      "accessLevel": "protected",
       "declarationFragments": [
         {
           "kind": "keyword",
-          "spelling": "static"
+          "spelling": "constexpr"
         },
         {
           "kind": "text",
@@ -322,8 +322,8 @@
         },
         {
           "kind": "typeIdentifier",
-          "preciseIdentifier": "c:d",
-          "spelling": "double"
+          "preciseIdentifier": "c:I",
+          "spelling": "int"
         },
         {
           "kind": "text",
@@ -331,34 +331,42 @@
         },
         {
           "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@Foo@F@getFoo#S"
+        "precise": "c:@S@Foo@F@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 @@
         "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 @@
         },
         {
           "kind": "typeIdentifier",
-          "preciseIdentifier": "c:I",
-          "spelling": "int"
+          "preciseIdentifier": "c:d",
+          "spelling": "double"
         },
         {
           "kind": "text",
@@ -404,42 +412,34 @@
         },
         {
           "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@Foo@F@getBar#1"
+        "precise": "c:@S@Foo@F@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 @@
         "navigator": [
           {
             "kind": "identifier",
-            "spelling": "getBar"
+            "spelling": "getFoo"
           }
         ],
         "subHeading": [
           {
             "kind": "identifier",
-            "spelling": "getBar"
+            "spelling": "getFoo"
           }
         ],
-        "title": "getBar"
+        "title": "getFoo"
       },
       "pathComponents": [
         "Foo",
-        "getBar"
+        "getFoo"
       ]
     }
   ]
Index: clang/test/ExtractAPI/constructor_destructor.cpp
===================================================================
--- clang/test/ExtractAPI/constructor_destructor.cpp
+++ clang/test/ExtractAPI/constructor_destructor.cpp
@@ -137,7 +137,7 @@
         "precise": "c:@S@Foo@F@Foo#"
       },
       "kind": {
-        "displayName": "Constructor",
+        "displayName": "Instance Method",
         "identifier": "c++.method"
       },
       "location": {
@@ -193,7 +193,7 @@
         "precise": "c:@S@Foo@F@~Foo#"
       },
       "kind": {
-        "displayName": "Destructor",
+        "displayName": "Instance Method",
         "identifier": "c++.method"
       },
       "location": {
Index: clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
===================================================================
--- clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -872,9 +872,6 @@
     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);
 }
@@ -886,9 +883,6 @@
     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);
 }
@@ -900,8 +894,6 @@
     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);
@@ -914,13 +906,33 @@
     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)
@@ -947,6 +959,17 @@
                         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)
@@ -1002,7 +1025,7 @@
 
 void SymbolGraphSerializer::visitGlobalFunctionTemplateSpecRecord(
     const GlobalFunctionTemplateSpecRecord &Record) {
-  auto GlobalFunctionTemplateSpec= serializeAPIRecord(Record);
+  auto GlobalFunctionTemplateSpec = serializeAPIRecord(Record);
   if (!GlobalFunctionTemplateSpec)
     return;
   Symbols.emplace_back(std::move(*GlobalFunctionTemplateSpec));
Index: clang/lib/ExtractAPI/API.cpp
===================================================================
--- clang/lib/ExtractAPI/API.cpp
+++ clang/lib/ExtractAPI/API.cpp
@@ -170,18 +170,17 @@
 }
 
 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(
@@ -277,50 +276,38 @@
                            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(
Index: clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
===================================================================
--- clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
+++ clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
@@ -175,10 +175,16 @@
   void visitClassTemplatePartialSpecRecord(
       const ClassTemplatePartialSpecRecord &Record);
 
+  void visitCXXInstanceMethodRecord(const CXXInstanceMethodRecord &Record);
+
+  void visitCXXStaticMethodRecord(const CXXStaticMethodRecord &Record);
+
   void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record);
 
   void visitMethodTemplateSpecRecord(const CXXMethodTemplateSpecRecord &Record);
 
+  void visitCXXFieldRecord(const CXXFieldRecord &Record);
+
   void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record);
 
   void visitConceptRecord(const ConceptRecord &Record);
Index: clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
===================================================================
--- clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
+++ clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
@@ -39,10 +39,16 @@
 
     getDerived()->traverseClassTemplatePartialSpecRecords();
 
+    getDerived()->traverseCXXInstanceMethods();
+
+    getDerived()->traverseCXXStaticMethods();
+
     getDerived()->traverseCXXMethodTemplates();
 
     getDerived()->traverseCXXMethodTemplateSpecializations();
 
+    getDerived()->traverseCXXFields();
+
     getDerived()->traverseCXXFieldTemplates();
 
     getDerived()->traverseConcepts();
@@ -126,6 +132,21 @@
           *ClassTemplatePartialSpec.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);
@@ -212,6 +233,10 @@
   void visitClassTemplatePartialSpecRecord(
       const ClassTemplatePartialSpecRecord &Record){};
 
+  void visitCXXInstanceRecord(const CXXInstanceMethodRecord &Record){};
+
+  void visitCXXStaticRecord(const CXXStaticMethodRecord &Record){};
+
   void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record){};
 
   void
Index: clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
===================================================================
--- clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
+++ clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
@@ -50,6 +50,8 @@
 
   bool VisitEnumDecl(const EnumDecl *Decl);
 
+  bool WalkUpFromFunctionDecl(const FunctionDecl *Decl);
+
   bool WalkUpFromRecordDecl(const RecordDecl *Decl);
 
   bool WalkUpFromCXXRecordDecl(const CXXRecordDecl *Decl);
@@ -78,6 +80,14 @@
 
   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 @@
   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,
@@ -355,6 +351,13 @@
   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) {
@@ -518,9 +521,6 @@
     CXXClassRecord->Bases.emplace_back(BaseClass);
   }
 
-  getDerivedExtractAPIVisitor().recordCXXFields(CXXClassRecord, Decl->fields());
-  getDerivedExtractAPIVisitor().recordCXXMethods(CXXClassRecord,
-                                                 Decl->methods());
   return true;
 }
 
@@ -530,18 +530,12 @@
   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());
@@ -552,15 +546,18 @@
                                             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 *Template = 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(Template),
         SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl),
         DeclarationFragmentsBuilder::getAccessControl(Template),
@@ -568,13 +565,93 @@
         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;
 }
 
@@ -637,10 +714,6 @@
     ClassTemplateSpecializationRecord->Bases.emplace_back(BaseClass);
   }
 
-  getDerivedExtractAPIVisitor().recordCXXFields(
-      ClassTemplateSpecializationRecord, Decl->fields());
-  getDerivedExtractAPIVisitor().recordCXXMethods(
-      ClassTemplateSpecializationRecord, Decl->methods());
   return true;
 }
 
@@ -681,10 +754,6 @@
     ClassTemplatePartialSpecRecord->Bases.emplace_back(BaseClass);
   }
 
-  getDerivedExtractAPIVisitor().recordCXXFields(ClassTemplatePartialSpecRecord,
-                                                Decl->fields());
-  getDerivedExtractAPIVisitor().recordCXXMethods(ClassTemplatePartialSpecRecord,
-                                                 Decl->methods());
   return true;
 }
 
@@ -1067,155 +1136,74 @@
 }
 
 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
Index: clang/include/clang/ExtractAPI/API.h
===================================================================
--- clang/include/clang/ExtractAPI/API.h
+++ clang/include/clang/ExtractAPI/API.h
@@ -1013,7 +1013,9 @@
 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<GlobalFunctionTemplateRecord>
     : public std::true_type {};
@@ -1028,7 +1030,8 @@
     : 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 {};
@@ -1159,7 +1162,7 @@
                  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,
@@ -1212,18 +1215,25 @@
       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(
@@ -1398,6 +1408,13 @@
   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<CXXMethodTemplateSpecRecord> &
   getCXXMethodTemplateSpecializations() const {
     return CXXMethodTemplateSpecializations;
@@ -1484,6 +1501,10 @@
   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<CXXMethodTemplateSpecRecord> CXXMethodTemplateSpecializations;
   RecordMap<CXXFieldTemplateRecord> CXXFieldTemplates;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to