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