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