1*12c85518Srobert //===- ExtractAPI/ExtractAPIVisitor.cpp -------------------------*- C++ -*-===//
2*12c85518Srobert //
3*12c85518Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*12c85518Srobert // See https://llvm.org/LICENSE.txt for license information.
5*12c85518Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*12c85518Srobert //
7*12c85518Srobert //===----------------------------------------------------------------------===//
8*12c85518Srobert ///
9*12c85518Srobert /// \file
10*12c85518Srobert /// This file implements the ExtractAPIVisitor an ASTVisitor to collect API
11*12c85518Srobert /// information.
12*12c85518Srobert ///
13*12c85518Srobert //===----------------------------------------------------------------------===//
14*12c85518Srobert
15*12c85518Srobert #include "clang/ExtractAPI/ExtractAPIVisitor.h"
16*12c85518Srobert
17*12c85518Srobert #include "TypedefUnderlyingTypeResolver.h"
18*12c85518Srobert #include "clang/AST/ASTConsumer.h"
19*12c85518Srobert #include "clang/AST/ASTContext.h"
20*12c85518Srobert #include "clang/AST/Decl.h"
21*12c85518Srobert #include "clang/AST/DeclCXX.h"
22*12c85518Srobert #include "clang/AST/ParentMapContext.h"
23*12c85518Srobert #include "clang/AST/RawCommentList.h"
24*12c85518Srobert #include "clang/Basic/SourceLocation.h"
25*12c85518Srobert #include "clang/Basic/SourceManager.h"
26*12c85518Srobert #include "clang/Basic/TargetInfo.h"
27*12c85518Srobert #include "clang/ExtractAPI/API.h"
28*12c85518Srobert #include "clang/ExtractAPI/AvailabilityInfo.h"
29*12c85518Srobert #include "clang/ExtractAPI/DeclarationFragments.h"
30*12c85518Srobert #include "clang/Frontend/ASTConsumers.h"
31*12c85518Srobert #include "clang/Frontend/FrontendOptions.h"
32*12c85518Srobert #include "llvm/Support/raw_ostream.h"
33*12c85518Srobert
34*12c85518Srobert using namespace clang;
35*12c85518Srobert using namespace extractapi;
36*12c85518Srobert
37*12c85518Srobert namespace {
38*12c85518Srobert
getTypedefName(const TagDecl * Decl)39*12c85518Srobert StringRef getTypedefName(const TagDecl *Decl) {
40*12c85518Srobert if (const auto *TypedefDecl = Decl->getTypedefNameForAnonDecl())
41*12c85518Srobert return TypedefDecl->getName();
42*12c85518Srobert
43*12c85518Srobert return {};
44*12c85518Srobert }
45*12c85518Srobert
46*12c85518Srobert template <class DeclTy>
isInSystemHeader(const ASTContext & Context,const DeclTy * D)47*12c85518Srobert bool isInSystemHeader(const ASTContext &Context, const DeclTy *D) {
48*12c85518Srobert return Context.getSourceManager().isInSystemHeader(D->getLocation());
49*12c85518Srobert }
50*12c85518Srobert
51*12c85518Srobert } // namespace
52*12c85518Srobert
VisitVarDecl(const VarDecl * Decl)53*12c85518Srobert bool ExtractAPIVisitor::VisitVarDecl(const VarDecl *Decl) {
54*12c85518Srobert // skip function parameters.
55*12c85518Srobert if (isa<ParmVarDecl>(Decl))
56*12c85518Srobert return true;
57*12c85518Srobert
58*12c85518Srobert // Skip non-global variables in records (struct/union/class).
59*12c85518Srobert if (Decl->getDeclContext()->isRecord())
60*12c85518Srobert return true;
61*12c85518Srobert
62*12c85518Srobert // Skip local variables inside function or method.
63*12c85518Srobert if (!Decl->isDefinedOutsideFunctionOrMethod())
64*12c85518Srobert return true;
65*12c85518Srobert
66*12c85518Srobert // If this is a template but not specialization or instantiation, skip.
67*12c85518Srobert if (Decl->getASTContext().getTemplateOrSpecializationInfo(Decl) &&
68*12c85518Srobert Decl->getTemplateSpecializationKind() == TSK_Undeclared)
69*12c85518Srobert return true;
70*12c85518Srobert
71*12c85518Srobert if (!LocationChecker(Decl->getLocation()))
72*12c85518Srobert return true;
73*12c85518Srobert
74*12c85518Srobert // Collect symbol information.
75*12c85518Srobert StringRef Name = Decl->getName();
76*12c85518Srobert StringRef USR = API.recordUSR(Decl);
77*12c85518Srobert PresumedLoc Loc =
78*12c85518Srobert Context.getSourceManager().getPresumedLoc(Decl->getLocation());
79*12c85518Srobert LinkageInfo Linkage = Decl->getLinkageAndVisibility();
80*12c85518Srobert DocComment Comment;
81*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
82*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
83*12c85518Srobert Context.getDiagnostics());
84*12c85518Srobert
85*12c85518Srobert // Build declaration fragments and sub-heading for the variable.
86*12c85518Srobert DeclarationFragments Declaration =
87*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForVar(Decl);
88*12c85518Srobert DeclarationFragments SubHeading =
89*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Decl);
90*12c85518Srobert
91*12c85518Srobert // Add the global variable record to the API set.
92*12c85518Srobert API.addGlobalVar(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
93*12c85518Srobert Declaration, SubHeading, isInSystemHeader(Context, Decl));
94*12c85518Srobert return true;
95*12c85518Srobert }
96*12c85518Srobert
VisitFunctionDecl(const FunctionDecl * Decl)97*12c85518Srobert bool ExtractAPIVisitor::VisitFunctionDecl(const FunctionDecl *Decl) {
98*12c85518Srobert if (const auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
99*12c85518Srobert // Skip member function in class templates.
100*12c85518Srobert if (Method->getParent()->getDescribedClassTemplate() != nullptr)
101*12c85518Srobert return true;
102*12c85518Srobert
103*12c85518Srobert // Skip methods in records.
104*12c85518Srobert for (auto P : Context.getParents(*Method)) {
105*12c85518Srobert if (P.get<CXXRecordDecl>())
106*12c85518Srobert return true;
107*12c85518Srobert }
108*12c85518Srobert
109*12c85518Srobert // Skip ConstructorDecl and DestructorDecl.
110*12c85518Srobert if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method))
111*12c85518Srobert return true;
112*12c85518Srobert }
113*12c85518Srobert
114*12c85518Srobert // Skip templated functions.
115*12c85518Srobert switch (Decl->getTemplatedKind()) {
116*12c85518Srobert case FunctionDecl::TK_NonTemplate:
117*12c85518Srobert case FunctionDecl::TK_DependentNonTemplate:
118*12c85518Srobert break;
119*12c85518Srobert case FunctionDecl::TK_MemberSpecialization:
120*12c85518Srobert case FunctionDecl::TK_FunctionTemplateSpecialization:
121*12c85518Srobert if (auto *TemplateInfo = Decl->getTemplateSpecializationInfo()) {
122*12c85518Srobert if (!TemplateInfo->isExplicitInstantiationOrSpecialization())
123*12c85518Srobert return true;
124*12c85518Srobert }
125*12c85518Srobert break;
126*12c85518Srobert case FunctionDecl::TK_FunctionTemplate:
127*12c85518Srobert case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
128*12c85518Srobert return true;
129*12c85518Srobert }
130*12c85518Srobert
131*12c85518Srobert if (!LocationChecker(Decl->getLocation()))
132*12c85518Srobert return true;
133*12c85518Srobert
134*12c85518Srobert // Collect symbol information.
135*12c85518Srobert StringRef Name = Decl->getName();
136*12c85518Srobert StringRef USR = API.recordUSR(Decl);
137*12c85518Srobert PresumedLoc Loc =
138*12c85518Srobert Context.getSourceManager().getPresumedLoc(Decl->getLocation());
139*12c85518Srobert LinkageInfo Linkage = Decl->getLinkageAndVisibility();
140*12c85518Srobert DocComment Comment;
141*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
142*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
143*12c85518Srobert Context.getDiagnostics());
144*12c85518Srobert
145*12c85518Srobert // Build declaration fragments, sub-heading, and signature of the function.
146*12c85518Srobert DeclarationFragments Declaration =
147*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForFunction(Decl);
148*12c85518Srobert DeclarationFragments SubHeading =
149*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Decl);
150*12c85518Srobert FunctionSignature Signature =
151*12c85518Srobert DeclarationFragmentsBuilder::getFunctionSignature(Decl);
152*12c85518Srobert
153*12c85518Srobert // Add the function record to the API set.
154*12c85518Srobert API.addGlobalFunction(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
155*12c85518Srobert Declaration, SubHeading, Signature,
156*12c85518Srobert isInSystemHeader(Context, Decl));
157*12c85518Srobert return true;
158*12c85518Srobert }
159*12c85518Srobert
VisitEnumDecl(const EnumDecl * Decl)160*12c85518Srobert bool ExtractAPIVisitor::VisitEnumDecl(const EnumDecl *Decl) {
161*12c85518Srobert if (!Decl->isComplete())
162*12c85518Srobert return true;
163*12c85518Srobert
164*12c85518Srobert // Skip forward declaration.
165*12c85518Srobert if (!Decl->isThisDeclarationADefinition())
166*12c85518Srobert return true;
167*12c85518Srobert
168*12c85518Srobert if (!LocationChecker(Decl->getLocation()))
169*12c85518Srobert return true;
170*12c85518Srobert
171*12c85518Srobert SmallString<128> QualifiedNameBuffer;
172*12c85518Srobert // Collect symbol information.
173*12c85518Srobert StringRef Name = Decl->getName();
174*12c85518Srobert if (Name.empty())
175*12c85518Srobert Name = getTypedefName(Decl);
176*12c85518Srobert if (Name.empty()) {
177*12c85518Srobert llvm::raw_svector_ostream OS(QualifiedNameBuffer);
178*12c85518Srobert Decl->printQualifiedName(OS);
179*12c85518Srobert Name = QualifiedNameBuffer.str();
180*12c85518Srobert }
181*12c85518Srobert
182*12c85518Srobert StringRef USR = API.recordUSR(Decl);
183*12c85518Srobert PresumedLoc Loc =
184*12c85518Srobert Context.getSourceManager().getPresumedLoc(Decl->getLocation());
185*12c85518Srobert DocComment Comment;
186*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
187*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
188*12c85518Srobert Context.getDiagnostics());
189*12c85518Srobert
190*12c85518Srobert // Build declaration fragments and sub-heading for the enum.
191*12c85518Srobert DeclarationFragments Declaration =
192*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForEnum(Decl);
193*12c85518Srobert DeclarationFragments SubHeading =
194*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Decl);
195*12c85518Srobert
196*12c85518Srobert EnumRecord *EnumRecord = API.addEnum(
197*12c85518Srobert API.copyString(Name), USR, Loc, AvailabilitySet(Decl), Comment,
198*12c85518Srobert Declaration, SubHeading, isInSystemHeader(Context, Decl));
199*12c85518Srobert
200*12c85518Srobert // Now collect information about the enumerators in this enum.
201*12c85518Srobert recordEnumConstants(EnumRecord, Decl->enumerators());
202*12c85518Srobert
203*12c85518Srobert return true;
204*12c85518Srobert }
205*12c85518Srobert
VisitRecordDecl(const RecordDecl * Decl)206*12c85518Srobert bool ExtractAPIVisitor::VisitRecordDecl(const RecordDecl *Decl) {
207*12c85518Srobert if (!Decl->isCompleteDefinition())
208*12c85518Srobert return true;
209*12c85518Srobert
210*12c85518Srobert // Skip C++ structs/classes/unions
211*12c85518Srobert // TODO: support C++ records
212*12c85518Srobert if (isa<CXXRecordDecl>(Decl))
213*12c85518Srobert return true;
214*12c85518Srobert
215*12c85518Srobert if (!LocationChecker(Decl->getLocation()))
216*12c85518Srobert return true;
217*12c85518Srobert
218*12c85518Srobert // Collect symbol information.
219*12c85518Srobert StringRef Name = Decl->getName();
220*12c85518Srobert if (Name.empty())
221*12c85518Srobert Name = getTypedefName(Decl);
222*12c85518Srobert if (Name.empty())
223*12c85518Srobert return true;
224*12c85518Srobert
225*12c85518Srobert StringRef USR = API.recordUSR(Decl);
226*12c85518Srobert PresumedLoc Loc =
227*12c85518Srobert Context.getSourceManager().getPresumedLoc(Decl->getLocation());
228*12c85518Srobert DocComment Comment;
229*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
230*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
231*12c85518Srobert Context.getDiagnostics());
232*12c85518Srobert
233*12c85518Srobert // Build declaration fragments and sub-heading for the struct.
234*12c85518Srobert DeclarationFragments Declaration =
235*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForStruct(Decl);
236*12c85518Srobert DeclarationFragments SubHeading =
237*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Decl);
238*12c85518Srobert
239*12c85518Srobert StructRecord *StructRecord =
240*12c85518Srobert API.addStruct(Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration,
241*12c85518Srobert SubHeading, isInSystemHeader(Context, Decl));
242*12c85518Srobert
243*12c85518Srobert // Now collect information about the fields in this struct.
244*12c85518Srobert recordStructFields(StructRecord, Decl->fields());
245*12c85518Srobert
246*12c85518Srobert return true;
247*12c85518Srobert }
248*12c85518Srobert
VisitObjCInterfaceDecl(const ObjCInterfaceDecl * Decl)249*12c85518Srobert bool ExtractAPIVisitor::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *Decl) {
250*12c85518Srobert // Skip forward declaration for classes (@class)
251*12c85518Srobert if (!Decl->isThisDeclarationADefinition())
252*12c85518Srobert return true;
253*12c85518Srobert
254*12c85518Srobert if (!LocationChecker(Decl->getLocation()))
255*12c85518Srobert return true;
256*12c85518Srobert
257*12c85518Srobert // Collect symbol information.
258*12c85518Srobert StringRef Name = Decl->getName();
259*12c85518Srobert StringRef USR = API.recordUSR(Decl);
260*12c85518Srobert PresumedLoc Loc =
261*12c85518Srobert Context.getSourceManager().getPresumedLoc(Decl->getLocation());
262*12c85518Srobert LinkageInfo Linkage = Decl->getLinkageAndVisibility();
263*12c85518Srobert DocComment Comment;
264*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
265*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
266*12c85518Srobert Context.getDiagnostics());
267*12c85518Srobert
268*12c85518Srobert // Build declaration fragments and sub-heading for the interface.
269*12c85518Srobert DeclarationFragments Declaration =
270*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Decl);
271*12c85518Srobert DeclarationFragments SubHeading =
272*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Decl);
273*12c85518Srobert
274*12c85518Srobert // Collect super class information.
275*12c85518Srobert SymbolReference SuperClass;
276*12c85518Srobert if (const auto *SuperClassDecl = Decl->getSuperClass()) {
277*12c85518Srobert SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString();
278*12c85518Srobert SuperClass.USR = API.recordUSR(SuperClassDecl);
279*12c85518Srobert }
280*12c85518Srobert
281*12c85518Srobert ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface(
282*12c85518Srobert Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment, Declaration,
283*12c85518Srobert SubHeading, SuperClass, isInSystemHeader(Context, Decl));
284*12c85518Srobert
285*12c85518Srobert // Record all methods (selectors). This doesn't include automatically
286*12c85518Srobert // synthesized property methods.
287*12c85518Srobert recordObjCMethods(ObjCInterfaceRecord, Decl->methods());
288*12c85518Srobert recordObjCProperties(ObjCInterfaceRecord, Decl->properties());
289*12c85518Srobert recordObjCInstanceVariables(ObjCInterfaceRecord, Decl->ivars());
290*12c85518Srobert recordObjCProtocols(ObjCInterfaceRecord, Decl->protocols());
291*12c85518Srobert
292*12c85518Srobert return true;
293*12c85518Srobert }
294*12c85518Srobert
VisitObjCProtocolDecl(const ObjCProtocolDecl * Decl)295*12c85518Srobert bool ExtractAPIVisitor::VisitObjCProtocolDecl(const ObjCProtocolDecl *Decl) {
296*12c85518Srobert // Skip forward declaration for protocols (@protocol).
297*12c85518Srobert if (!Decl->isThisDeclarationADefinition())
298*12c85518Srobert return true;
299*12c85518Srobert
300*12c85518Srobert if (!LocationChecker(Decl->getLocation()))
301*12c85518Srobert return true;
302*12c85518Srobert
303*12c85518Srobert // Collect symbol information.
304*12c85518Srobert StringRef Name = Decl->getName();
305*12c85518Srobert StringRef USR = API.recordUSR(Decl);
306*12c85518Srobert PresumedLoc Loc =
307*12c85518Srobert Context.getSourceManager().getPresumedLoc(Decl->getLocation());
308*12c85518Srobert DocComment Comment;
309*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
310*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
311*12c85518Srobert Context.getDiagnostics());
312*12c85518Srobert
313*12c85518Srobert // Build declaration fragments and sub-heading for the protocol.
314*12c85518Srobert DeclarationFragments Declaration =
315*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(Decl);
316*12c85518Srobert DeclarationFragments SubHeading =
317*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Decl);
318*12c85518Srobert
319*12c85518Srobert ObjCProtocolRecord *ObjCProtocolRecord = API.addObjCProtocol(
320*12c85518Srobert Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, SubHeading,
321*12c85518Srobert isInSystemHeader(Context, Decl));
322*12c85518Srobert
323*12c85518Srobert recordObjCMethods(ObjCProtocolRecord, Decl->methods());
324*12c85518Srobert recordObjCProperties(ObjCProtocolRecord, Decl->properties());
325*12c85518Srobert recordObjCProtocols(ObjCProtocolRecord, Decl->protocols());
326*12c85518Srobert
327*12c85518Srobert return true;
328*12c85518Srobert }
329*12c85518Srobert
VisitTypedefNameDecl(const TypedefNameDecl * Decl)330*12c85518Srobert bool ExtractAPIVisitor::VisitTypedefNameDecl(const TypedefNameDecl *Decl) {
331*12c85518Srobert // Skip ObjC Type Parameter for now.
332*12c85518Srobert if (isa<ObjCTypeParamDecl>(Decl))
333*12c85518Srobert return true;
334*12c85518Srobert
335*12c85518Srobert if (!Decl->isDefinedOutsideFunctionOrMethod())
336*12c85518Srobert return true;
337*12c85518Srobert
338*12c85518Srobert if (!LocationChecker(Decl->getLocation()))
339*12c85518Srobert return true;
340*12c85518Srobert
341*12c85518Srobert PresumedLoc Loc =
342*12c85518Srobert Context.getSourceManager().getPresumedLoc(Decl->getLocation());
343*12c85518Srobert StringRef Name = Decl->getName();
344*12c85518Srobert StringRef USR = API.recordUSR(Decl);
345*12c85518Srobert DocComment Comment;
346*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
347*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
348*12c85518Srobert Context.getDiagnostics());
349*12c85518Srobert
350*12c85518Srobert QualType Type = Decl->getUnderlyingType();
351*12c85518Srobert SymbolReference SymRef =
352*12c85518Srobert TypedefUnderlyingTypeResolver(Context).getSymbolReferenceForType(Type,
353*12c85518Srobert API);
354*12c85518Srobert
355*12c85518Srobert API.addTypedef(Name, USR, Loc, AvailabilitySet(Decl), Comment,
356*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl),
357*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef,
358*12c85518Srobert isInSystemHeader(Context, Decl));
359*12c85518Srobert
360*12c85518Srobert return true;
361*12c85518Srobert }
362*12c85518Srobert
VisitObjCCategoryDecl(const ObjCCategoryDecl * Decl)363*12c85518Srobert bool ExtractAPIVisitor::VisitObjCCategoryDecl(const ObjCCategoryDecl *Decl) {
364*12c85518Srobert // Collect symbol information.
365*12c85518Srobert StringRef Name = Decl->getName();
366*12c85518Srobert StringRef USR = API.recordUSR(Decl);
367*12c85518Srobert PresumedLoc Loc =
368*12c85518Srobert Context.getSourceManager().getPresumedLoc(Decl->getLocation());
369*12c85518Srobert DocComment Comment;
370*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
371*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
372*12c85518Srobert Context.getDiagnostics());
373*12c85518Srobert // Build declaration fragments and sub-heading for the category.
374*12c85518Srobert DeclarationFragments Declaration =
375*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForObjCCategory(Decl);
376*12c85518Srobert DeclarationFragments SubHeading =
377*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Decl);
378*12c85518Srobert
379*12c85518Srobert const ObjCInterfaceDecl *InterfaceDecl = Decl->getClassInterface();
380*12c85518Srobert SymbolReference Interface(InterfaceDecl->getName(),
381*12c85518Srobert API.recordUSR(InterfaceDecl));
382*12c85518Srobert
383*12c85518Srobert ObjCCategoryRecord *ObjCCategoryRecord = API.addObjCCategory(
384*12c85518Srobert Name, USR, Loc, AvailabilitySet(Decl), Comment, Declaration, SubHeading,
385*12c85518Srobert Interface, isInSystemHeader(Context, Decl));
386*12c85518Srobert
387*12c85518Srobert recordObjCMethods(ObjCCategoryRecord, Decl->methods());
388*12c85518Srobert recordObjCProperties(ObjCCategoryRecord, Decl->properties());
389*12c85518Srobert recordObjCInstanceVariables(ObjCCategoryRecord, Decl->ivars());
390*12c85518Srobert recordObjCProtocols(ObjCCategoryRecord, Decl->protocols());
391*12c85518Srobert
392*12c85518Srobert return true;
393*12c85518Srobert }
394*12c85518Srobert
395*12c85518Srobert /// Collect API information for the enum constants and associate with the
396*12c85518Srobert /// parent enum.
recordEnumConstants(EnumRecord * EnumRecord,const EnumDecl::enumerator_range Constants)397*12c85518Srobert void ExtractAPIVisitor::recordEnumConstants(
398*12c85518Srobert EnumRecord *EnumRecord, const EnumDecl::enumerator_range Constants) {
399*12c85518Srobert for (const auto *Constant : Constants) {
400*12c85518Srobert // Collect symbol information.
401*12c85518Srobert StringRef Name = Constant->getName();
402*12c85518Srobert StringRef USR = API.recordUSR(Constant);
403*12c85518Srobert PresumedLoc Loc =
404*12c85518Srobert Context.getSourceManager().getPresumedLoc(Constant->getLocation());
405*12c85518Srobert DocComment Comment;
406*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Constant))
407*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
408*12c85518Srobert Context.getDiagnostics());
409*12c85518Srobert
410*12c85518Srobert // Build declaration fragments and sub-heading for the enum constant.
411*12c85518Srobert DeclarationFragments Declaration =
412*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForEnumConstant(Constant);
413*12c85518Srobert DeclarationFragments SubHeading =
414*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Constant);
415*12c85518Srobert
416*12c85518Srobert API.addEnumConstant(EnumRecord, Name, USR, Loc, AvailabilitySet(Constant),
417*12c85518Srobert Comment, Declaration, SubHeading,
418*12c85518Srobert isInSystemHeader(Context, Constant));
419*12c85518Srobert }
420*12c85518Srobert }
421*12c85518Srobert
422*12c85518Srobert /// Collect API information for the struct fields and associate with the
423*12c85518Srobert /// parent struct.
recordStructFields(StructRecord * StructRecord,const RecordDecl::field_range Fields)424*12c85518Srobert void ExtractAPIVisitor::recordStructFields(
425*12c85518Srobert StructRecord *StructRecord, const RecordDecl::field_range Fields) {
426*12c85518Srobert for (const auto *Field : Fields) {
427*12c85518Srobert // Collect symbol information.
428*12c85518Srobert StringRef Name = Field->getName();
429*12c85518Srobert StringRef USR = API.recordUSR(Field);
430*12c85518Srobert PresumedLoc Loc =
431*12c85518Srobert Context.getSourceManager().getPresumedLoc(Field->getLocation());
432*12c85518Srobert DocComment Comment;
433*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Field))
434*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
435*12c85518Srobert Context.getDiagnostics());
436*12c85518Srobert
437*12c85518Srobert // Build declaration fragments and sub-heading for the struct field.
438*12c85518Srobert DeclarationFragments Declaration =
439*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForField(Field);
440*12c85518Srobert DeclarationFragments SubHeading =
441*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Field);
442*12c85518Srobert
443*12c85518Srobert API.addStructField(StructRecord, Name, USR, Loc, AvailabilitySet(Field),
444*12c85518Srobert Comment, Declaration, SubHeading,
445*12c85518Srobert isInSystemHeader(Context, Field));
446*12c85518Srobert }
447*12c85518Srobert }
448*12c85518Srobert
449*12c85518Srobert /// Collect API information for the Objective-C methods and associate with the
450*12c85518Srobert /// parent container.
recordObjCMethods(ObjCContainerRecord * Container,const ObjCContainerDecl::method_range Methods)451*12c85518Srobert void ExtractAPIVisitor::recordObjCMethods(
452*12c85518Srobert ObjCContainerRecord *Container,
453*12c85518Srobert const ObjCContainerDecl::method_range Methods) {
454*12c85518Srobert for (const auto *Method : Methods) {
455*12c85518Srobert // Don't record selectors for properties.
456*12c85518Srobert if (Method->isPropertyAccessor())
457*12c85518Srobert continue;
458*12c85518Srobert
459*12c85518Srobert StringRef Name = API.copyString(Method->getSelector().getAsString());
460*12c85518Srobert StringRef USR = API.recordUSR(Method);
461*12c85518Srobert PresumedLoc Loc =
462*12c85518Srobert Context.getSourceManager().getPresumedLoc(Method->getLocation());
463*12c85518Srobert DocComment Comment;
464*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Method))
465*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
466*12c85518Srobert Context.getDiagnostics());
467*12c85518Srobert
468*12c85518Srobert // Build declaration fragments, sub-heading, and signature for the method.
469*12c85518Srobert DeclarationFragments Declaration =
470*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForObjCMethod(Method);
471*12c85518Srobert DeclarationFragments SubHeading =
472*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Method);
473*12c85518Srobert FunctionSignature Signature =
474*12c85518Srobert DeclarationFragmentsBuilder::getFunctionSignature(Method);
475*12c85518Srobert
476*12c85518Srobert API.addObjCMethod(Container, Name, USR, Loc, AvailabilitySet(Method),
477*12c85518Srobert Comment, Declaration, SubHeading, Signature,
478*12c85518Srobert Method->isInstanceMethod(),
479*12c85518Srobert isInSystemHeader(Context, Method));
480*12c85518Srobert }
481*12c85518Srobert }
482*12c85518Srobert
recordObjCProperties(ObjCContainerRecord * Container,const ObjCContainerDecl::prop_range Properties)483*12c85518Srobert void ExtractAPIVisitor::recordObjCProperties(
484*12c85518Srobert ObjCContainerRecord *Container,
485*12c85518Srobert const ObjCContainerDecl::prop_range Properties) {
486*12c85518Srobert for (const auto *Property : Properties) {
487*12c85518Srobert StringRef Name = Property->getName();
488*12c85518Srobert StringRef USR = API.recordUSR(Property);
489*12c85518Srobert PresumedLoc Loc =
490*12c85518Srobert Context.getSourceManager().getPresumedLoc(Property->getLocation());
491*12c85518Srobert DocComment Comment;
492*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Property))
493*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
494*12c85518Srobert Context.getDiagnostics());
495*12c85518Srobert
496*12c85518Srobert // Build declaration fragments and sub-heading for the property.
497*12c85518Srobert DeclarationFragments Declaration =
498*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForObjCProperty(Property);
499*12c85518Srobert DeclarationFragments SubHeading =
500*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Property);
501*12c85518Srobert
502*12c85518Srobert StringRef GetterName =
503*12c85518Srobert API.copyString(Property->getGetterName().getAsString());
504*12c85518Srobert StringRef SetterName =
505*12c85518Srobert API.copyString(Property->getSetterName().getAsString());
506*12c85518Srobert
507*12c85518Srobert // Get the attributes for property.
508*12c85518Srobert unsigned Attributes = ObjCPropertyRecord::NoAttr;
509*12c85518Srobert if (Property->getPropertyAttributes() &
510*12c85518Srobert ObjCPropertyAttribute::kind_readonly)
511*12c85518Srobert Attributes |= ObjCPropertyRecord::ReadOnly;
512*12c85518Srobert
513*12c85518Srobert API.addObjCProperty(
514*12c85518Srobert Container, Name, USR, Loc, AvailabilitySet(Property), Comment,
515*12c85518Srobert Declaration, SubHeading,
516*12c85518Srobert static_cast<ObjCPropertyRecord::AttributeKind>(Attributes), GetterName,
517*12c85518Srobert SetterName, Property->isOptional(),
518*12c85518Srobert !(Property->getPropertyAttributes() &
519*12c85518Srobert ObjCPropertyAttribute::kind_class),
520*12c85518Srobert isInSystemHeader(Context, Property));
521*12c85518Srobert }
522*12c85518Srobert }
523*12c85518Srobert
recordObjCInstanceVariables(ObjCContainerRecord * Container,const llvm::iterator_range<DeclContext::specific_decl_iterator<ObjCIvarDecl>> Ivars)524*12c85518Srobert void ExtractAPIVisitor::recordObjCInstanceVariables(
525*12c85518Srobert ObjCContainerRecord *Container,
526*12c85518Srobert const llvm::iterator_range<
527*12c85518Srobert DeclContext::specific_decl_iterator<ObjCIvarDecl>>
528*12c85518Srobert Ivars) {
529*12c85518Srobert for (const auto *Ivar : Ivars) {
530*12c85518Srobert StringRef Name = Ivar->getName();
531*12c85518Srobert StringRef USR = API.recordUSR(Ivar);
532*12c85518Srobert PresumedLoc Loc =
533*12c85518Srobert Context.getSourceManager().getPresumedLoc(Ivar->getLocation());
534*12c85518Srobert DocComment Comment;
535*12c85518Srobert if (auto *RawComment = Context.getRawCommentForDeclNoCache(Ivar))
536*12c85518Srobert Comment = RawComment->getFormattedLines(Context.getSourceManager(),
537*12c85518Srobert Context.getDiagnostics());
538*12c85518Srobert
539*12c85518Srobert // Build declaration fragments and sub-heading for the instance variable.
540*12c85518Srobert DeclarationFragments Declaration =
541*12c85518Srobert DeclarationFragmentsBuilder::getFragmentsForField(Ivar);
542*12c85518Srobert DeclarationFragments SubHeading =
543*12c85518Srobert DeclarationFragmentsBuilder::getSubHeading(Ivar);
544*12c85518Srobert
545*12c85518Srobert ObjCInstanceVariableRecord::AccessControl Access =
546*12c85518Srobert Ivar->getCanonicalAccessControl();
547*12c85518Srobert
548*12c85518Srobert API.addObjCInstanceVariable(
549*12c85518Srobert Container, Name, USR, Loc, AvailabilitySet(Ivar), Comment, Declaration,
550*12c85518Srobert SubHeading, Access, isInSystemHeader(Context, Ivar));
551*12c85518Srobert }
552*12c85518Srobert }
553*12c85518Srobert
recordObjCProtocols(ObjCContainerRecord * Container,ObjCInterfaceDecl::protocol_range Protocols)554*12c85518Srobert void ExtractAPIVisitor::recordObjCProtocols(
555*12c85518Srobert ObjCContainerRecord *Container,
556*12c85518Srobert ObjCInterfaceDecl::protocol_range Protocols) {
557*12c85518Srobert for (const auto *Protocol : Protocols)
558*12c85518Srobert Container->Protocols.emplace_back(Protocol->getName(),
559*12c85518Srobert API.recordUSR(Protocol));
560*12c85518Srobert }
561