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