File indexing completed on 2026-05-10 08:36:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
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
0134
0135 void recordEnumConstants(SymbolReference Container,
0136 const EnumDecl::enumerator_range Constants);
0137
0138
0139
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
0177 SmallVector<SymbolReference> Bases;
0178 for (const auto &BaseSpecifier : Decl->bases()) {
0179
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
0270 if (isa<ParmVarDecl>(Decl))
0271 return true;
0272
0273
0274
0275 if (Decl->getDeclContext()->isRecord() && !Decl->isStaticDataMember())
0276 return true;
0277
0278
0279 if (!Decl->isDefinedOutsideFunctionOrMethod())
0280 return true;
0281
0282
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
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
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
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
0322
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
0334 if (Method->getParent()->getDescribedClassTemplate() != nullptr)
0335 return true;
0336
0337
0338 for (const auto &P : Context.getParents(*Method)) {
0339 if (P.template get<CXXRecordDecl>())
0340 return true;
0341 }
0342
0343
0344 if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method))
0345 return true;
0346 }
0347
0348
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
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
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
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
0414 DeclarationFragments Declaration =
0415 DeclarationFragmentsBuilder::getFragmentsForEnum(Decl);
0416 DeclarationFragments SubHeading =
0417 DeclarationFragmentsBuilder::getSubHeading(Decl);
0418
0419
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
0434
0435 ParentContainer = {};
0436 }
0437
0438
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
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
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
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
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
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
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
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
0920 DeclarationFragments Declaration;
0921 Declaration
0922 .append(DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
0923 Decl))
0924 .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(
0925 Decl->getTemplatedDecl()));
0926
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
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
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
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
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
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
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
1062 DeclarationFragments Declaration =
1063 DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Decl);
1064 DeclarationFragments SubHeading =
1065 DeclarationFragmentsBuilder::getSubHeading(Decl);
1066
1067
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
1078
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
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
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
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
1145
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
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
1235
1236 template <typename Derived>
1237 void ExtractAPIVisitorBase<Derived>::recordEnumConstants(
1238 SymbolReference Container, const EnumDecl::enumerator_range Constants) {
1239 for (const auto *Constant : Constants) {
1240
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
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
1267 if (isa<ObjCIvarDecl>(Decl) || isa<ObjCAtDefsFieldDecl>(Decl))
1268 return true;
1269
1270 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
1271 return true;
1272
1273
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
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
1313
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
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
1361
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
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
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
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
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
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 }
1494
1495
1496
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 }
1524 }
1525
1526 #endif