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