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

source code of clang/include/clang/ExtractAPI/ExtractAPIVisitor.h