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