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/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 | |
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 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 &; |
151 | APISet &; |
152 | |
153 | StringRef (const TagDecl *Decl) { |
154 | if (const auto *TypedefDecl = Decl->getTypedefNameForAnonDecl()) |
155 | return TypedefDecl->getName(); |
156 | |
157 | return {}; |
158 | } |
159 | |
160 | bool (const Decl *D) { |
161 | return Context.getSourceManager().isInSystemHeader(Loc: D->getLocation()); |
162 | } |
163 | |
164 | private: |
165 | Derived &() { |
166 | return *static_cast<Derived *>(this); |
167 | } |
168 | |
169 | protected: |
170 | SmallVector<SymbolReference> (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 (const Decl &D) { |
198 | if (auto *OwningModule = D.getImportedOwningModule()) |
199 | return OwningModule->Name; |
200 | |
201 | return {}; |
202 | } |
203 | |
204 | SymbolReference (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 (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 (const TagDecl &D) { |
229 | return D.getName().empty() && getTypedefName(Decl: &D).empty() && |
230 | D.isEmbeddedInDeclarator(); |
231 | } |
232 | |
233 | void (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 | |
252 | template <typename Derived> |
253 | bool ExtractAPIVisitorBase<Derived>::(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 ; |
283 | if (auto * = |
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 | |
314 | template <typename Derived> |
315 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
356 | if (auto * = |
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 | |
383 | template <typename Derived> |
384 | bool ExtractAPIVisitorBase<Derived>::(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 ; |
404 | if (auto * = |
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 | |
425 | template <typename Derived> |
426 | bool ExtractAPIVisitorBase<Derived>::( |
427 | const FunctionDecl *Decl) { |
428 | getDerivedExtractAPIVisitor().VisitFunctionDecl(Decl); |
429 | return true; |
430 | } |
431 | |
432 | template <typename Derived> |
433 | bool ExtractAPIVisitorBase<Derived>::( |
434 | const RecordDecl *Decl) { |
435 | getDerivedExtractAPIVisitor().VisitRecordDecl(Decl); |
436 | return true; |
437 | } |
438 | |
439 | template <typename Derived> |
440 | bool ExtractAPIVisitorBase<Derived>::( |
441 | const CXXRecordDecl *Decl) { |
442 | getDerivedExtractAPIVisitor().VisitCXXRecordDecl(Decl); |
443 | return true; |
444 | } |
445 | |
446 | template <typename Derived> |
447 | bool ExtractAPIVisitorBase<Derived>::( |
448 | const CXXMethodDecl *Decl) { |
449 | getDerivedExtractAPIVisitor().VisitCXXMethodDecl(Decl); |
450 | return true; |
451 | } |
452 | |
453 | template <typename Derived> |
454 | bool ExtractAPIVisitorBase<Derived>::( |
455 | const ClassTemplateSpecializationDecl *Decl) { |
456 | getDerivedExtractAPIVisitor().VisitClassTemplateSpecializationDecl(Decl); |
457 | return true; |
458 | } |
459 | |
460 | template <typename Derived> |
461 | bool ExtractAPIVisitorBase<Derived>:: |
462 | ( |
463 | const ClassTemplatePartialSpecializationDecl *Decl) { |
464 | getDerivedExtractAPIVisitor().VisitClassTemplatePartialSpecializationDecl( |
465 | Decl); |
466 | return true; |
467 | } |
468 | |
469 | template <typename Derived> |
470 | bool ExtractAPIVisitorBase<Derived>::( |
471 | const VarTemplateDecl *Decl) { |
472 | getDerivedExtractAPIVisitor().VisitVarTemplateDecl(Decl); |
473 | return true; |
474 | } |
475 | |
476 | template <typename Derived> |
477 | bool ExtractAPIVisitorBase<Derived>::( |
478 | const VarTemplateSpecializationDecl *Decl) { |
479 | getDerivedExtractAPIVisitor().VisitVarTemplateSpecializationDecl(Decl); |
480 | return true; |
481 | } |
482 | |
483 | template <typename Derived> |
484 | bool ExtractAPIVisitorBase<Derived>:: |
485 | ( |
486 | const VarTemplatePartialSpecializationDecl *Decl) { |
487 | getDerivedExtractAPIVisitor().VisitVarTemplatePartialSpecializationDecl(Decl); |
488 | return true; |
489 | } |
490 | |
491 | template <typename Derived> |
492 | bool ExtractAPIVisitorBase<Derived>::( |
493 | const FunctionTemplateDecl *Decl) { |
494 | getDerivedExtractAPIVisitor().VisitFunctionTemplateDecl(Decl); |
495 | return true; |
496 | } |
497 | |
498 | template <typename Derived> |
499 | bool ExtractAPIVisitorBase<Derived>::( |
500 | const NamespaceDecl *Decl) { |
501 | getDerivedExtractAPIVisitor().VisitNamespaceDecl(Decl); |
502 | return true; |
503 | } |
504 | |
505 | template <typename Derived> |
506 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
519 | if (auto * = |
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 | |
537 | template <typename Derived> |
538 | bool ExtractAPIVisitorBase<Derived>::(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 ; |
552 | if (auto * = |
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 | |
577 | template <typename Derived> |
578 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
593 | if (auto * = |
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 | |
634 | template <typename Derived> |
635 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
651 | if (auto * = |
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 | |
699 | template <typename Derived> |
700 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
712 | if (auto * = |
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 | |
733 | template <typename Derived> |
734 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
746 | if (auto * = |
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 | |
766 | template <typename Derived> |
767 | bool ExtractAPIVisitorBase<Derived>::(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 ; |
777 | if (auto * = |
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 | |
792 | template <typename Derived> |
793 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
804 | if (auto * = |
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 | |
825 | template <typename Derived> |
826 | bool ExtractAPIVisitorBase<Derived>:: |
827 | ( |
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 ; |
838 | if (auto * = |
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 | |
857 | template <typename Derived> |
858 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
871 | if (auto * = |
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 | |
901 | template <typename Derived> |
902 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
915 | if (auto * = |
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 | |
933 | template <typename Derived> |
934 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
947 | if (auto * = |
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 | |
964 | template <typename Derived> |
965 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
980 | if (auto * = |
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 | |
999 | template <typename Derived> |
1000 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
1013 | if (auto * = |
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 | |
1048 | template <typename Derived> |
1049 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
1061 | if (auto * = |
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 | |
1086 | template <typename Derived> |
1087 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
1129 | if (auto * = |
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 | |
1149 | template <typename Derived> |
1150 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
1161 | if (auto * = |
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. |
1193 | template <typename Derived> |
1194 | void ExtractAPIVisitorBase<Derived>::( |
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 ; |
1204 | if (auto * = |
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 | |
1222 | template <typename Derived> |
1223 | bool ExtractAPIVisitorBase<Derived>::(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 ; |
1238 | if (auto * = |
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 | |
1277 | template <typename Derived> |
1278 | bool ExtractAPIVisitorBase<Derived>::( |
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 ; |
1290 | if (auto * = |
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. |
1320 | template <typename Derived> |
1321 | void ExtractAPIVisitorBase<Derived>::( |
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 ; |
1335 | if (auto * = |
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 | |
1361 | template <typename Derived> |
1362 | void ExtractAPIVisitorBase<Derived>::( |
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 ; |
1372 | if (auto * = |
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 | |
1411 | template <typename Derived> |
1412 | void ExtractAPIVisitorBase<Derived>::( |
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 ; |
1425 | if (auto * = |
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 | |
1443 | template <typename Derived> |
1444 | void ExtractAPIVisitorBase<Derived>::( |
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. |
1455 | template <typename Derived = void> |
1456 | class |
1457 | : public impl::ExtractAPIVisitorBase<std::conditional_t< |
1458 | std::is_same_v<Derived, void>, ExtractAPIVisitor<>, Derived>> { |
1459 | using = impl::ExtractAPIVisitorBase<std::conditional_t< |
1460 | std::is_same_v<Derived, void>, ExtractAPIVisitor<>, Derived>>; |
1461 | |
1462 | public: |
1463 | (ASTContext &Context, APISet &API) : Base(Context, API) {} |
1464 | |
1465 | bool (const Decl *D) const { return true; } |
1466 | const RawComment *(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 | |