xref: /llvm-project/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h (revision a368402d633098fc211c29f9726eef6e1874da5f)
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