Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:54

0001 //===- ExtractAPI/ExtractAPIVisitor.h ---------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// This file defines the ExtractAPVisitor AST visitation interface.
0011 ///
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H
0015 #define LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H
0016 
0017 #include "clang/AST/ASTContext.h"
0018 #include "clang/AST/Decl.h"
0019 #include "clang/AST/DeclCXX.h"
0020 #include "clang/AST/DeclObjC.h"
0021 #include "clang/AST/DeclTemplate.h"
0022 #include "clang/AST/ParentMapContext.h"
0023 #include "clang/AST/RecursiveASTVisitor.h"
0024 #include "clang/Basic/LLVM.h"
0025 #include "clang/Basic/Module.h"
0026 #include "clang/Basic/SourceManager.h"
0027 #include "clang/Basic/Specifiers.h"
0028 #include "clang/ExtractAPI/API.h"
0029 #include "clang/ExtractAPI/DeclarationFragments.h"
0030 #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
0031 #include "clang/Index/USRGeneration.h"
0032 #include "llvm/ADT/SmallString.h"
0033 #include "llvm/ADT/StringRef.h"
0034 #include "llvm/Support/Casting.h"
0035 #include <type_traits>
0036 
0037 namespace clang {
0038 namespace extractapi {
0039 namespace impl {
0040 
0041 template <typename Derived>
0042 class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
0043   using Base = RecursiveASTVisitor<Derived>;
0044 
0045 protected:
0046   ExtractAPIVisitorBase(ASTContext &Context, APISet &API)
0047       : Context(Context), API(API) {}
0048 
0049 public:
0050   const APISet &getAPI() const { return API; }
0051 
0052   bool VisitVarDecl(const VarDecl *Decl);
0053 
0054   bool VisitFunctionDecl(const FunctionDecl *Decl);
0055 
0056   bool VisitEnumDecl(const EnumDecl *Decl);
0057 
0058   bool WalkUpFromFunctionDecl(const FunctionDecl *Decl);
0059 
0060   bool WalkUpFromRecordDecl(const RecordDecl *Decl);
0061 
0062   bool WalkUpFromCXXRecordDecl(const CXXRecordDecl *Decl);
0063 
0064   bool WalkUpFromCXXMethodDecl(const CXXMethodDecl *Decl);
0065 
0066   bool WalkUpFromClassTemplateSpecializationDecl(
0067       const ClassTemplateSpecializationDecl *Decl);
0068 
0069   bool WalkUpFromClassTemplatePartialSpecializationDecl(
0070       const ClassTemplatePartialSpecializationDecl *Decl);
0071 
0072   bool WalkUpFromVarTemplateDecl(const VarTemplateDecl *Decl);
0073 
0074   bool WalkUpFromVarTemplateSpecializationDecl(
0075       const VarTemplateSpecializationDecl *Decl);
0076 
0077   bool WalkUpFromVarTemplatePartialSpecializationDecl(
0078       const VarTemplatePartialSpecializationDecl *Decl);
0079 
0080   bool WalkUpFromFunctionTemplateDecl(const FunctionTemplateDecl *Decl);
0081 
0082   bool WalkUpFromNamespaceDecl(const NamespaceDecl *Decl);
0083 
0084   bool VisitNamespaceDecl(const NamespaceDecl *Decl);
0085 
0086   bool TraverseRecordDecl(RecordDecl *Decl);
0087   bool VisitRecordDecl(const RecordDecl *Decl);
0088 
0089   bool TraverseCXXRecordDecl(CXXRecordDecl *Decl);
0090   bool VisitCXXRecordDecl(const CXXRecordDecl *Decl);
0091 
0092   bool VisitCXXMethodDecl(const CXXMethodDecl *Decl);
0093 
0094   bool VisitFieldDecl(const FieldDecl *Decl);
0095 
0096   bool VisitCXXConversionDecl(const CXXConversionDecl *Decl);
0097 
0098   bool VisitCXXConstructorDecl(const CXXConstructorDecl *Decl);
0099 
0100   bool VisitCXXDestructorDecl(const CXXDestructorDecl *Decl);
0101 
0102   bool VisitConceptDecl(const ConceptDecl *Decl);
0103 
0104   bool VisitClassTemplateSpecializationDecl(
0105       const ClassTemplateSpecializationDecl *Decl);
0106 
0107   bool VisitClassTemplatePartialSpecializationDecl(
0108       const ClassTemplatePartialSpecializationDecl *Decl);
0109 
0110   bool VisitVarTemplateDecl(const VarTemplateDecl *Decl);
0111 
0112   bool
0113   VisitVarTemplateSpecializationDecl(const VarTemplateSpecializationDecl *Decl);
0114 
0115   bool VisitVarTemplatePartialSpecializationDecl(
0116       const VarTemplatePartialSpecializationDecl *Decl);
0117 
0118   bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *Decl);
0119 
0120   bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *Decl);
0121 
0122   bool VisitObjCProtocolDecl(const ObjCProtocolDecl *Decl);
0123 
0124   bool VisitTypedefNameDecl(const TypedefNameDecl *Decl);
0125 
0126   bool VisitObjCCategoryDecl(const ObjCCategoryDecl *Decl);
0127 
0128   bool shouldDeclBeIncluded(const Decl *Decl) const;
0129 
0130   const RawComment *fetchRawCommentForDecl(const Decl *Decl) const;
0131 
0132 protected:
0133   /// Collect API information for the enum constants and associate with the
0134   /// parent enum.
0135   void recordEnumConstants(SymbolReference Container,
0136                            const EnumDecl::enumerator_range Constants);
0137 
0138   /// Collect API information for the Objective-C methods and associate with the
0139   /// parent container.
0140   void recordObjCMethods(ObjCContainerRecord *Container,
0141                          const ObjCContainerDecl::method_range Methods);
0142 
0143   void recordObjCProperties(ObjCContainerRecord *Container,
0144                             const ObjCContainerDecl::prop_range Properties);
0145 
0146   void recordObjCInstanceVariables(
0147       ObjCContainerRecord *Container,
0148       const llvm::iterator_range<
0149           DeclContext::specific_decl_iterator<ObjCIvarDecl>>
0150           Ivars);
0151 
0152   void recordObjCProtocols(ObjCContainerRecord *Container,
0153                            ObjCInterfaceDecl::protocol_range Protocols);
0154 
0155   ASTContext &Context;
0156   APISet &API;
0157 
0158   StringRef getTypedefName(const TagDecl *Decl) {
0159     if (const auto *TypedefDecl = Decl->getTypedefNameForAnonDecl())
0160       return TypedefDecl->getName();
0161 
0162     return {};
0163   }
0164 
0165   bool isInSystemHeader(const Decl *D) {
0166     return Context.getSourceManager().isInSystemHeader(D->getLocation());
0167   }
0168 
0169 private:
0170   Derived &getDerivedExtractAPIVisitor() {
0171     return *static_cast<Derived *>(this);
0172   }
0173 
0174 protected:
0175   SmallVector<SymbolReference> getBases(const CXXRecordDecl *Decl) {
0176     // FIXME: store AccessSpecifier given by inheritance
0177     SmallVector<SymbolReference> Bases;
0178     for (const auto &BaseSpecifier : Decl->bases()) {
0179       // skip classes not inherited as public
0180       if (BaseSpecifier.getAccessSpecifier() != AccessSpecifier::AS_public)
0181         continue;
0182       if (auto *BaseDecl = BaseSpecifier.getType()->getAsTagDecl()) {
0183         Bases.emplace_back(createSymbolReferenceForDecl(*BaseDecl));
0184       } else {
0185         SymbolReference BaseClass;
0186         BaseClass.Name = API.copyString(BaseSpecifier.getType().getAsString(
0187             Decl->getASTContext().getPrintingPolicy()));
0188 
0189         if (BaseSpecifier.getType().getTypePtr()->isTemplateTypeParmType()) {
0190           if (auto *TTPTD = BaseSpecifier.getType()
0191                                 ->getAs<TemplateTypeParmType>()
0192                                 ->getDecl()) {
0193             SmallString<128> USR;
0194             index::generateUSRForDecl(TTPTD, USR);
0195             BaseClass.USR = API.copyString(USR);
0196             BaseClass.Source = API.copyString(getOwningModuleName(*TTPTD));
0197           }
0198         }
0199         Bases.emplace_back(BaseClass);
0200       }
0201     }
0202     return Bases;
0203   }
0204 
0205   APIRecord::RecordKind getKindForDisplay(const CXXRecordDecl *Decl) {
0206     if (Decl->isUnion())
0207       return APIRecord::RK_Union;
0208     if (Decl->isStruct())
0209       return APIRecord::RK_Struct;
0210 
0211     return APIRecord::RK_CXXClass;
0212   }
0213 
0214   StringRef getOwningModuleName(const Decl &D) {
0215     if (auto *OwningModule = D.getImportedOwningModule())
0216       return OwningModule->getTopLevelModule()->Name;
0217 
0218     return {};
0219   }
0220 
0221   SymbolReference createHierarchyInformationForDecl(const Decl &D) {
0222     const auto *Context = cast_if_present<Decl>(D.getDeclContext());
0223 
0224     if (!Context || isa<TranslationUnitDecl>(Context))
0225       return {};
0226 
0227     return createSymbolReferenceForDecl(*Context);
0228   }
0229 
0230   SymbolReference createSymbolReferenceForDecl(const Decl &D) {
0231     SmallString<128> USR;
0232     index::generateUSRForDecl(&D, USR);
0233 
0234     APIRecord *Record = API.findRecordForUSR(USR);
0235     if (Record)
0236       return SymbolReference(Record);
0237 
0238     StringRef Name;
0239     if (auto *ND = dyn_cast<NamedDecl>(&D))
0240       Name = ND->getName();
0241 
0242     return API.createSymbolReference(Name, USR, getOwningModuleName(D));
0243   }
0244 
0245   bool isEmbeddedInVarDeclarator(const TagDecl &D) {
0246     return D.getName().empty() && getTypedefName(&D).empty() &&
0247            D.isEmbeddedInDeclarator() && !D.isFreeStanding();
0248   }
0249 
0250   void maybeMergeWithAnonymousTag(const DeclaratorDecl &D,
0251                                   RecordContext *NewRecordContext) {
0252     if (!NewRecordContext)
0253       return;
0254     auto *Tag = D.getType()->getAsTagDecl();
0255     SmallString<128> TagUSR;
0256     clang::index::generateUSRForDecl(Tag, TagUSR);
0257     if (auto *Record = llvm::dyn_cast_if_present<TagRecord>(
0258             API.findRecordForUSR(TagUSR))) {
0259       if (Record->IsEmbeddedInVarDeclarator) {
0260         NewRecordContext->stealRecordChain(*Record);
0261         API.removeRecord(Record);
0262       }
0263     }
0264   }
0265 };
0266 
0267 template <typename Derived>
0268 bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
0269   // skip function parameters.
0270   if (isa<ParmVarDecl>(Decl))
0271     return true;
0272 
0273   // Skip non-global variables in records (struct/union/class) but not static
0274   // members.
0275   if (Decl->getDeclContext()->isRecord() && !Decl->isStaticDataMember())
0276     return true;
0277 
0278   // Skip local variables inside function or method.
0279   if (!Decl->isDefinedOutsideFunctionOrMethod())
0280     return true;
0281 
0282   // If this is a template but not specialization or instantiation, skip.
0283   if (Decl->getASTContext().getTemplateOrSpecializationInfo(Decl) &&
0284       Decl->getTemplateSpecializationKind() == TSK_Undeclared)
0285     return true;
0286 
0287   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
0288     return true;
0289 
0290   // Collect symbol information.
0291   StringRef Name = Decl->getName();
0292   SmallString<128> USR;
0293   index::generateUSRForDecl(Decl, USR);
0294   PresumedLoc Loc =
0295       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0296   LinkageInfo Linkage = Decl->getLinkageAndVisibility();
0297   DocComment Comment;
0298   if (auto *RawComment =
0299           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0300     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0301                                             Context.getDiagnostics());
0302 
0303   // Build declaration fragments and sub-heading for the variable.
0304   DeclarationFragments Declaration =
0305       DeclarationFragmentsBuilder::getFragmentsForVar(Decl);
0306   DeclarationFragments SubHeading =
0307       DeclarationFragmentsBuilder::getSubHeading(Decl);
0308   if (Decl->isStaticDataMember()) {
0309     auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
0310     API.createRecord<StaticFieldRecord>(
0311         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0312         AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
0313         SubHeading, Access, isInSystemHeader(Decl));
0314   } else {
0315     // Add the global variable record to the API set.
0316     auto *NewRecord = API.createRecord<GlobalVariableRecord>(
0317         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0318         AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
0319         SubHeading, isInSystemHeader(Decl));
0320 
0321     // If this global variable has a non typedef'd anonymous tag type let's
0322     // pretend the type's child records are under us in the hierarchy.
0323     maybeMergeWithAnonymousTag(*Decl, NewRecord);
0324   }
0325 
0326   return true;
0327 }
0328 
0329 template <typename Derived>
0330 bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
0331     const FunctionDecl *Decl) {
0332   if (const auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
0333     // Skip member function in class templates.
0334     if (Method->getParent()->getDescribedClassTemplate() != nullptr)
0335       return true;
0336 
0337     // Skip methods in records.
0338     for (const auto &P : Context.getParents(*Method)) {
0339       if (P.template get<CXXRecordDecl>())
0340         return true;
0341     }
0342 
0343     // Skip ConstructorDecl and DestructorDecl.
0344     if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method))
0345       return true;
0346   }
0347 
0348   // Skip templated functions that aren't processed here.
0349   switch (Decl->getTemplatedKind()) {
0350   case FunctionDecl::TK_NonTemplate:
0351   case FunctionDecl::TK_DependentNonTemplate:
0352   case FunctionDecl::TK_FunctionTemplateSpecialization:
0353     break;
0354   case FunctionDecl::TK_FunctionTemplate:
0355   case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
0356   case FunctionDecl::TK_MemberSpecialization:
0357     return true;
0358   }
0359 
0360   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
0361     return true;
0362 
0363   // Collect symbol information.
0364   auto Name = Decl->getNameAsString();
0365   SmallString<128> USR;
0366   index::generateUSRForDecl(Decl, USR);
0367   PresumedLoc Loc =
0368       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0369   LinkageInfo Linkage = Decl->getLinkageAndVisibility();
0370   DocComment Comment;
0371   if (auto *RawComment =
0372           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0373     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0374                                             Context.getDiagnostics());
0375 
0376   // Build declaration fragments, sub-heading, and signature of the function.
0377   DeclarationFragments SubHeading =
0378       DeclarationFragmentsBuilder::getSubHeading(Decl);
0379   FunctionSignature Signature =
0380       DeclarationFragmentsBuilder::getFunctionSignature(Decl);
0381   if (Decl->getTemplateSpecializationInfo())
0382     API.createRecord<GlobalFunctionTemplateSpecializationRecord>(
0383         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0384         AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
0385         DeclarationFragmentsBuilder::
0386             getFragmentsForFunctionTemplateSpecialization(Decl),
0387         SubHeading, Signature, isInSystemHeader(Decl));
0388   else
0389     // Add the function record to the API set.
0390     API.createRecord<GlobalFunctionRecord>(
0391         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0392         AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
0393         DeclarationFragmentsBuilder::getFragmentsForFunction(Decl), SubHeading,
0394         Signature, isInSystemHeader(Decl));
0395   return true;
0396 }
0397 
0398 template <typename Derived>
0399 bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
0400   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
0401     return true;
0402 
0403   SmallString<128> USR;
0404   index::generateUSRForDecl(Decl, USR);
0405   PresumedLoc Loc =
0406       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0407   DocComment Comment;
0408   if (auto *RawComment =
0409           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0410     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0411                                             Context.getDiagnostics());
0412 
0413   // Build declaration fragments and sub-heading for the enum.
0414   DeclarationFragments Declaration =
0415       DeclarationFragmentsBuilder::getFragmentsForEnum(Decl);
0416   DeclarationFragments SubHeading =
0417       DeclarationFragmentsBuilder::getSubHeading(Decl);
0418 
0419   // Collect symbol information.
0420   SymbolReference ParentContainer;
0421 
0422   if (Decl->hasNameForLinkage()) {
0423     StringRef Name = Decl->getName();
0424     if (Name.empty())
0425       Name = getTypedefName(Decl);
0426 
0427     auto *ER = API.createRecord<EnumRecord>(
0428         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0429         AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
0430         SubHeading, isInSystemHeader(Decl), false);
0431     ParentContainer = SymbolReference(ER);
0432   } else {
0433     // If this an anonymous enum then the parent scope of the constants is the
0434     // top level namespace.
0435     ParentContainer = {};
0436   }
0437 
0438   // Now collect information about the enumerators in this enum.
0439   getDerivedExtractAPIVisitor().recordEnumConstants(ParentContainer,
0440                                                     Decl->enumerators());
0441 
0442   return true;
0443 }
0444 
0445 template <typename Derived>
0446 bool ExtractAPIVisitorBase<Derived>::WalkUpFromFunctionDecl(
0447     const FunctionDecl *Decl) {
0448   getDerivedExtractAPIVisitor().VisitFunctionDecl(Decl);
0449   return true;
0450 }
0451 
0452 template <typename Derived>
0453 bool ExtractAPIVisitorBase<Derived>::WalkUpFromRecordDecl(
0454     const RecordDecl *Decl) {
0455   getDerivedExtractAPIVisitor().VisitRecordDecl(Decl);
0456   return true;
0457 }
0458 
0459 template <typename Derived>
0460 bool ExtractAPIVisitorBase<Derived>::WalkUpFromCXXRecordDecl(
0461     const CXXRecordDecl *Decl) {
0462   getDerivedExtractAPIVisitor().VisitCXXRecordDecl(Decl);
0463   return true;
0464 }
0465 
0466 template <typename Derived>
0467 bool ExtractAPIVisitorBase<Derived>::WalkUpFromCXXMethodDecl(
0468     const CXXMethodDecl *Decl) {
0469   getDerivedExtractAPIVisitor().VisitCXXMethodDecl(Decl);
0470   return true;
0471 }
0472 
0473 template <typename Derived>
0474 bool ExtractAPIVisitorBase<Derived>::WalkUpFromClassTemplateSpecializationDecl(
0475     const ClassTemplateSpecializationDecl *Decl) {
0476   getDerivedExtractAPIVisitor().VisitClassTemplateSpecializationDecl(Decl);
0477   return true;
0478 }
0479 
0480 template <typename Derived>
0481 bool ExtractAPIVisitorBase<Derived>::
0482     WalkUpFromClassTemplatePartialSpecializationDecl(
0483         const ClassTemplatePartialSpecializationDecl *Decl) {
0484   getDerivedExtractAPIVisitor().VisitClassTemplatePartialSpecializationDecl(
0485       Decl);
0486   return true;
0487 }
0488 
0489 template <typename Derived>
0490 bool ExtractAPIVisitorBase<Derived>::WalkUpFromVarTemplateDecl(
0491     const VarTemplateDecl *Decl) {
0492   getDerivedExtractAPIVisitor().VisitVarTemplateDecl(Decl);
0493   return true;
0494 }
0495 
0496 template <typename Derived>
0497 bool ExtractAPIVisitorBase<Derived>::WalkUpFromVarTemplateSpecializationDecl(
0498     const VarTemplateSpecializationDecl *Decl) {
0499   getDerivedExtractAPIVisitor().VisitVarTemplateSpecializationDecl(Decl);
0500   return true;
0501 }
0502 
0503 template <typename Derived>
0504 bool ExtractAPIVisitorBase<Derived>::
0505     WalkUpFromVarTemplatePartialSpecializationDecl(
0506         const VarTemplatePartialSpecializationDecl *Decl) {
0507   getDerivedExtractAPIVisitor().VisitVarTemplatePartialSpecializationDecl(Decl);
0508   return true;
0509 }
0510 
0511 template <typename Derived>
0512 bool ExtractAPIVisitorBase<Derived>::WalkUpFromFunctionTemplateDecl(
0513     const FunctionTemplateDecl *Decl) {
0514   getDerivedExtractAPIVisitor().VisitFunctionTemplateDecl(Decl);
0515   return true;
0516 }
0517 
0518 template <typename Derived>
0519 bool ExtractAPIVisitorBase<Derived>::WalkUpFromNamespaceDecl(
0520     const NamespaceDecl *Decl) {
0521   getDerivedExtractAPIVisitor().VisitNamespaceDecl(Decl);
0522   return true;
0523 }
0524 
0525 template <typename Derived>
0526 bool ExtractAPIVisitorBase<Derived>::VisitNamespaceDecl(
0527     const NamespaceDecl *Decl) {
0528   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
0529     return true;
0530   if (Decl->isAnonymousNamespace())
0531     return true;
0532   StringRef Name = Decl->getName();
0533   SmallString<128> USR;
0534   index::generateUSRForDecl(Decl, USR);
0535   LinkageInfo Linkage = Decl->getLinkageAndVisibility();
0536   PresumedLoc Loc =
0537       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0538   DocComment Comment;
0539   if (auto *RawComment =
0540           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0541     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0542                                             Context.getDiagnostics());
0543 
0544   // Build declaration fragments and sub-heading for the struct.
0545   DeclarationFragments Declaration =
0546       DeclarationFragmentsBuilder::getFragmentsForNamespace(Decl);
0547   DeclarationFragments SubHeading =
0548       DeclarationFragmentsBuilder::getSubHeading(Decl);
0549   API.createRecord<NamespaceRecord>(
0550       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0551       AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
0552       SubHeading, isInSystemHeader(Decl));
0553 
0554   return true;
0555 }
0556 
0557 template <typename Derived>
0558 bool ExtractAPIVisitorBase<Derived>::TraverseRecordDecl(RecordDecl *Decl) {
0559   bool Ret = Base::TraverseRecordDecl(Decl);
0560 
0561   if (!isEmbeddedInVarDeclarator(*Decl) && Decl->isAnonymousStructOrUnion()) {
0562     SmallString<128> USR;
0563     index::generateUSRForDecl(Decl, USR);
0564     API.removeRecord(USR);
0565   }
0566 
0567   return Ret;
0568 }
0569 
0570 template <typename Derived>
0571 bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
0572   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
0573     return true;
0574 
0575   // Collect symbol information.
0576   StringRef Name = Decl->getName();
0577   if (Name.empty())
0578     Name = getTypedefName(Decl);
0579 
0580   SmallString<128> USR;
0581   index::generateUSRForDecl(Decl, USR);
0582   PresumedLoc Loc =
0583       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0584   DocComment Comment;
0585   if (auto *RawComment =
0586           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0587     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0588                                             Context.getDiagnostics());
0589 
0590   // Build declaration fragments and sub-heading for the struct.
0591   DeclarationFragments Declaration =
0592       DeclarationFragmentsBuilder::getFragmentsForRecordDecl(Decl);
0593   DeclarationFragments SubHeading =
0594       DeclarationFragmentsBuilder::getSubHeading(Decl);
0595 
0596   if (Decl->isUnion())
0597     API.createRecord<UnionRecord>(
0598         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0599         AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
0600         SubHeading, isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));
0601   else
0602     API.createRecord<StructRecord>(
0603         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0604         AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
0605         SubHeading, isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));
0606 
0607   return true;
0608 }
0609 
0610 template <typename Derived>
0611 bool ExtractAPIVisitorBase<Derived>::TraverseCXXRecordDecl(
0612     CXXRecordDecl *Decl) {
0613   bool Ret = Base::TraverseCXXRecordDecl(Decl);
0614 
0615   if (!isEmbeddedInVarDeclarator(*Decl) && Decl->isAnonymousStructOrUnion()) {
0616     SmallString<128> USR;
0617     index::generateUSRForDecl(Decl, USR);
0618     API.removeRecord(USR);
0619   }
0620 
0621   return Ret;
0622 }
0623 
0624 template <typename Derived>
0625 bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
0626     const CXXRecordDecl *Decl) {
0627   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
0628       Decl->isImplicit())
0629     return true;
0630 
0631   StringRef Name = Decl->getName();
0632   if (Name.empty())
0633     Name = getTypedefName(Decl);
0634 
0635   SmallString<128> USR;
0636   index::generateUSRForDecl(Decl, USR);
0637   PresumedLoc Loc =
0638       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0639   DocComment Comment;
0640   if (auto *RawComment =
0641           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0642     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0643                                             Context.getDiagnostics());
0644   DeclarationFragments Declaration =
0645       DeclarationFragmentsBuilder::getFragmentsForCXXClass(Decl);
0646   DeclarationFragments SubHeading =
0647       DeclarationFragmentsBuilder::getSubHeading(Decl);
0648 
0649   auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
0650 
0651   CXXClassRecord *Record;
0652   if (Decl->getDescribedClassTemplate()) {
0653     // Inject template fragments before class fragments.
0654     Declaration.prepend(
0655         DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
0656             Decl->getDescribedClassTemplate()));
0657     Record = API.createRecord<ClassTemplateRecord>(
0658         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0659         AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
0660         SubHeading, Template(Decl->getDescribedClassTemplate()), Access,
0661         isInSystemHeader(Decl));
0662   } else {
0663     Record = API.createRecord<CXXClassRecord>(
0664         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0665         AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
0666         SubHeading, APIRecord::RecordKind::RK_CXXClass, Access,
0667         isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl));
0668   }
0669 
0670   Record->KindForDisplay = getKindForDisplay(Decl);
0671   Record->Bases = getBases(Decl);
0672 
0673   return true;
0674 }
0675 
0676 template <typename Derived>
0677 bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
0678     const CXXMethodDecl *Decl) {
0679   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
0680       Decl->isImplicit())
0681     return true;
0682 
0683   if (isa<CXXConversionDecl>(Decl))
0684     return true;
0685   if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
0686     return true;
0687 
0688   SmallString<128> USR;
0689   index::generateUSRForDecl(Decl, USR);
0690   PresumedLoc Loc =
0691       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0692   DocComment Comment;
0693   if (auto *RawComment =
0694           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0695     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0696                                             Context.getDiagnostics());
0697   DeclarationFragments SubHeading =
0698       DeclarationFragmentsBuilder::getSubHeading(Decl);
0699   auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
0700   auto Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl);
0701 
0702   if (FunctionTemplateDecl *TemplateDecl =
0703           Decl->getDescribedFunctionTemplate()) {
0704     API.createRecord<CXXMethodTemplateRecord>(
0705         USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl),
0706         Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
0707         DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
0708             TemplateDecl),
0709         SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl),
0710         DeclarationFragmentsBuilder::getAccessControl(TemplateDecl),
0711         Template(TemplateDecl), isInSystemHeader(Decl));
0712   } else if (Decl->getTemplateSpecializationInfo())
0713     API.createRecord<CXXMethodTemplateSpecializationRecord>(
0714         USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl),
0715         Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
0716         DeclarationFragmentsBuilder::
0717             getFragmentsForFunctionTemplateSpecialization(Decl),
0718         SubHeading, Signature, Access, isInSystemHeader(Decl));
0719   else if (Decl->isOverloadedOperator())
0720     API.createRecord<CXXInstanceMethodRecord>(
0721         USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl),
0722         Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
0723         DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(Decl),
0724         SubHeading, Signature, Access, isInSystemHeader(Decl));
0725   else if (Decl->isStatic())
0726     API.createRecord<CXXStaticMethodRecord>(
0727         USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl),
0728         Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
0729         DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
0730         Signature, Access, isInSystemHeader(Decl));
0731   else
0732     API.createRecord<CXXInstanceMethodRecord>(
0733         USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl),
0734         Loc, AvailabilityInfo::createFromDecl(Decl), Comment,
0735         DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading,
0736         Signature, Access, isInSystemHeader(Decl));
0737 
0738   return true;
0739 }
0740 
0741 template <typename Derived>
0742 bool ExtractAPIVisitorBase<Derived>::VisitCXXConstructorDecl(
0743     const CXXConstructorDecl *Decl) {
0744   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
0745       Decl->isImplicit())
0746     return true;
0747 
0748   auto Name = Decl->getNameAsString();
0749   SmallString<128> USR;
0750   index::generateUSRForDecl(Decl, USR);
0751   PresumedLoc Loc =
0752       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0753   DocComment Comment;
0754   if (auto *RawComment =
0755           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0756     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0757                                             Context.getDiagnostics());
0758 
0759   // Build declaration fragments, sub-heading, and signature for the method.
0760   DeclarationFragments Declaration =
0761       DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(Decl);
0762   DeclarationFragments SubHeading =
0763       DeclarationFragmentsBuilder::getSubHeading(Decl);
0764   FunctionSignature Signature =
0765       DeclarationFragmentsBuilder::getFunctionSignature(Decl);
0766   AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
0767 
0768   API.createRecord<CXXConstructorRecord>(
0769       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0770       AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
0771       Signature, Access, isInSystemHeader(Decl));
0772   return true;
0773 }
0774 
0775 template <typename Derived>
0776 bool ExtractAPIVisitorBase<Derived>::VisitCXXDestructorDecl(
0777     const CXXDestructorDecl *Decl) {
0778   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
0779       Decl->isImplicit())
0780     return true;
0781 
0782   auto Name = Decl->getNameAsString();
0783   SmallString<128> USR;
0784   index::generateUSRForDecl(Decl, USR);
0785   PresumedLoc Loc =
0786       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0787   DocComment Comment;
0788   if (auto *RawComment =
0789           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0790     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0791                                             Context.getDiagnostics());
0792 
0793   // Build declaration fragments, sub-heading, and signature for the method.
0794   DeclarationFragments Declaration =
0795       DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(Decl);
0796   DeclarationFragments SubHeading =
0797       DeclarationFragmentsBuilder::getSubHeading(Decl);
0798   FunctionSignature Signature =
0799       DeclarationFragmentsBuilder::getFunctionSignature(Decl);
0800   AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
0801   API.createRecord<CXXDestructorRecord>(
0802       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0803       AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
0804       Signature, Access, isInSystemHeader(Decl));
0805   return true;
0806 }
0807 
0808 template <typename Derived>
0809 bool ExtractAPIVisitorBase<Derived>::VisitConceptDecl(const ConceptDecl *Decl) {
0810   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
0811     return true;
0812 
0813   StringRef Name = Decl->getName();
0814   SmallString<128> USR;
0815   index::generateUSRForDecl(Decl, USR);
0816   PresumedLoc Loc =
0817       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0818   DocComment Comment;
0819   if (auto *RawComment =
0820           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0821     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0822                                             Context.getDiagnostics());
0823   DeclarationFragments Declaration =
0824       DeclarationFragmentsBuilder::getFragmentsForConcept(Decl);
0825   DeclarationFragments SubHeading =
0826       DeclarationFragmentsBuilder::getSubHeading(Decl);
0827   API.createRecord<ConceptRecord>(
0828       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0829       AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
0830       Template(Decl), isInSystemHeader(Decl));
0831   return true;
0832 }
0833 
0834 template <typename Derived>
0835 bool ExtractAPIVisitorBase<Derived>::VisitClassTemplateSpecializationDecl(
0836     const ClassTemplateSpecializationDecl *Decl) {
0837   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
0838     return true;
0839 
0840   StringRef Name = Decl->getName();
0841   SmallString<128> USR;
0842   index::generateUSRForDecl(Decl, USR);
0843   PresumedLoc Loc =
0844       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0845   DocComment Comment;
0846   if (auto *RawComment =
0847           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0848     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0849                                             Context.getDiagnostics());
0850   DeclarationFragments Declaration =
0851       DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
0852           Decl);
0853   DeclarationFragments SubHeading =
0854       DeclarationFragmentsBuilder::getSubHeading(Decl);
0855 
0856   auto *CTSR = API.createRecord<ClassTemplateSpecializationRecord>(
0857       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0858       AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
0859       DeclarationFragmentsBuilder::getAccessControl(Decl),
0860       isInSystemHeader(Decl));
0861 
0862   CTSR->Bases = getBases(Decl);
0863 
0864   return true;
0865 }
0866 
0867 template <typename Derived>
0868 bool ExtractAPIVisitorBase<Derived>::
0869     VisitClassTemplatePartialSpecializationDecl(
0870         const ClassTemplatePartialSpecializationDecl *Decl) {
0871   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
0872     return true;
0873 
0874   StringRef Name = Decl->getName();
0875   SmallString<128> USR;
0876   index::generateUSRForDecl(Decl, USR);
0877   PresumedLoc Loc =
0878       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0879   DocComment Comment;
0880   if (auto *RawComment =
0881           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0882     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0883                                             Context.getDiagnostics());
0884   DeclarationFragments Declaration = DeclarationFragmentsBuilder::
0885       getFragmentsForClassTemplatePartialSpecialization(Decl);
0886   DeclarationFragments SubHeading =
0887       DeclarationFragmentsBuilder::getSubHeading(Decl);
0888   auto *CTPSR = API.createRecord<ClassTemplatePartialSpecializationRecord>(
0889       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0890       AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
0891       Template(Decl), DeclarationFragmentsBuilder::getAccessControl(Decl),
0892       isInSystemHeader(Decl));
0893 
0894   CTPSR->KindForDisplay = getKindForDisplay(Decl);
0895   CTPSR->Bases = getBases(Decl);
0896 
0897   return true;
0898 }
0899 
0900 template <typename Derived>
0901 bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateDecl(
0902     const VarTemplateDecl *Decl) {
0903   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
0904     return true;
0905 
0906   // Collect symbol information.
0907   StringRef Name = Decl->getName();
0908   SmallString<128> USR;
0909   index::generateUSRForDecl(Decl, USR);
0910   PresumedLoc Loc =
0911       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0912   LinkageInfo Linkage = Decl->getLinkageAndVisibility();
0913   DocComment Comment;
0914   if (auto *RawComment =
0915           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0916     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0917                                             Context.getDiagnostics());
0918 
0919   // Build declaration fragments and sub-heading for the variable.
0920   DeclarationFragments Declaration;
0921   Declaration
0922       .append(DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
0923           Decl))
0924       .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(
0925           Decl->getTemplatedDecl()));
0926   // Inject template fragments before var fragments.
0927   DeclarationFragments SubHeading =
0928       DeclarationFragmentsBuilder::getSubHeading(Decl);
0929 
0930   if (Decl->getDeclContext()->getDeclKind() == Decl::CXXRecord)
0931     API.createRecord<CXXFieldTemplateRecord>(
0932         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0933         AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
0934         SubHeading, DeclarationFragmentsBuilder::getAccessControl(Decl),
0935         Template(Decl), isInSystemHeader(Decl));
0936   else
0937     API.createRecord<GlobalVariableTemplateRecord>(
0938         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0939         AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
0940         SubHeading, Template(Decl), isInSystemHeader(Decl));
0941   return true;
0942 }
0943 
0944 template <typename Derived>
0945 bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateSpecializationDecl(
0946     const VarTemplateSpecializationDecl *Decl) {
0947   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
0948     return true;
0949 
0950   // Collect symbol information.
0951   StringRef Name = Decl->getName();
0952   SmallString<128> USR;
0953   index::generateUSRForDecl(Decl, USR);
0954   PresumedLoc Loc =
0955       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0956   LinkageInfo Linkage = Decl->getLinkageAndVisibility();
0957   DocComment Comment;
0958   if (auto *RawComment =
0959           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0960     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0961                                             Context.getDiagnostics());
0962 
0963   // Build declaration fragments and sub-heading for the variable.
0964   DeclarationFragments Declaration =
0965       DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
0966           Decl);
0967   DeclarationFragments SubHeading =
0968       DeclarationFragmentsBuilder::getSubHeading(Decl);
0969   API.createRecord<GlobalVariableTemplateSpecializationRecord>(
0970       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
0971       AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
0972       SubHeading, isInSystemHeader(Decl));
0973   return true;
0974 }
0975 
0976 template <typename Derived>
0977 bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
0978     const VarTemplatePartialSpecializationDecl *Decl) {
0979   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
0980     return true;
0981 
0982   // Collect symbol information.
0983   StringRef Name = Decl->getName();
0984   SmallString<128> USR;
0985   index::generateUSRForDecl(Decl, USR);
0986   PresumedLoc Loc =
0987       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
0988   LinkageInfo Linkage = Decl->getLinkageAndVisibility();
0989   DocComment Comment;
0990   if (auto *RawComment =
0991           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
0992     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
0993                                             Context.getDiagnostics());
0994 
0995   // Build declaration fragments and sub-heading for the variable.
0996   DeclarationFragments Declaration = DeclarationFragmentsBuilder::
0997       getFragmentsForVarTemplatePartialSpecialization(Decl);
0998   DeclarationFragments SubHeading =
0999       DeclarationFragmentsBuilder::getSubHeading(Decl);
1000   API.createRecord<GlobalVariableTemplatePartialSpecializationRecord>(
1001       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
1002       AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
1003       SubHeading, Template(Decl), isInSystemHeader(Decl));
1004   return true;
1005 }
1006 
1007 template <typename Derived>
1008 bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
1009     const FunctionTemplateDecl *Decl) {
1010   if (isa<CXXMethodDecl>(Decl->getTemplatedDecl()))
1011     return true;
1012   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
1013     return true;
1014 
1015   // Collect symbol information.
1016   auto Name = Decl->getNameAsString();
1017   SmallString<128> USR;
1018   index::generateUSRForDecl(Decl, USR);
1019   PresumedLoc Loc =
1020       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
1021   LinkageInfo Linkage = Decl->getLinkageAndVisibility();
1022   DocComment Comment;
1023   if (auto *RawComment =
1024           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
1025     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
1026                                             Context.getDiagnostics());
1027 
1028   DeclarationFragments SubHeading =
1029       DeclarationFragmentsBuilder::getSubHeading(Decl);
1030   FunctionSignature Signature =
1031       DeclarationFragmentsBuilder::getFunctionSignature(
1032           Decl->getTemplatedDecl());
1033   API.createRecord<GlobalFunctionTemplateRecord>(
1034       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
1035       AvailabilityInfo::createFromDecl(Decl), Linkage, Comment,
1036       DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(Decl),
1037       SubHeading, Signature, Template(Decl), isInSystemHeader(Decl));
1038 
1039   return true;
1040 }
1041 
1042 template <typename Derived>
1043 bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
1044     const ObjCInterfaceDecl *Decl) {
1045   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
1046     return true;
1047 
1048   // Collect symbol information.
1049   StringRef Name = Decl->getName();
1050   SmallString<128> USR;
1051   index::generateUSRForDecl(Decl, USR);
1052   PresumedLoc Loc =
1053       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
1054   LinkageInfo Linkage = Decl->getLinkageAndVisibility();
1055   DocComment Comment;
1056   if (auto *RawComment =
1057           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
1058     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
1059                                             Context.getDiagnostics());
1060 
1061   // Build declaration fragments and sub-heading for the interface.
1062   DeclarationFragments Declaration =
1063       DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Decl);
1064   DeclarationFragments SubHeading =
1065       DeclarationFragmentsBuilder::getSubHeading(Decl);
1066 
1067   // Collect super class information.
1068   SymbolReference SuperClass;
1069   if (const auto *SuperClassDecl = Decl->getSuperClass())
1070     SuperClass = createSymbolReferenceForDecl(*SuperClassDecl);
1071 
1072   auto *InterfaceRecord = API.createRecord<ObjCInterfaceRecord>(
1073       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
1074       AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration,
1075       SubHeading, SuperClass, isInSystemHeader(Decl));
1076 
1077   // Record all methods (selectors). This doesn't include automatically
1078   // synthesized property methods.
1079   getDerivedExtractAPIVisitor().recordObjCMethods(InterfaceRecord,
1080                                                   Decl->methods());
1081   getDerivedExtractAPIVisitor().recordObjCProperties(InterfaceRecord,
1082                                                      Decl->properties());
1083   getDerivedExtractAPIVisitor().recordObjCInstanceVariables(InterfaceRecord,
1084                                                             Decl->ivars());
1085   getDerivedExtractAPIVisitor().recordObjCProtocols(InterfaceRecord,
1086                                                     Decl->protocols());
1087 
1088   return true;
1089 }
1090 
1091 template <typename Derived>
1092 bool ExtractAPIVisitorBase<Derived>::VisitObjCProtocolDecl(
1093     const ObjCProtocolDecl *Decl) {
1094   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
1095     return true;
1096 
1097   // Collect symbol information.
1098   StringRef Name = Decl->getName();
1099   SmallString<128> USR;
1100   index::generateUSRForDecl(Decl, USR);
1101   PresumedLoc Loc =
1102       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
1103   DocComment Comment;
1104   if (auto *RawComment =
1105           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
1106     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
1107                                             Context.getDiagnostics());
1108 
1109   // Build declaration fragments and sub-heading for the protocol.
1110   DeclarationFragments Declaration =
1111       DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(Decl);
1112   DeclarationFragments SubHeading =
1113       DeclarationFragmentsBuilder::getSubHeading(Decl);
1114 
1115   auto *ProtoRecord = API.createRecord<ObjCProtocolRecord>(
1116       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
1117       AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
1118       isInSystemHeader(Decl));
1119 
1120   getDerivedExtractAPIVisitor().recordObjCMethods(ProtoRecord, Decl->methods());
1121   getDerivedExtractAPIVisitor().recordObjCProperties(ProtoRecord,
1122                                                      Decl->properties());
1123   getDerivedExtractAPIVisitor().recordObjCProtocols(ProtoRecord,
1124                                                     Decl->protocols());
1125 
1126   return true;
1127 }
1128 
1129 template <typename Derived>
1130 bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl(
1131     const TypedefNameDecl *Decl) {
1132   // Skip ObjC Type Parameter for now.
1133   if (isa<ObjCTypeParamDecl>(Decl))
1134     return true;
1135 
1136   if (!Decl->isDefinedOutsideFunctionOrMethod())
1137     return true;
1138 
1139   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
1140     return true;
1141 
1142   StringRef Name = Decl->getName();
1143 
1144   // If the underlying type was defined as part of the typedef modify it's
1145   // fragments directly and pretend the typedef doesn't exist.
1146   if (auto *TagDecl = Decl->getUnderlyingType()->getAsTagDecl()) {
1147     if (TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition() &&
1148         Decl->getName() == TagDecl->getName()) {
1149       SmallString<128> TagUSR;
1150       index::generateUSRForDecl(TagDecl, TagUSR);
1151       if (auto *Record = API.findRecordForUSR(TagUSR)) {
1152         DeclarationFragments LeadingFragments;
1153         LeadingFragments.append("typedef",
1154                                 DeclarationFragments::FragmentKind::Keyword);
1155         LeadingFragments.appendSpace();
1156         Record->Declaration.removeTrailingSemicolon()
1157             .prepend(std::move(LeadingFragments))
1158             .append(" { ... } ", DeclarationFragments::FragmentKind::Text)
1159             .append(Name, DeclarationFragments::FragmentKind::Identifier)
1160             .appendSemicolon();
1161 
1162         return true;
1163       }
1164     }
1165   }
1166 
1167   PresumedLoc Loc =
1168       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
1169   SmallString<128> USR;
1170   index::generateUSRForDecl(Decl, USR);
1171   DocComment Comment;
1172   if (auto *RawComment =
1173           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
1174     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
1175                                             Context.getDiagnostics());
1176 
1177   QualType Type = Decl->getUnderlyingType();
1178   SymbolReference SymRef =
1179       TypedefUnderlyingTypeResolver(Context).getSymbolReferenceForType(Type,
1180                                                                        API);
1181 
1182   API.createRecord<TypedefRecord>(
1183       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
1184       AvailabilityInfo::createFromDecl(Decl), Comment,
1185       DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl),
1186       DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef,
1187       isInSystemHeader(Decl));
1188 
1189   return true;
1190 }
1191 
1192 template <typename Derived>
1193 bool ExtractAPIVisitorBase<Derived>::VisitObjCCategoryDecl(
1194     const ObjCCategoryDecl *Decl) {
1195   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
1196     return true;
1197 
1198   StringRef Name = Decl->getName();
1199   SmallString<128> USR;
1200   index::generateUSRForDecl(Decl, USR);
1201   PresumedLoc Loc =
1202       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
1203   DocComment Comment;
1204   if (auto *RawComment =
1205           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
1206     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
1207                                             Context.getDiagnostics());
1208   // Build declaration fragments and sub-heading for the category.
1209   DeclarationFragments Declaration =
1210       DeclarationFragmentsBuilder::getFragmentsForObjCCategory(Decl);
1211   DeclarationFragments SubHeading =
1212       DeclarationFragmentsBuilder::getSubHeading(Decl);
1213 
1214   const ObjCInterfaceDecl *InterfaceDecl = Decl->getClassInterface();
1215   SymbolReference Interface = createSymbolReferenceForDecl(*InterfaceDecl);
1216 
1217   auto *CategoryRecord = API.createRecord<ObjCCategoryRecord>(
1218       USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
1219       AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading,
1220       Interface, isInSystemHeader(Decl));
1221 
1222   getDerivedExtractAPIVisitor().recordObjCMethods(CategoryRecord,
1223                                                   Decl->methods());
1224   getDerivedExtractAPIVisitor().recordObjCProperties(CategoryRecord,
1225                                                      Decl->properties());
1226   getDerivedExtractAPIVisitor().recordObjCInstanceVariables(CategoryRecord,
1227                                                             Decl->ivars());
1228   getDerivedExtractAPIVisitor().recordObjCProtocols(CategoryRecord,
1229                                                     Decl->protocols());
1230 
1231   return true;
1232 }
1233 
1234 /// Collect API information for the enum constants and associate with the
1235 /// parent enum.
1236 template <typename Derived>
1237 void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
1238     SymbolReference Container, const EnumDecl::enumerator_range Constants) {
1239   for (const auto *Constant : Constants) {
1240     // Collect symbol information.
1241     StringRef Name = Constant->getName();
1242     SmallString<128> USR;
1243     index::generateUSRForDecl(Constant, USR);
1244     PresumedLoc Loc =
1245         Context.getSourceManager().getPresumedLoc(Constant->getLocation());
1246     DocComment Comment;
1247     if (auto *RawComment =
1248             getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Constant))
1249       Comment = RawComment->getFormattedLines(Context.getSourceManager(),
1250                                               Context.getDiagnostics());
1251 
1252     // Build declaration fragments and sub-heading for the enum constant.
1253     DeclarationFragments Declaration =
1254         DeclarationFragmentsBuilder::getFragmentsForEnumConstant(Constant);
1255     DeclarationFragments SubHeading =
1256         DeclarationFragmentsBuilder::getSubHeading(Constant);
1257 
1258     API.createRecord<EnumConstantRecord>(
1259         USR, Name, Container, Loc, AvailabilityInfo::createFromDecl(Constant),
1260         Comment, Declaration, SubHeading, isInSystemHeader(Constant));
1261   }
1262 }
1263 
1264 template <typename Derived>
1265 bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) {
1266   // ObjCIvars are handled separately
1267   if (isa<ObjCIvarDecl>(Decl) || isa<ObjCAtDefsFieldDecl>(Decl))
1268     return true;
1269 
1270   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
1271     return true;
1272 
1273   // Collect symbol information.
1274   StringRef Name = Decl->getName();
1275   SmallString<128> USR;
1276   index::generateUSRForDecl(Decl, USR);
1277   PresumedLoc Loc =
1278       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
1279   DocComment Comment;
1280   if (auto *RawComment =
1281           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
1282     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
1283                                             Context.getDiagnostics());
1284 
1285   // Build declaration fragments and sub-heading for the struct field.
1286   DeclarationFragments Declaration =
1287       DeclarationFragmentsBuilder::getFragmentsForField(Decl);
1288   DeclarationFragments SubHeading =
1289       DeclarationFragmentsBuilder::getSubHeading(Decl);
1290 
1291   RecordContext *NewRecord = nullptr;
1292   if (isa<CXXRecordDecl>(Decl->getDeclContext())) {
1293     AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
1294 
1295     NewRecord = API.createRecord<CXXFieldRecord>(
1296         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
1297         AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
1298         SubHeading, Access, isInSystemHeader(Decl));
1299   } else if (auto *RD = dyn_cast<RecordDecl>(Decl->getDeclContext())) {
1300     if (RD->isUnion())
1301       NewRecord = API.createRecord<UnionFieldRecord>(
1302           USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
1303           AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
1304           SubHeading, isInSystemHeader(Decl));
1305     else
1306       NewRecord = API.createRecord<StructFieldRecord>(
1307           USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
1308           AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
1309           SubHeading, isInSystemHeader(Decl));
1310   }
1311 
1312   // If this field has a non typedef'd anonymous tag type let's pretend the
1313   // type's child records are under us in the hierarchy.
1314   maybeMergeWithAnonymousTag(*Decl, NewRecord);
1315 
1316   return true;
1317 }
1318 
1319 template <typename Derived>
1320 bool ExtractAPIVisitorBase<Derived>::VisitCXXConversionDecl(
1321     const CXXConversionDecl *Decl) {
1322   if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
1323       Decl->isImplicit())
1324     return true;
1325 
1326   auto Name = Decl->getNameAsString();
1327   SmallString<128> USR;
1328   index::generateUSRForDecl(Decl, USR);
1329   PresumedLoc Loc =
1330       Context.getSourceManager().getPresumedLoc(Decl->getLocation());
1331   DocComment Comment;
1332   if (auto *RawComment =
1333           getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
1334     Comment = RawComment->getFormattedLines(Context.getSourceManager(),
1335                                             Context.getDiagnostics());
1336 
1337   // Build declaration fragments, sub-heading, and signature for the method.
1338   DeclarationFragments Declaration =
1339       DeclarationFragmentsBuilder::getFragmentsForConversionFunction(Decl);
1340   DeclarationFragments SubHeading =
1341       DeclarationFragmentsBuilder::getSubHeading(Decl);
1342   FunctionSignature Signature =
1343       DeclarationFragmentsBuilder::getFunctionSignature(Decl);
1344   AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
1345 
1346   if (Decl->isStatic())
1347     API.createRecord<CXXStaticMethodRecord>(
1348         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
1349         AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
1350         SubHeading, Signature, Access, isInSystemHeader(Decl));
1351   else
1352     API.createRecord<CXXInstanceMethodRecord>(
1353         USR, Name, createHierarchyInformationForDecl(*Decl), Loc,
1354         AvailabilityInfo::createFromDecl(Decl), Comment, Declaration,
1355         SubHeading, Signature, Access, isInSystemHeader(Decl));
1356 
1357   return true;
1358 }
1359 
1360 /// Collect API information for the Objective-C methods and associate with the
1361 /// parent container.
1362 template <typename Derived>
1363 void ExtractAPIVisitorBase<Derived>::recordObjCMethods(
1364     ObjCContainerRecord *Container,
1365     const ObjCContainerDecl::method_range Methods) {
1366   for (const auto *Method : Methods) {
1367     // Don't record selectors for properties.
1368     if (Method->isPropertyAccessor())
1369       continue;
1370 
1371     auto Name = Method->getSelector().getAsString();
1372     SmallString<128> USR;
1373     index::generateUSRForDecl(Method, USR);
1374     PresumedLoc Loc =
1375         Context.getSourceManager().getPresumedLoc(Method->getLocation());
1376     DocComment Comment;
1377     if (auto *RawComment =
1378             getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Method))
1379       Comment = RawComment->getFormattedLines(Context.getSourceManager(),
1380                                               Context.getDiagnostics());
1381 
1382     // Build declaration fragments, sub-heading, and signature for the method.
1383     DeclarationFragments Declaration =
1384         DeclarationFragmentsBuilder::getFragmentsForObjCMethod(Method);
1385     DeclarationFragments SubHeading =
1386         DeclarationFragmentsBuilder::getSubHeading(Method);
1387     FunctionSignature Signature =
1388         DeclarationFragmentsBuilder::getFunctionSignature(Method);
1389 
1390     if (Method->isInstanceMethod())
1391       API.createRecord<ObjCInstanceMethodRecord>(
1392           USR, Name, createHierarchyInformationForDecl(*Method), Loc,
1393           AvailabilityInfo::createFromDecl(Method), Comment, Declaration,
1394           SubHeading, Signature, isInSystemHeader(Method));
1395     else
1396       API.createRecord<ObjCClassMethodRecord>(
1397           USR, Name, createHierarchyInformationForDecl(*Method), Loc,
1398           AvailabilityInfo::createFromDecl(Method), Comment, Declaration,
1399           SubHeading, Signature, isInSystemHeader(Method));
1400   }
1401 }
1402 
1403 template <typename Derived>
1404 void ExtractAPIVisitorBase<Derived>::recordObjCProperties(
1405     ObjCContainerRecord *Container,
1406     const ObjCContainerDecl::prop_range Properties) {
1407   for (const auto *Property : Properties) {
1408     StringRef Name = Property->getName();
1409     SmallString<128> USR;
1410     index::generateUSRForDecl(Property, USR);
1411     PresumedLoc Loc =
1412         Context.getSourceManager().getPresumedLoc(Property->getLocation());
1413     DocComment Comment;
1414     if (auto *RawComment =
1415             getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Property))
1416       Comment = RawComment->getFormattedLines(Context.getSourceManager(),
1417                                               Context.getDiagnostics());
1418 
1419     // Build declaration fragments and sub-heading for the property.
1420     DeclarationFragments Declaration =
1421         DeclarationFragmentsBuilder::getFragmentsForObjCProperty(Property);
1422     DeclarationFragments SubHeading =
1423         DeclarationFragmentsBuilder::getSubHeading(Property);
1424 
1425     auto GetterName = Property->getGetterName().getAsString();
1426     auto SetterName = Property->getSetterName().getAsString();
1427 
1428     // Get the attributes for property.
1429     unsigned Attributes = ObjCPropertyRecord::NoAttr;
1430     if (Property->getPropertyAttributes() &
1431         ObjCPropertyAttribute::kind_readonly)
1432       Attributes |= ObjCPropertyRecord::ReadOnly;
1433 
1434     if (Property->getPropertyAttributes() & ObjCPropertyAttribute::kind_class)
1435       API.createRecord<ObjCClassPropertyRecord>(
1436           USR, Name, createHierarchyInformationForDecl(*Property), Loc,
1437           AvailabilityInfo::createFromDecl(Property), Comment, Declaration,
1438           SubHeading,
1439           static_cast<ObjCPropertyRecord::AttributeKind>(Attributes),
1440           GetterName, SetterName, Property->isOptional(),
1441           isInSystemHeader(Property));
1442     else
1443       API.createRecord<ObjCInstancePropertyRecord>(
1444           USR, Name, createHierarchyInformationForDecl(*Property), Loc,
1445           AvailabilityInfo::createFromDecl(Property), Comment, Declaration,
1446           SubHeading,
1447           static_cast<ObjCPropertyRecord::AttributeKind>(Attributes),
1448           GetterName, SetterName, Property->isOptional(),
1449           isInSystemHeader(Property));
1450   }
1451 }
1452 
1453 template <typename Derived>
1454 void ExtractAPIVisitorBase<Derived>::recordObjCInstanceVariables(
1455     ObjCContainerRecord *Container,
1456     const llvm::iterator_range<
1457         DeclContext::specific_decl_iterator<ObjCIvarDecl>>
1458         Ivars) {
1459   for (const auto *Ivar : Ivars) {
1460     StringRef Name = Ivar->getName();
1461     SmallString<128> USR;
1462     index::generateUSRForDecl(Ivar, USR);
1463 
1464     PresumedLoc Loc =
1465         Context.getSourceManager().getPresumedLoc(Ivar->getLocation());
1466     DocComment Comment;
1467     if (auto *RawComment =
1468             getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Ivar))
1469       Comment = RawComment->getFormattedLines(Context.getSourceManager(),
1470                                               Context.getDiagnostics());
1471 
1472     // Build declaration fragments and sub-heading for the instance variable.
1473     DeclarationFragments Declaration =
1474         DeclarationFragmentsBuilder::getFragmentsForField(Ivar);
1475     DeclarationFragments SubHeading =
1476         DeclarationFragmentsBuilder::getSubHeading(Ivar);
1477 
1478     API.createRecord<ObjCInstanceVariableRecord>(
1479         USR, Name, createHierarchyInformationForDecl(*Ivar), Loc,
1480         AvailabilityInfo::createFromDecl(Ivar), Comment, Declaration,
1481         SubHeading, isInSystemHeader(Ivar));
1482   }
1483 }
1484 
1485 template <typename Derived>
1486 void ExtractAPIVisitorBase<Derived>::recordObjCProtocols(
1487     ObjCContainerRecord *Container,
1488     ObjCInterfaceDecl::protocol_range Protocols) {
1489   for (const auto *Protocol : Protocols)
1490     Container->Protocols.emplace_back(createSymbolReferenceForDecl(*Protocol));
1491 }
1492 
1493 } // namespace impl
1494 
1495 /// The RecursiveASTVisitor to traverse symbol declarations and collect API
1496 /// information.
1497 template <typename Derived = void>
1498 class ExtractAPIVisitor
1499     : public impl::ExtractAPIVisitorBase<std::conditional_t<
1500           std::is_same_v<Derived, void>, ExtractAPIVisitor<>, Derived>> {
1501   using Base = impl::ExtractAPIVisitorBase<std::conditional_t<
1502       std::is_same_v<Derived, void>, ExtractAPIVisitor<>, Derived>>;
1503 
1504 public:
1505   ExtractAPIVisitor(ASTContext &Context, APISet &API) : Base(Context, API) {}
1506 
1507   bool shouldDeclBeIncluded(const Decl *D) const { return true; }
1508   const RawComment *fetchRawCommentForDecl(const Decl *D) const {
1509     if (const auto *Comment = this->Context.getRawCommentForDeclNoCache(D))
1510       return Comment;
1511 
1512     if (const auto *Declarator = dyn_cast<DeclaratorDecl>(D)) {
1513       const auto *TagTypeDecl = Declarator->getType()->getAsTagDecl();
1514       if (TagTypeDecl && TagTypeDecl->isEmbeddedInDeclarator() &&
1515           TagTypeDecl->isCompleteDefinition())
1516         return this->Context.getRawCommentForDeclNoCache(TagTypeDecl);
1517     }
1518 
1519     return nullptr;
1520   }
1521 };
1522 
1523 } // namespace extractapi
1524 } // namespace clang
1525 
1526 #endif // LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H