1 //===- ExtractAPI/ExtractAPIVisitor.h ---------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file defines the ExtractAPVisitor AST visitation interface. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H 15 #define LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H 16 17 #include "clang/AST/ASTContext.h" 18 #include "clang/AST/Decl.h" 19 #include "clang/AST/DeclCXX.h" 20 #include "clang/AST/DeclObjC.h" 21 #include "clang/AST/DeclTemplate.h" 22 #include "clang/AST/ParentMapContext.h" 23 #include "clang/AST/RecursiveASTVisitor.h" 24 #include "clang/Basic/LLVM.h" 25 #include "clang/Basic/Module.h" 26 #include "clang/Basic/SourceManager.h" 27 #include "clang/Basic/Specifiers.h" 28 #include "clang/ExtractAPI/API.h" 29 #include "clang/ExtractAPI/DeclarationFragments.h" 30 #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" 31 #include "clang/Index/USRGeneration.h" 32 #include "llvm/ADT/SmallString.h" 33 #include "llvm/ADT/StringRef.h" 34 #include "llvm/Support/Casting.h" 35 #include <type_traits> 36 37 namespace clang { 38 namespace extractapi { 39 namespace impl { 40 41 template <typename Derived> 42 class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> { 43 protected: 44 ExtractAPIVisitorBase(ASTContext &Context, APISet &API) 45 : Context(Context), API(API) {} 46 47 public: 48 const APISet &getAPI() const { return API; } 49 50 bool VisitVarDecl(const VarDecl *Decl); 51 52 bool VisitFunctionDecl(const FunctionDecl *Decl); 53 54 bool VisitEnumDecl(const EnumDecl *Decl); 55 56 bool WalkUpFromFunctionDecl(const FunctionDecl *Decl); 57 58 bool WalkUpFromRecordDecl(const RecordDecl *Decl); 59 60 bool WalkUpFromCXXRecordDecl(const CXXRecordDecl *Decl); 61 62 bool WalkUpFromCXXMethodDecl(const CXXMethodDecl *Decl); 63 64 bool WalkUpFromClassTemplateSpecializationDecl( 65 const ClassTemplateSpecializationDecl *Decl); 66 67 bool WalkUpFromClassTemplatePartialSpecializationDecl( 68 const ClassTemplatePartialSpecializationDecl *Decl); 69 70 bool WalkUpFromVarTemplateDecl(const VarTemplateDecl *Decl); 71 72 bool WalkUpFromVarTemplateSpecializationDecl( 73 const VarTemplateSpecializationDecl *Decl); 74 75 bool WalkUpFromVarTemplatePartialSpecializationDecl( 76 const VarTemplatePartialSpecializationDecl *Decl); 77 78 bool WalkUpFromFunctionTemplateDecl(const FunctionTemplateDecl *Decl); 79 80 bool WalkUpFromNamespaceDecl(const NamespaceDecl *Decl); 81 82 bool VisitNamespaceDecl(const NamespaceDecl *Decl); 83 84 bool VisitRecordDecl(const RecordDecl *Decl); 85 86 bool VisitCXXRecordDecl(const CXXRecordDecl *Decl); 87 88 bool VisitCXXMethodDecl(const CXXMethodDecl *Decl); 89 90 bool VisitFieldDecl(const FieldDecl *Decl); 91 92 bool VisitCXXConversionDecl(const CXXConversionDecl *Decl); 93 94 bool VisitCXXConstructorDecl(const CXXConstructorDecl *Decl); 95 96 bool VisitCXXDestructorDecl(const CXXDestructorDecl *Decl); 97 98 bool VisitConceptDecl(const ConceptDecl *Decl); 99 100 bool VisitClassTemplateSpecializationDecl( 101 const ClassTemplateSpecializationDecl *Decl); 102 103 bool VisitClassTemplatePartialSpecializationDecl( 104 const ClassTemplatePartialSpecializationDecl *Decl); 105 106 bool VisitVarTemplateDecl(const VarTemplateDecl *Decl); 107 108 bool 109 VisitVarTemplateSpecializationDecl(const VarTemplateSpecializationDecl *Decl); 110 111 bool VisitVarTemplatePartialSpecializationDecl( 112 const VarTemplatePartialSpecializationDecl *Decl); 113 114 bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *Decl); 115 116 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *Decl); 117 118 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *Decl); 119 120 bool VisitTypedefNameDecl(const TypedefNameDecl *Decl); 121 122 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *Decl); 123 124 bool shouldDeclBeIncluded(const Decl *Decl) const; 125 126 const RawComment *fetchRawCommentForDecl(const Decl *Decl) const; 127 128 protected: 129 /// Collect API information for the enum constants and associate with the 130 /// parent enum. 131 void recordEnumConstants(SymbolReference Container, 132 const EnumDecl::enumerator_range Constants); 133 134 /// Collect API information for the Objective-C methods and associate with the 135 /// parent container. 136 void recordObjCMethods(ObjCContainerRecord *Container, 137 const ObjCContainerDecl::method_range Methods); 138 139 void recordObjCProperties(ObjCContainerRecord *Container, 140 const ObjCContainerDecl::prop_range Properties); 141 142 void recordObjCInstanceVariables( 143 ObjCContainerRecord *Container, 144 const llvm::iterator_range< 145 DeclContext::specific_decl_iterator<ObjCIvarDecl>> 146 Ivars); 147 148 void recordObjCProtocols(ObjCContainerRecord *Container, 149 ObjCInterfaceDecl::protocol_range Protocols); 150 151 ASTContext &Context; 152 APISet &API; 153 154 StringRef getTypedefName(const TagDecl *Decl) { 155 if (const auto *TypedefDecl = Decl->getTypedefNameForAnonDecl()) 156 return TypedefDecl->getName(); 157 158 return {}; 159 } 160 161 bool isInSystemHeader(const Decl *D) { 162 return Context.getSourceManager().isInSystemHeader(D->getLocation()); 163 } 164 165 private: 166 Derived &getDerivedExtractAPIVisitor() { 167 return *static_cast<Derived *>(this); 168 } 169 170 protected: 171 SmallVector<SymbolReference> getBases(const CXXRecordDecl *Decl) { 172 // FIXME: store AccessSpecifier given by inheritance 173 SmallVector<SymbolReference> Bases; 174 for (const auto &BaseSpecifier : Decl->bases()) { 175 // skip classes not inherited as public 176 if (BaseSpecifier.getAccessSpecifier() != AccessSpecifier::AS_public) 177 continue; 178 if (auto *BaseDecl = BaseSpecifier.getType()->getAsTagDecl()) { 179 Bases.emplace_back(createSymbolReferenceForDecl(*BaseDecl)); 180 } else { 181 SymbolReference BaseClass; 182 BaseClass.Name = API.copyString(BaseSpecifier.getType().getAsString( 183 Decl->getASTContext().getPrintingPolicy())); 184 185 if (BaseSpecifier.getType().getTypePtr()->isTemplateTypeParmType()) { 186 if (auto *TTPTD = BaseSpecifier.getType() 187 ->getAs<TemplateTypeParmType>() 188 ->getDecl()) { 189 SmallString<128> USR; 190 index::generateUSRForDecl(TTPTD, USR); 191 BaseClass.USR = API.copyString(USR); 192 BaseClass.Source = API.copyString(getOwningModuleName(*TTPTD)); 193 } 194 } 195 Bases.emplace_back(BaseClass); 196 } 197 } 198 return Bases; 199 } 200 201 APIRecord::RecordKind getKindForDisplay(const CXXRecordDecl *Decl) { 202 if (Decl->isUnion()) 203 return APIRecord::RK_Union; 204 if (Decl->isStruct()) 205 return APIRecord::RK_Struct; 206 207 return APIRecord::RK_CXXClass; 208 } 209 210 StringRef getOwningModuleName(const Decl &D) { 211 if (auto *OwningModule = D.getImportedOwningModule()) 212 return OwningModule->Name; 213 214 return {}; 215 } 216 217 SymbolReference createHierarchyInformationForDecl(const Decl &D) { 218 const auto *Context = cast_if_present<Decl>(D.getDeclContext()); 219 220 if (!Context || isa<TranslationUnitDecl>(Context)) 221 return {}; 222 223 return createSymbolReferenceForDecl(*Context); 224 } 225 226 SymbolReference createSymbolReferenceForDecl(const Decl &D) { 227 SmallString<128> USR; 228 index::generateUSRForDecl(&D, USR); 229 230 APIRecord *Record = API.findRecordForUSR(USR); 231 if (Record) 232 return SymbolReference(Record); 233 234 StringRef Name; 235 if (auto *ND = dyn_cast<NamedDecl>(&D)) 236 Name = ND->getName(); 237 238 return API.createSymbolReference(Name, USR, getOwningModuleName(D)); 239 } 240 241 bool isEmbeddedInVarDeclarator(const TagDecl &D) { 242 return D.getName().empty() && getTypedefName(&D).empty() && 243 D.isEmbeddedInDeclarator(); 244 } 245 246 void maybeMergeWithAnonymousTag(const DeclaratorDecl &D, 247 RecordContext *NewRecordContext) { 248 if (!NewRecordContext) 249 return; 250 auto *Tag = D.getType()->getAsTagDecl(); 251 SmallString<128> TagUSR; 252 clang::index::generateUSRForDecl(Tag, TagUSR); 253 if (auto *Record = llvm::dyn_cast_if_present<TagRecord>( 254 API.findRecordForUSR(TagUSR))) { 255 if (Record->IsEmbeddedInVarDeclarator) 256 NewRecordContext->stealRecordChain(*Record); 257 } 258 } 259 }; 260 261 template <typename Derived> 262 bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) { 263 // skip function parameters. 264 if (isa<ParmVarDecl>(Decl)) 265 return true; 266 267 // Skip non-global variables in records (struct/union/class) but not static 268 // members. 269 if (Decl->getDeclContext()->isRecord() && !Decl->isStaticDataMember()) 270 return true; 271 272 // Skip local variables inside function or method. 273 if (!Decl->isDefinedOutsideFunctionOrMethod()) 274 return true; 275 276 // If this is a template but not specialization or instantiation, skip. 277 if (Decl->getASTContext().getTemplateOrSpecializationInfo(Decl) && 278 Decl->getTemplateSpecializationKind() == TSK_Undeclared) 279 return true; 280 281 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 282 return true; 283 284 // Collect symbol information. 285 StringRef Name = Decl->getName(); 286 SmallString<128> USR; 287 index::generateUSRForDecl(Decl, USR); 288 PresumedLoc Loc = 289 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 290 LinkageInfo Linkage = Decl->getLinkageAndVisibility(); 291 DocComment Comment; 292 if (auto *RawComment = 293 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 294 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 295 Context.getDiagnostics()); 296 297 // Build declaration fragments and sub-heading for the variable. 298 DeclarationFragments Declaration = 299 DeclarationFragmentsBuilder::getFragmentsForVar(Decl); 300 DeclarationFragments SubHeading = 301 DeclarationFragmentsBuilder::getSubHeading(Decl); 302 if (Decl->isStaticDataMember()) { 303 auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl); 304 API.createRecord<StaticFieldRecord>( 305 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 306 AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, 307 SubHeading, Access, isInSystemHeader(Decl)); 308 } else { 309 // Add the global variable record to the API set. 310 auto *NewRecord = API.createRecord<GlobalVariableRecord>( 311 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 312 AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, 313 SubHeading, isInSystemHeader(Decl)); 314 315 // If this global variable has a non typedef'd anonymous tag type let's 316 // pretend the type's child records are under us in the hierarchy. 317 maybeMergeWithAnonymousTag(*Decl, NewRecord); 318 } 319 320 return true; 321 } 322 323 template <typename Derived> 324 bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl( 325 const FunctionDecl *Decl) { 326 if (const auto *Method = dyn_cast<CXXMethodDecl>(Decl)) { 327 // Skip member function in class templates. 328 if (Method->getParent()->getDescribedClassTemplate() != nullptr) 329 return true; 330 331 // Skip methods in records. 332 for (const auto &P : Context.getParents(*Method)) { 333 if (P.template get<CXXRecordDecl>()) 334 return true; 335 } 336 337 // Skip ConstructorDecl and DestructorDecl. 338 if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method)) 339 return true; 340 } 341 342 // Skip templated functions that aren't processed here. 343 switch (Decl->getTemplatedKind()) { 344 case FunctionDecl::TK_NonTemplate: 345 case FunctionDecl::TK_DependentNonTemplate: 346 case FunctionDecl::TK_FunctionTemplateSpecialization: 347 break; 348 case FunctionDecl::TK_FunctionTemplate: 349 case FunctionDecl::TK_DependentFunctionTemplateSpecialization: 350 case FunctionDecl::TK_MemberSpecialization: 351 return true; 352 } 353 354 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 355 return true; 356 357 // Collect symbol information. 358 auto Name = Decl->getNameAsString(); 359 SmallString<128> USR; 360 index::generateUSRForDecl(Decl, USR); 361 PresumedLoc Loc = 362 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 363 LinkageInfo Linkage = Decl->getLinkageAndVisibility(); 364 DocComment Comment; 365 if (auto *RawComment = 366 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 367 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 368 Context.getDiagnostics()); 369 370 // Build declaration fragments, sub-heading, and signature of the function. 371 DeclarationFragments SubHeading = 372 DeclarationFragmentsBuilder::getSubHeading(Decl); 373 FunctionSignature Signature = 374 DeclarationFragmentsBuilder::getFunctionSignature(Decl); 375 if (Decl->getTemplateSpecializationInfo()) 376 API.createRecord<GlobalFunctionTemplateSpecializationRecord>( 377 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 378 AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, 379 DeclarationFragmentsBuilder:: 380 getFragmentsForFunctionTemplateSpecialization(Decl), 381 SubHeading, Signature, isInSystemHeader(Decl)); 382 else 383 // Add the function record to the API set. 384 API.createRecord<GlobalFunctionRecord>( 385 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 386 AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, 387 DeclarationFragmentsBuilder::getFragmentsForFunction(Decl), SubHeading, 388 Signature, isInSystemHeader(Decl)); 389 return true; 390 } 391 392 template <typename Derived> 393 bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) { 394 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 395 return true; 396 397 SmallString<128> USR; 398 index::generateUSRForDecl(Decl, USR); 399 PresumedLoc Loc = 400 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 401 DocComment Comment; 402 if (auto *RawComment = 403 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 404 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 405 Context.getDiagnostics()); 406 407 // Build declaration fragments and sub-heading for the enum. 408 DeclarationFragments Declaration = 409 DeclarationFragmentsBuilder::getFragmentsForEnum(Decl); 410 DeclarationFragments SubHeading = 411 DeclarationFragmentsBuilder::getSubHeading(Decl); 412 413 // Collect symbol information. 414 SymbolReference ParentContainer; 415 416 if (Decl->hasNameForLinkage()) { 417 StringRef Name = Decl->getName(); 418 if (Name.empty()) 419 Name = getTypedefName(Decl); 420 421 auto *ER = API.createRecord<EnumRecord>( 422 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 423 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, 424 SubHeading, isInSystemHeader(Decl), false); 425 ParentContainer = SymbolReference(ER); 426 } else { 427 // If this an anonymous enum then the parent scope of the constants is the 428 // top level namespace. 429 ParentContainer = {}; 430 } 431 432 // Now collect information about the enumerators in this enum. 433 getDerivedExtractAPIVisitor().recordEnumConstants(ParentContainer, 434 Decl->enumerators()); 435 436 return true; 437 } 438 439 template <typename Derived> 440 bool ExtractAPIVisitorBase<Derived>::WalkUpFromFunctionDecl( 441 const FunctionDecl *Decl) { 442 getDerivedExtractAPIVisitor().VisitFunctionDecl(Decl); 443 return true; 444 } 445 446 template <typename Derived> 447 bool ExtractAPIVisitorBase<Derived>::WalkUpFromRecordDecl( 448 const RecordDecl *Decl) { 449 getDerivedExtractAPIVisitor().VisitRecordDecl(Decl); 450 return true; 451 } 452 453 template <typename Derived> 454 bool ExtractAPIVisitorBase<Derived>::WalkUpFromCXXRecordDecl( 455 const CXXRecordDecl *Decl) { 456 getDerivedExtractAPIVisitor().VisitCXXRecordDecl(Decl); 457 return true; 458 } 459 460 template <typename Derived> 461 bool ExtractAPIVisitorBase<Derived>::WalkUpFromCXXMethodDecl( 462 const CXXMethodDecl *Decl) { 463 getDerivedExtractAPIVisitor().VisitCXXMethodDecl(Decl); 464 return true; 465 } 466 467 template <typename Derived> 468 bool ExtractAPIVisitorBase<Derived>::WalkUpFromClassTemplateSpecializationDecl( 469 const ClassTemplateSpecializationDecl *Decl) { 470 getDerivedExtractAPIVisitor().VisitClassTemplateSpecializationDecl(Decl); 471 return true; 472 } 473 474 template <typename Derived> 475 bool ExtractAPIVisitorBase<Derived>:: 476 WalkUpFromClassTemplatePartialSpecializationDecl( 477 const ClassTemplatePartialSpecializationDecl *Decl) { 478 getDerivedExtractAPIVisitor().VisitClassTemplatePartialSpecializationDecl( 479 Decl); 480 return true; 481 } 482 483 template <typename Derived> 484 bool ExtractAPIVisitorBase<Derived>::WalkUpFromVarTemplateDecl( 485 const VarTemplateDecl *Decl) { 486 getDerivedExtractAPIVisitor().VisitVarTemplateDecl(Decl); 487 return true; 488 } 489 490 template <typename Derived> 491 bool ExtractAPIVisitorBase<Derived>::WalkUpFromVarTemplateSpecializationDecl( 492 const VarTemplateSpecializationDecl *Decl) { 493 getDerivedExtractAPIVisitor().VisitVarTemplateSpecializationDecl(Decl); 494 return true; 495 } 496 497 template <typename Derived> 498 bool ExtractAPIVisitorBase<Derived>:: 499 WalkUpFromVarTemplatePartialSpecializationDecl( 500 const VarTemplatePartialSpecializationDecl *Decl) { 501 getDerivedExtractAPIVisitor().VisitVarTemplatePartialSpecializationDecl(Decl); 502 return true; 503 } 504 505 template <typename Derived> 506 bool ExtractAPIVisitorBase<Derived>::WalkUpFromFunctionTemplateDecl( 507 const FunctionTemplateDecl *Decl) { 508 getDerivedExtractAPIVisitor().VisitFunctionTemplateDecl(Decl); 509 return true; 510 } 511 512 template <typename Derived> 513 bool ExtractAPIVisitorBase<Derived>::WalkUpFromNamespaceDecl( 514 const NamespaceDecl *Decl) { 515 getDerivedExtractAPIVisitor().VisitNamespaceDecl(Decl); 516 return true; 517 } 518 519 template <typename Derived> 520 bool ExtractAPIVisitorBase<Derived>::VisitNamespaceDecl( 521 const NamespaceDecl *Decl) { 522 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 523 return true; 524 if (Decl->isAnonymousNamespace()) 525 return true; 526 StringRef Name = Decl->getName(); 527 SmallString<128> USR; 528 index::generateUSRForDecl(Decl, USR); 529 LinkageInfo Linkage = Decl->getLinkageAndVisibility(); 530 PresumedLoc Loc = 531 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 532 DocComment Comment; 533 if (auto *RawComment = 534 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 535 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 536 Context.getDiagnostics()); 537 538 // Build declaration fragments and sub-heading for the struct. 539 DeclarationFragments Declaration = 540 DeclarationFragmentsBuilder::getFragmentsForNamespace(Decl); 541 DeclarationFragments SubHeading = 542 DeclarationFragmentsBuilder::getSubHeading(Decl); 543 API.createRecord<NamespaceRecord>( 544 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 545 AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, 546 SubHeading, isInSystemHeader(Decl)); 547 548 return true; 549 } 550 551 template <typename Derived> 552 bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) { 553 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 554 return true; 555 556 // Collect symbol information. 557 StringRef Name = Decl->getName(); 558 if (Name.empty()) 559 Name = getTypedefName(Decl); 560 561 SmallString<128> USR; 562 index::generateUSRForDecl(Decl, USR); 563 PresumedLoc Loc = 564 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 565 DocComment Comment; 566 if (auto *RawComment = 567 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 568 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 569 Context.getDiagnostics()); 570 571 // Build declaration fragments and sub-heading for the struct. 572 DeclarationFragments Declaration = 573 DeclarationFragmentsBuilder::getFragmentsForRecordDecl(Decl); 574 DeclarationFragments SubHeading = 575 DeclarationFragmentsBuilder::getSubHeading(Decl); 576 577 if (Decl->isUnion()) 578 API.createRecord<UnionRecord>( 579 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 580 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, 581 SubHeading, isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl)); 582 else 583 API.createRecord<StructRecord>( 584 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 585 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, 586 SubHeading, isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl)); 587 588 return true; 589 } 590 591 template <typename Derived> 592 bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl( 593 const CXXRecordDecl *Decl) { 594 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) || 595 Decl->isImplicit()) 596 return true; 597 598 StringRef Name = Decl->getName(); 599 if (Name.empty()) 600 Name = getTypedefName(Decl); 601 602 SmallString<128> USR; 603 index::generateUSRForDecl(Decl, USR); 604 PresumedLoc Loc = 605 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 606 DocComment Comment; 607 if (auto *RawComment = 608 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 609 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 610 Context.getDiagnostics()); 611 DeclarationFragments Declaration = 612 DeclarationFragmentsBuilder::getFragmentsForCXXClass(Decl); 613 DeclarationFragments SubHeading = 614 DeclarationFragmentsBuilder::getSubHeading(Decl); 615 616 auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl); 617 618 CXXClassRecord *Record; 619 if (Decl->getDescribedClassTemplate()) { 620 // Inject template fragments before class fragments. 621 Declaration.prepend( 622 DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate( 623 Decl->getDescribedClassTemplate())); 624 Record = API.createRecord<ClassTemplateRecord>( 625 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 626 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, 627 SubHeading, Template(Decl->getDescribedClassTemplate()), Access, 628 isInSystemHeader(Decl)); 629 } else { 630 Record = API.createRecord<CXXClassRecord>( 631 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 632 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, 633 SubHeading, APIRecord::RecordKind::RK_CXXClass, Access, 634 isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl)); 635 } 636 637 Record->KindForDisplay = getKindForDisplay(Decl); 638 Record->Bases = getBases(Decl); 639 640 return true; 641 } 642 643 template <typename Derived> 644 bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl( 645 const CXXMethodDecl *Decl) { 646 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) || 647 Decl->isImplicit()) 648 return true; 649 650 if (isa<CXXConversionDecl>(Decl)) 651 return true; 652 if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl)) 653 return true; 654 655 SmallString<128> USR; 656 index::generateUSRForDecl(Decl, USR); 657 PresumedLoc Loc = 658 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 659 DocComment Comment; 660 if (auto *RawComment = 661 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 662 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 663 Context.getDiagnostics()); 664 DeclarationFragments SubHeading = 665 DeclarationFragmentsBuilder::getSubHeading(Decl); 666 auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl); 667 auto Signature = DeclarationFragmentsBuilder::getFunctionSignature(Decl); 668 669 if (FunctionTemplateDecl *TemplateDecl = 670 Decl->getDescribedFunctionTemplate()) { 671 API.createRecord<CXXMethodTemplateRecord>( 672 USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl), 673 Loc, AvailabilityInfo::createFromDecl(Decl), Comment, 674 DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate( 675 TemplateDecl), 676 SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl), 677 DeclarationFragmentsBuilder::getAccessControl(TemplateDecl), 678 Template(TemplateDecl), isInSystemHeader(Decl)); 679 } else if (Decl->getTemplateSpecializationInfo()) 680 API.createRecord<CXXMethodTemplateSpecializationRecord>( 681 USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl), 682 Loc, AvailabilityInfo::createFromDecl(Decl), Comment, 683 DeclarationFragmentsBuilder:: 684 getFragmentsForFunctionTemplateSpecialization(Decl), 685 SubHeading, Signature, Access, isInSystemHeader(Decl)); 686 else if (Decl->isOverloadedOperator()) 687 API.createRecord<CXXInstanceMethodRecord>( 688 USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl), 689 Loc, AvailabilityInfo::createFromDecl(Decl), Comment, 690 DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(Decl), 691 SubHeading, Signature, Access, isInSystemHeader(Decl)); 692 else if (Decl->isStatic()) 693 API.createRecord<CXXStaticMethodRecord>( 694 USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl), 695 Loc, AvailabilityInfo::createFromDecl(Decl), Comment, 696 DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading, 697 Signature, Access, isInSystemHeader(Decl)); 698 else 699 API.createRecord<CXXInstanceMethodRecord>( 700 USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl), 701 Loc, AvailabilityInfo::createFromDecl(Decl), Comment, 702 DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeading, 703 Signature, Access, isInSystemHeader(Decl)); 704 705 return true; 706 } 707 708 template <typename Derived> 709 bool ExtractAPIVisitorBase<Derived>::VisitCXXConstructorDecl( 710 const CXXConstructorDecl *Decl) { 711 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) || 712 Decl->isImplicit()) 713 return true; 714 715 auto Name = Decl->getNameAsString(); 716 SmallString<128> USR; 717 index::generateUSRForDecl(Decl, USR); 718 PresumedLoc Loc = 719 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 720 DocComment Comment; 721 if (auto *RawComment = 722 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 723 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 724 Context.getDiagnostics()); 725 726 // Build declaration fragments, sub-heading, and signature for the method. 727 DeclarationFragments Declaration = 728 DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(Decl); 729 DeclarationFragments SubHeading = 730 DeclarationFragmentsBuilder::getSubHeading(Decl); 731 FunctionSignature Signature = 732 DeclarationFragmentsBuilder::getFunctionSignature(Decl); 733 AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); 734 735 API.createRecord<CXXConstructorRecord>( 736 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 737 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, 738 Signature, Access, isInSystemHeader(Decl)); 739 return true; 740 } 741 742 template <typename Derived> 743 bool ExtractAPIVisitorBase<Derived>::VisitCXXDestructorDecl( 744 const CXXDestructorDecl *Decl) { 745 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) || 746 Decl->isImplicit()) 747 return true; 748 749 auto Name = Decl->getNameAsString(); 750 SmallString<128> USR; 751 index::generateUSRForDecl(Decl, USR); 752 PresumedLoc Loc = 753 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 754 DocComment Comment; 755 if (auto *RawComment = 756 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 757 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 758 Context.getDiagnostics()); 759 760 // Build declaration fragments, sub-heading, and signature for the method. 761 DeclarationFragments Declaration = 762 DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(Decl); 763 DeclarationFragments SubHeading = 764 DeclarationFragmentsBuilder::getSubHeading(Decl); 765 FunctionSignature Signature = 766 DeclarationFragmentsBuilder::getFunctionSignature(Decl); 767 AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); 768 API.createRecord<CXXDestructorRecord>( 769 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 770 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, 771 Signature, Access, isInSystemHeader(Decl)); 772 return true; 773 } 774 775 template <typename Derived> 776 bool ExtractAPIVisitorBase<Derived>::VisitConceptDecl(const ConceptDecl *Decl) { 777 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 778 return true; 779 780 StringRef Name = Decl->getName(); 781 SmallString<128> USR; 782 index::generateUSRForDecl(Decl, USR); 783 PresumedLoc Loc = 784 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 785 DocComment Comment; 786 if (auto *RawComment = 787 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 788 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 789 Context.getDiagnostics()); 790 DeclarationFragments Declaration = 791 DeclarationFragmentsBuilder::getFragmentsForConcept(Decl); 792 DeclarationFragments SubHeading = 793 DeclarationFragmentsBuilder::getSubHeading(Decl); 794 API.createRecord<ConceptRecord>( 795 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 796 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, 797 Template(Decl), isInSystemHeader(Decl)); 798 return true; 799 } 800 801 template <typename Derived> 802 bool ExtractAPIVisitorBase<Derived>::VisitClassTemplateSpecializationDecl( 803 const ClassTemplateSpecializationDecl *Decl) { 804 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 805 return true; 806 807 StringRef Name = Decl->getName(); 808 SmallString<128> USR; 809 index::generateUSRForDecl(Decl, USR); 810 PresumedLoc Loc = 811 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 812 DocComment Comment; 813 if (auto *RawComment = 814 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 815 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 816 Context.getDiagnostics()); 817 DeclarationFragments Declaration = 818 DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization( 819 Decl); 820 DeclarationFragments SubHeading = 821 DeclarationFragmentsBuilder::getSubHeading(Decl); 822 823 auto *CTSR = API.createRecord<ClassTemplateSpecializationRecord>( 824 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 825 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, 826 DeclarationFragmentsBuilder::getAccessControl(Decl), 827 isInSystemHeader(Decl)); 828 829 CTSR->Bases = getBases(Decl); 830 831 return true; 832 } 833 834 template <typename Derived> 835 bool ExtractAPIVisitorBase<Derived>:: 836 VisitClassTemplatePartialSpecializationDecl( 837 const ClassTemplatePartialSpecializationDecl *Decl) { 838 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 839 return true; 840 841 StringRef Name = Decl->getName(); 842 SmallString<128> USR; 843 index::generateUSRForDecl(Decl, USR); 844 PresumedLoc Loc = 845 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 846 DocComment Comment; 847 if (auto *RawComment = 848 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 849 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 850 Context.getDiagnostics()); 851 DeclarationFragments Declaration = DeclarationFragmentsBuilder:: 852 getFragmentsForClassTemplatePartialSpecialization(Decl); 853 DeclarationFragments SubHeading = 854 DeclarationFragmentsBuilder::getSubHeading(Decl); 855 auto *CTPSR = API.createRecord<ClassTemplatePartialSpecializationRecord>( 856 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 857 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, 858 Template(Decl), DeclarationFragmentsBuilder::getAccessControl(Decl), 859 isInSystemHeader(Decl)); 860 861 CTPSR->KindForDisplay = getKindForDisplay(Decl); 862 CTPSR->Bases = getBases(Decl); 863 864 return true; 865 } 866 867 template <typename Derived> 868 bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateDecl( 869 const VarTemplateDecl *Decl) { 870 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 871 return true; 872 873 // Collect symbol information. 874 StringRef Name = Decl->getName(); 875 SmallString<128> USR; 876 index::generateUSRForDecl(Decl, USR); 877 PresumedLoc Loc = 878 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 879 LinkageInfo Linkage = Decl->getLinkageAndVisibility(); 880 DocComment Comment; 881 if (auto *RawComment = 882 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 883 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 884 Context.getDiagnostics()); 885 886 // Build declaration fragments and sub-heading for the variable. 887 DeclarationFragments Declaration; 888 Declaration 889 .append(DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate( 890 Decl)) 891 .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate( 892 Decl->getTemplatedDecl())); 893 // Inject template fragments before var fragments. 894 DeclarationFragments SubHeading = 895 DeclarationFragmentsBuilder::getSubHeading(Decl); 896 897 if (Decl->getDeclContext()->getDeclKind() == Decl::CXXRecord) 898 API.createRecord<CXXFieldTemplateRecord>( 899 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 900 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, 901 SubHeading, DeclarationFragmentsBuilder::getAccessControl(Decl), 902 Template(Decl), isInSystemHeader(Decl)); 903 else 904 API.createRecord<GlobalVariableTemplateRecord>( 905 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 906 AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, 907 SubHeading, Template(Decl), isInSystemHeader(Decl)); 908 return true; 909 } 910 911 template <typename Derived> 912 bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateSpecializationDecl( 913 const VarTemplateSpecializationDecl *Decl) { 914 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 915 return true; 916 917 // Collect symbol information. 918 StringRef Name = Decl->getName(); 919 SmallString<128> USR; 920 index::generateUSRForDecl(Decl, USR); 921 PresumedLoc Loc = 922 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 923 LinkageInfo Linkage = Decl->getLinkageAndVisibility(); 924 DocComment Comment; 925 if (auto *RawComment = 926 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 927 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 928 Context.getDiagnostics()); 929 930 // Build declaration fragments and sub-heading for the variable. 931 DeclarationFragments Declaration = 932 DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization( 933 Decl); 934 DeclarationFragments SubHeading = 935 DeclarationFragmentsBuilder::getSubHeading(Decl); 936 API.createRecord<GlobalVariableTemplateSpecializationRecord>( 937 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 938 AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, 939 SubHeading, isInSystemHeader(Decl)); 940 return true; 941 } 942 943 template <typename Derived> 944 bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl( 945 const VarTemplatePartialSpecializationDecl *Decl) { 946 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 947 return true; 948 949 // Collect symbol information. 950 StringRef Name = Decl->getName(); 951 SmallString<128> USR; 952 index::generateUSRForDecl(Decl, USR); 953 PresumedLoc Loc = 954 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 955 LinkageInfo Linkage = Decl->getLinkageAndVisibility(); 956 DocComment Comment; 957 if (auto *RawComment = 958 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 959 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 960 Context.getDiagnostics()); 961 962 // Build declaration fragments and sub-heading for the variable. 963 DeclarationFragments Declaration = DeclarationFragmentsBuilder:: 964 getFragmentsForVarTemplatePartialSpecialization(Decl); 965 DeclarationFragments SubHeading = 966 DeclarationFragmentsBuilder::getSubHeading(Decl); 967 API.createRecord<GlobalVariableTemplatePartialSpecializationRecord>( 968 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 969 AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, 970 SubHeading, Template(Decl), isInSystemHeader(Decl)); 971 return true; 972 } 973 974 template <typename Derived> 975 bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl( 976 const FunctionTemplateDecl *Decl) { 977 if (isa<CXXMethodDecl>(Decl->getTemplatedDecl())) 978 return true; 979 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 980 return true; 981 982 // Collect symbol information. 983 auto Name = Decl->getNameAsString(); 984 SmallString<128> USR; 985 index::generateUSRForDecl(Decl, USR); 986 PresumedLoc Loc = 987 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 988 LinkageInfo Linkage = Decl->getLinkageAndVisibility(); 989 DocComment Comment; 990 if (auto *RawComment = 991 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 992 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 993 Context.getDiagnostics()); 994 995 DeclarationFragments SubHeading = 996 DeclarationFragmentsBuilder::getSubHeading(Decl); 997 FunctionSignature Signature = 998 DeclarationFragmentsBuilder::getFunctionSignature( 999 Decl->getTemplatedDecl()); 1000 API.createRecord<GlobalFunctionTemplateRecord>( 1001 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 1002 AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, 1003 DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(Decl), 1004 SubHeading, Signature, Template(Decl), isInSystemHeader(Decl)); 1005 1006 return true; 1007 } 1008 1009 template <typename Derived> 1010 bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl( 1011 const ObjCInterfaceDecl *Decl) { 1012 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 1013 return true; 1014 1015 // Collect symbol information. 1016 StringRef Name = Decl->getName(); 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 // Build declaration fragments and sub-heading for the interface. 1029 DeclarationFragments Declaration = 1030 DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Decl); 1031 DeclarationFragments SubHeading = 1032 DeclarationFragmentsBuilder::getSubHeading(Decl); 1033 1034 // Collect super class information. 1035 SymbolReference SuperClass; 1036 if (const auto *SuperClassDecl = Decl->getSuperClass()) 1037 SuperClass = createSymbolReferenceForDecl(*SuperClassDecl); 1038 1039 auto *InterfaceRecord = API.createRecord<ObjCInterfaceRecord>( 1040 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 1041 AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, 1042 SubHeading, SuperClass, isInSystemHeader(Decl)); 1043 1044 // Record all methods (selectors). This doesn't include automatically 1045 // synthesized property methods. 1046 getDerivedExtractAPIVisitor().recordObjCMethods(InterfaceRecord, 1047 Decl->methods()); 1048 getDerivedExtractAPIVisitor().recordObjCProperties(InterfaceRecord, 1049 Decl->properties()); 1050 getDerivedExtractAPIVisitor().recordObjCInstanceVariables(InterfaceRecord, 1051 Decl->ivars()); 1052 getDerivedExtractAPIVisitor().recordObjCProtocols(InterfaceRecord, 1053 Decl->protocols()); 1054 1055 return true; 1056 } 1057 1058 template <typename Derived> 1059 bool ExtractAPIVisitorBase<Derived>::VisitObjCProtocolDecl( 1060 const ObjCProtocolDecl *Decl) { 1061 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 1062 return true; 1063 1064 // Collect symbol information. 1065 StringRef Name = Decl->getName(); 1066 SmallString<128> USR; 1067 index::generateUSRForDecl(Decl, USR); 1068 PresumedLoc Loc = 1069 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 1070 DocComment Comment; 1071 if (auto *RawComment = 1072 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 1073 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 1074 Context.getDiagnostics()); 1075 1076 // Build declaration fragments and sub-heading for the protocol. 1077 DeclarationFragments Declaration = 1078 DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(Decl); 1079 DeclarationFragments SubHeading = 1080 DeclarationFragmentsBuilder::getSubHeading(Decl); 1081 1082 auto *ProtoRecord = API.createRecord<ObjCProtocolRecord>( 1083 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 1084 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, 1085 isInSystemHeader(Decl)); 1086 1087 getDerivedExtractAPIVisitor().recordObjCMethods(ProtoRecord, Decl->methods()); 1088 getDerivedExtractAPIVisitor().recordObjCProperties(ProtoRecord, 1089 Decl->properties()); 1090 getDerivedExtractAPIVisitor().recordObjCProtocols(ProtoRecord, 1091 Decl->protocols()); 1092 1093 return true; 1094 } 1095 1096 template <typename Derived> 1097 bool ExtractAPIVisitorBase<Derived>::VisitTypedefNameDecl( 1098 const TypedefNameDecl *Decl) { 1099 // Skip ObjC Type Parameter for now. 1100 if (isa<ObjCTypeParamDecl>(Decl)) 1101 return true; 1102 1103 if (!Decl->isDefinedOutsideFunctionOrMethod()) 1104 return true; 1105 1106 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 1107 return true; 1108 1109 StringRef Name = Decl->getName(); 1110 1111 // If the underlying type was defined as part of the typedef modify it's 1112 // fragments directly and pretend the typedef doesn't exist. 1113 if (auto *TagDecl = Decl->getUnderlyingType()->getAsTagDecl()) { 1114 if (TagDecl->isEmbeddedInDeclarator() && TagDecl->isCompleteDefinition() && 1115 Decl->getName() == TagDecl->getName()) { 1116 SmallString<128> TagUSR; 1117 index::generateUSRForDecl(TagDecl, TagUSR); 1118 if (auto *Record = API.findRecordForUSR(TagUSR)) { 1119 DeclarationFragments LeadingFragments; 1120 LeadingFragments.append("typedef", 1121 DeclarationFragments::FragmentKind::Keyword); 1122 LeadingFragments.appendSpace(); 1123 Record->Declaration.removeTrailingSemicolon() 1124 .prepend(std::move(LeadingFragments)) 1125 .append(" { ... } ", DeclarationFragments::FragmentKind::Text) 1126 .append(Name, DeclarationFragments::FragmentKind::Identifier) 1127 .appendSemicolon(); 1128 1129 return true; 1130 } 1131 } 1132 } 1133 1134 PresumedLoc Loc = 1135 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 1136 SmallString<128> USR; 1137 index::generateUSRForDecl(Decl, USR); 1138 DocComment Comment; 1139 if (auto *RawComment = 1140 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 1141 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 1142 Context.getDiagnostics()); 1143 1144 QualType Type = Decl->getUnderlyingType(); 1145 SymbolReference SymRef = 1146 TypedefUnderlyingTypeResolver(Context).getSymbolReferenceForType(Type, 1147 API); 1148 1149 API.createRecord<TypedefRecord>( 1150 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 1151 AvailabilityInfo::createFromDecl(Decl), Comment, 1152 DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl), 1153 DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef, 1154 isInSystemHeader(Decl)); 1155 1156 return true; 1157 } 1158 1159 template <typename Derived> 1160 bool ExtractAPIVisitorBase<Derived>::VisitObjCCategoryDecl( 1161 const ObjCCategoryDecl *Decl) { 1162 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 1163 return true; 1164 1165 StringRef Name = Decl->getName(); 1166 SmallString<128> USR; 1167 index::generateUSRForDecl(Decl, USR); 1168 PresumedLoc Loc = 1169 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 1170 DocComment Comment; 1171 if (auto *RawComment = 1172 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 1173 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 1174 Context.getDiagnostics()); 1175 // Build declaration fragments and sub-heading for the category. 1176 DeclarationFragments Declaration = 1177 DeclarationFragmentsBuilder::getFragmentsForObjCCategory(Decl); 1178 DeclarationFragments SubHeading = 1179 DeclarationFragmentsBuilder::getSubHeading(Decl); 1180 1181 const ObjCInterfaceDecl *InterfaceDecl = Decl->getClassInterface(); 1182 SymbolReference Interface = createSymbolReferenceForDecl(*InterfaceDecl); 1183 1184 auto *CategoryRecord = API.createRecord<ObjCCategoryRecord>( 1185 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 1186 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, 1187 Interface, isInSystemHeader(Decl)); 1188 1189 getDerivedExtractAPIVisitor().recordObjCMethods(CategoryRecord, 1190 Decl->methods()); 1191 getDerivedExtractAPIVisitor().recordObjCProperties(CategoryRecord, 1192 Decl->properties()); 1193 getDerivedExtractAPIVisitor().recordObjCInstanceVariables(CategoryRecord, 1194 Decl->ivars()); 1195 getDerivedExtractAPIVisitor().recordObjCProtocols(CategoryRecord, 1196 Decl->protocols()); 1197 1198 return true; 1199 } 1200 1201 /// Collect API information for the enum constants and associate with the 1202 /// parent enum. 1203 template <typename Derived> 1204 void ExtractAPIVisitorBase<Derived>::recordEnumConstants( 1205 SymbolReference Container, const EnumDecl::enumerator_range Constants) { 1206 for (const auto *Constant : Constants) { 1207 // Collect symbol information. 1208 StringRef Name = Constant->getName(); 1209 SmallString<128> USR; 1210 index::generateUSRForDecl(Constant, USR); 1211 PresumedLoc Loc = 1212 Context.getSourceManager().getPresumedLoc(Constant->getLocation()); 1213 DocComment Comment; 1214 if (auto *RawComment = 1215 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Constant)) 1216 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 1217 Context.getDiagnostics()); 1218 1219 // Build declaration fragments and sub-heading for the enum constant. 1220 DeclarationFragments Declaration = 1221 DeclarationFragmentsBuilder::getFragmentsForEnumConstant(Constant); 1222 DeclarationFragments SubHeading = 1223 DeclarationFragmentsBuilder::getSubHeading(Constant); 1224 1225 API.createRecord<EnumConstantRecord>( 1226 USR, Name, Container, Loc, AvailabilityInfo::createFromDecl(Constant), 1227 Comment, Declaration, SubHeading, isInSystemHeader(Constant)); 1228 } 1229 } 1230 1231 template <typename Derived> 1232 bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) { 1233 // ObjCIvars are handled separately 1234 if (isa<ObjCIvarDecl>(Decl) || isa<ObjCAtDefsFieldDecl>(Decl)) 1235 return true; 1236 1237 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) 1238 return true; 1239 1240 // Collect symbol information. 1241 StringRef Name = Decl->getName(); 1242 SmallString<128> USR; 1243 index::generateUSRForDecl(Decl, USR); 1244 PresumedLoc Loc = 1245 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 1246 DocComment Comment; 1247 if (auto *RawComment = 1248 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 1249 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 1250 Context.getDiagnostics()); 1251 1252 // Build declaration fragments and sub-heading for the struct field. 1253 DeclarationFragments Declaration = 1254 DeclarationFragmentsBuilder::getFragmentsForField(Decl); 1255 DeclarationFragments SubHeading = 1256 DeclarationFragmentsBuilder::getSubHeading(Decl); 1257 1258 RecordContext *NewRecord = nullptr; 1259 if (isa<CXXRecordDecl>(Decl->getDeclContext())) { 1260 AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); 1261 1262 NewRecord = API.createRecord<CXXFieldRecord>( 1263 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 1264 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, 1265 SubHeading, Access, isInSystemHeader(Decl)); 1266 } else if (auto *RD = dyn_cast<RecordDecl>(Decl->getDeclContext())) { 1267 if (RD->isUnion()) 1268 NewRecord = API.createRecord<UnionFieldRecord>( 1269 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 1270 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, 1271 SubHeading, isInSystemHeader(Decl)); 1272 else 1273 NewRecord = API.createRecord<StructFieldRecord>( 1274 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 1275 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, 1276 SubHeading, isInSystemHeader(Decl)); 1277 } 1278 1279 // If this field has a non typedef'd anonymous tag type let's pretend the 1280 // type's child records are under us in the hierarchy. 1281 maybeMergeWithAnonymousTag(*Decl, NewRecord); 1282 1283 return true; 1284 } 1285 1286 template <typename Derived> 1287 bool ExtractAPIVisitorBase<Derived>::VisitCXXConversionDecl( 1288 const CXXConversionDecl *Decl) { 1289 if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) || 1290 Decl->isImplicit()) 1291 return true; 1292 1293 auto Name = Decl->getNameAsString(); 1294 SmallString<128> USR; 1295 index::generateUSRForDecl(Decl, USR); 1296 PresumedLoc Loc = 1297 Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 1298 DocComment Comment; 1299 if (auto *RawComment = 1300 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl)) 1301 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 1302 Context.getDiagnostics()); 1303 1304 // Build declaration fragments, sub-heading, and signature for the method. 1305 DeclarationFragments Declaration = 1306 DeclarationFragmentsBuilder::getFragmentsForConversionFunction(Decl); 1307 DeclarationFragments SubHeading = 1308 DeclarationFragmentsBuilder::getSubHeading(Decl); 1309 FunctionSignature Signature = 1310 DeclarationFragmentsBuilder::getFunctionSignature(Decl); 1311 AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); 1312 1313 if (Decl->isStatic()) 1314 API.createRecord<CXXStaticMethodRecord>( 1315 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 1316 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, 1317 SubHeading, Signature, Access, isInSystemHeader(Decl)); 1318 else 1319 API.createRecord<CXXInstanceMethodRecord>( 1320 USR, Name, createHierarchyInformationForDecl(*Decl), Loc, 1321 AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, 1322 SubHeading, Signature, Access, isInSystemHeader(Decl)); 1323 1324 return true; 1325 } 1326 1327 /// Collect API information for the Objective-C methods and associate with the 1328 /// parent container. 1329 template <typename Derived> 1330 void ExtractAPIVisitorBase<Derived>::recordObjCMethods( 1331 ObjCContainerRecord *Container, 1332 const ObjCContainerDecl::method_range Methods) { 1333 for (const auto *Method : Methods) { 1334 // Don't record selectors for properties. 1335 if (Method->isPropertyAccessor()) 1336 continue; 1337 1338 auto Name = Method->getSelector().getAsString(); 1339 SmallString<128> USR; 1340 index::generateUSRForDecl(Method, USR); 1341 PresumedLoc Loc = 1342 Context.getSourceManager().getPresumedLoc(Method->getLocation()); 1343 DocComment Comment; 1344 if (auto *RawComment = 1345 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Method)) 1346 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 1347 Context.getDiagnostics()); 1348 1349 // Build declaration fragments, sub-heading, and signature for the method. 1350 DeclarationFragments Declaration = 1351 DeclarationFragmentsBuilder::getFragmentsForObjCMethod(Method); 1352 DeclarationFragments SubHeading = 1353 DeclarationFragmentsBuilder::getSubHeading(Method); 1354 FunctionSignature Signature = 1355 DeclarationFragmentsBuilder::getFunctionSignature(Method); 1356 1357 if (Method->isInstanceMethod()) 1358 API.createRecord<ObjCInstanceMethodRecord>( 1359 USR, Name, createHierarchyInformationForDecl(*Method), Loc, 1360 AvailabilityInfo::createFromDecl(Method), Comment, Declaration, 1361 SubHeading, Signature, isInSystemHeader(Method)); 1362 else 1363 API.createRecord<ObjCClassMethodRecord>( 1364 USR, Name, createHierarchyInformationForDecl(*Method), Loc, 1365 AvailabilityInfo::createFromDecl(Method), Comment, Declaration, 1366 SubHeading, Signature, isInSystemHeader(Method)); 1367 } 1368 } 1369 1370 template <typename Derived> 1371 void ExtractAPIVisitorBase<Derived>::recordObjCProperties( 1372 ObjCContainerRecord *Container, 1373 const ObjCContainerDecl::prop_range Properties) { 1374 for (const auto *Property : Properties) { 1375 StringRef Name = Property->getName(); 1376 SmallString<128> USR; 1377 index::generateUSRForDecl(Property, USR); 1378 PresumedLoc Loc = 1379 Context.getSourceManager().getPresumedLoc(Property->getLocation()); 1380 DocComment Comment; 1381 if (auto *RawComment = 1382 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Property)) 1383 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 1384 Context.getDiagnostics()); 1385 1386 // Build declaration fragments and sub-heading for the property. 1387 DeclarationFragments Declaration = 1388 DeclarationFragmentsBuilder::getFragmentsForObjCProperty(Property); 1389 DeclarationFragments SubHeading = 1390 DeclarationFragmentsBuilder::getSubHeading(Property); 1391 1392 auto GetterName = Property->getGetterName().getAsString(); 1393 auto SetterName = Property->getSetterName().getAsString(); 1394 1395 // Get the attributes for property. 1396 unsigned Attributes = ObjCPropertyRecord::NoAttr; 1397 if (Property->getPropertyAttributes() & 1398 ObjCPropertyAttribute::kind_readonly) 1399 Attributes |= ObjCPropertyRecord::ReadOnly; 1400 1401 if (Property->getPropertyAttributes() & ObjCPropertyAttribute::kind_class) 1402 API.createRecord<ObjCClassPropertyRecord>( 1403 USR, Name, createHierarchyInformationForDecl(*Property), Loc, 1404 AvailabilityInfo::createFromDecl(Property), Comment, Declaration, 1405 SubHeading, 1406 static_cast<ObjCPropertyRecord::AttributeKind>(Attributes), 1407 GetterName, SetterName, Property->isOptional(), 1408 isInSystemHeader(Property)); 1409 else 1410 API.createRecord<ObjCInstancePropertyRecord>( 1411 USR, Name, createHierarchyInformationForDecl(*Property), Loc, 1412 AvailabilityInfo::createFromDecl(Property), Comment, Declaration, 1413 SubHeading, 1414 static_cast<ObjCPropertyRecord::AttributeKind>(Attributes), 1415 GetterName, SetterName, Property->isOptional(), 1416 isInSystemHeader(Property)); 1417 } 1418 } 1419 1420 template <typename Derived> 1421 void ExtractAPIVisitorBase<Derived>::recordObjCInstanceVariables( 1422 ObjCContainerRecord *Container, 1423 const llvm::iterator_range< 1424 DeclContext::specific_decl_iterator<ObjCIvarDecl>> 1425 Ivars) { 1426 for (const auto *Ivar : Ivars) { 1427 StringRef Name = Ivar->getName(); 1428 SmallString<128> USR; 1429 index::generateUSRForDecl(Ivar, USR); 1430 1431 PresumedLoc Loc = 1432 Context.getSourceManager().getPresumedLoc(Ivar->getLocation()); 1433 DocComment Comment; 1434 if (auto *RawComment = 1435 getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Ivar)) 1436 Comment = RawComment->getFormattedLines(Context.getSourceManager(), 1437 Context.getDiagnostics()); 1438 1439 // Build declaration fragments and sub-heading for the instance variable. 1440 DeclarationFragments Declaration = 1441 DeclarationFragmentsBuilder::getFragmentsForField(Ivar); 1442 DeclarationFragments SubHeading = 1443 DeclarationFragmentsBuilder::getSubHeading(Ivar); 1444 1445 API.createRecord<ObjCInstanceVariableRecord>( 1446 USR, Name, createHierarchyInformationForDecl(*Ivar), Loc, 1447 AvailabilityInfo::createFromDecl(Ivar), Comment, Declaration, 1448 SubHeading, isInSystemHeader(Ivar)); 1449 } 1450 } 1451 1452 template <typename Derived> 1453 void ExtractAPIVisitorBase<Derived>::recordObjCProtocols( 1454 ObjCContainerRecord *Container, 1455 ObjCInterfaceDecl::protocol_range Protocols) { 1456 for (const auto *Protocol : Protocols) 1457 Container->Protocols.emplace_back(createSymbolReferenceForDecl(*Protocol)); 1458 } 1459 1460 } // namespace impl 1461 1462 /// The RecursiveASTVisitor to traverse symbol declarations and collect API 1463 /// information. 1464 template <typename Derived = void> 1465 class ExtractAPIVisitor 1466 : public impl::ExtractAPIVisitorBase<std::conditional_t< 1467 std::is_same_v<Derived, void>, ExtractAPIVisitor<>, Derived>> { 1468 using Base = impl::ExtractAPIVisitorBase<std::conditional_t< 1469 std::is_same_v<Derived, void>, ExtractAPIVisitor<>, Derived>>; 1470 1471 public: 1472 ExtractAPIVisitor(ASTContext &Context, APISet &API) : Base(Context, API) {} 1473 1474 bool shouldDeclBeIncluded(const Decl *D) const { return true; } 1475 const RawComment *fetchRawCommentForDecl(const Decl *D) const { 1476 if (const auto *Comment = this->Context.getRawCommentForDeclNoCache(D)) 1477 return Comment; 1478 1479 if (const auto *Declarator = dyn_cast<DeclaratorDecl>(D)) { 1480 const auto *TagTypeDecl = Declarator->getType()->getAsTagDecl(); 1481 if (TagTypeDecl && TagTypeDecl->isEmbeddedInDeclarator() && 1482 TagTypeDecl->isCompleteDefinition()) 1483 return this->Context.getRawCommentForDeclNoCache(TagTypeDecl); 1484 } 1485 1486 return nullptr; 1487 } 1488 }; 1489 1490 } // namespace extractapi 1491 } // namespace clang 1492 1493 #endif // LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H 1494