1 //===- ExtractAPI/API.cpp ---------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file implements the APIRecord and derived record structs,
11 /// and the APISet class.
13 //===----------------------------------------------------------------------===//
15 #include "clang/ExtractAPI/API.h"
16 #include "clang/AST/CommentCommandTraits.h"
17 #include "clang/AST/CommentLexer.h"
18 #include "clang/AST/RawCommentList.h"
19 #include "clang/Index/USRGeneration.h"
20 #include "llvm/ADT/STLFunctionalExtras.h"
21 #include "llvm/ADT/StringRef.h"
24 using namespace clang::extractapi
;
29 template <typename RecordTy
, typename
... CtorArgsTy
>
30 RecordTy
*addTopLevelRecord(APISet::RecordMap
<RecordTy
> &RecordMap
,
31 StringRef USR
, CtorArgsTy
&&...CtorArgs
) {
32 auto Result
= RecordMap
.insert({USR
, nullptr});
34 // Create the record if it does not already exist
36 Result
.first
->second
=
37 std::make_unique
<RecordTy
>(USR
, std::forward
<CtorArgsTy
>(CtorArgs
)...);
39 return Result
.first
->second
.get();
44 GlobalVariableRecord
*
45 APISet::addGlobalVar(StringRef Name
, StringRef USR
, PresumedLoc Loc
,
46 AvailabilitySet Availabilities
, LinkageInfo Linkage
,
47 const DocComment
&Comment
, DeclarationFragments Fragments
,
48 DeclarationFragments SubHeading
) {
49 return addTopLevelRecord(GlobalVariables
, USR
, Name
, Loc
,
50 std::move(Availabilities
), Linkage
, Comment
,
51 Fragments
, SubHeading
);
54 GlobalFunctionRecord
*APISet::addGlobalFunction(
55 StringRef Name
, StringRef USR
, PresumedLoc Loc
,
56 AvailabilitySet Availabilities
, LinkageInfo Linkage
,
57 const DocComment
&Comment
, DeclarationFragments Fragments
,
58 DeclarationFragments SubHeading
, FunctionSignature Signature
) {
59 return addTopLevelRecord(GlobalFunctions
, USR
, Name
, Loc
,
60 std::move(Availabilities
), Linkage
, Comment
,
61 Fragments
, SubHeading
, Signature
);
64 EnumConstantRecord
*APISet::addEnumConstant(EnumRecord
*Enum
, StringRef Name
,
65 StringRef USR
, PresumedLoc Loc
,
66 AvailabilitySet Availabilities
,
67 const DocComment
&Comment
,
68 DeclarationFragments Declaration
,
69 DeclarationFragments SubHeading
) {
70 auto Record
= std::make_unique
<EnumConstantRecord
>(
71 USR
, Name
, Loc
, std::move(Availabilities
), Comment
, Declaration
,
73 return Enum
->Constants
.emplace_back(std::move(Record
)).get();
76 EnumRecord
*APISet::addEnum(StringRef Name
, StringRef USR
, PresumedLoc Loc
,
77 AvailabilitySet Availabilities
,
78 const DocComment
&Comment
,
79 DeclarationFragments Declaration
,
80 DeclarationFragments SubHeading
) {
81 return addTopLevelRecord(Enums
, USR
, Name
, Loc
, std::move(Availabilities
),
82 Comment
, Declaration
, SubHeading
);
85 StructFieldRecord
*APISet::addStructField(StructRecord
*Struct
, StringRef Name
,
86 StringRef USR
, PresumedLoc Loc
,
87 AvailabilitySet Availabilities
,
88 const DocComment
&Comment
,
89 DeclarationFragments Declaration
,
90 DeclarationFragments SubHeading
) {
91 auto Record
= std::make_unique
<StructFieldRecord
>(
92 USR
, Name
, Loc
, std::move(Availabilities
), Comment
, Declaration
,
94 return Struct
->Fields
.emplace_back(std::move(Record
)).get();
97 StructRecord
*APISet::addStruct(StringRef Name
, StringRef USR
, PresumedLoc Loc
,
98 AvailabilitySet Availabilities
,
99 const DocComment
&Comment
,
100 DeclarationFragments Declaration
,
101 DeclarationFragments SubHeading
) {
102 return addTopLevelRecord(Structs
, USR
, Name
, Loc
, std::move(Availabilities
),
103 Comment
, Declaration
, SubHeading
);
106 ObjCCategoryRecord
*APISet::addObjCCategory(StringRef Name
, StringRef USR
,
108 AvailabilitySet Availabilities
,
109 const DocComment
&Comment
,
110 DeclarationFragments Declaration
,
111 DeclarationFragments SubHeading
,
112 SymbolReference Interface
) {
113 // Create the category record.
114 auto *Record
= addTopLevelRecord(ObjCCategories
, USR
, Name
, Loc
,
115 std::move(Availabilities
), Comment
,
116 Declaration
, SubHeading
, Interface
);
118 // If this category is extending a known interface, associate it with the
119 // ObjCInterfaceRecord.
120 auto It
= ObjCInterfaces
.find(Interface
.USR
);
121 if (It
!= ObjCInterfaces
.end())
122 It
->second
->Categories
.push_back(Record
);
127 ObjCInterfaceRecord
*APISet::addObjCInterface(
128 StringRef Name
, StringRef USR
, PresumedLoc Loc
,
129 AvailabilitySet Availabilities
, LinkageInfo Linkage
,
130 const DocComment
&Comment
, DeclarationFragments Declaration
,
131 DeclarationFragments SubHeading
, SymbolReference SuperClass
) {
132 return addTopLevelRecord(ObjCInterfaces
, USR
, Name
, Loc
,
133 std::move(Availabilities
), Linkage
, Comment
,
134 Declaration
, SubHeading
, SuperClass
);
137 ObjCMethodRecord
*APISet::addObjCMethod(
138 ObjCContainerRecord
*Container
, StringRef Name
, StringRef USR
,
139 PresumedLoc Loc
, AvailabilitySet Availabilities
, const DocComment
&Comment
,
140 DeclarationFragments Declaration
, DeclarationFragments SubHeading
,
141 FunctionSignature Signature
, bool IsInstanceMethod
) {
142 auto Record
= std::make_unique
<ObjCMethodRecord
>(
143 USR
, Name
, Loc
, std::move(Availabilities
), Comment
, Declaration
,
144 SubHeading
, Signature
, IsInstanceMethod
);
145 return Container
->Methods
.emplace_back(std::move(Record
)).get();
148 ObjCPropertyRecord
*APISet::addObjCProperty(
149 ObjCContainerRecord
*Container
, StringRef Name
, StringRef USR
,
150 PresumedLoc Loc
, AvailabilitySet Availabilities
, const DocComment
&Comment
,
151 DeclarationFragments Declaration
, DeclarationFragments SubHeading
,
152 ObjCPropertyRecord::AttributeKind Attributes
, StringRef GetterName
,
153 StringRef SetterName
, bool IsOptional
) {
154 auto Record
= std::make_unique
<ObjCPropertyRecord
>(
155 USR
, Name
, Loc
, std::move(Availabilities
), Comment
, Declaration
,
156 SubHeading
, Attributes
, GetterName
, SetterName
, IsOptional
);
157 return Container
->Properties
.emplace_back(std::move(Record
)).get();
160 ObjCInstanceVariableRecord
*APISet::addObjCInstanceVariable(
161 ObjCContainerRecord
*Container
, StringRef Name
, StringRef USR
,
162 PresumedLoc Loc
, AvailabilitySet Availabilities
, const DocComment
&Comment
,
163 DeclarationFragments Declaration
, DeclarationFragments SubHeading
,
164 ObjCInstanceVariableRecord::AccessControl Access
) {
165 auto Record
= std::make_unique
<ObjCInstanceVariableRecord
>(
166 USR
, Name
, Loc
, std::move(Availabilities
), Comment
, Declaration
,
168 return Container
->Ivars
.emplace_back(std::move(Record
)).get();
171 ObjCProtocolRecord
*APISet::addObjCProtocol(StringRef Name
, StringRef USR
,
173 AvailabilitySet Availabilities
,
174 const DocComment
&Comment
,
175 DeclarationFragments Declaration
,
176 DeclarationFragments SubHeading
) {
177 return addTopLevelRecord(ObjCProtocols
, USR
, Name
, Loc
,
178 std::move(Availabilities
), Comment
, Declaration
,
182 MacroDefinitionRecord
*
183 APISet::addMacroDefinition(StringRef Name
, StringRef USR
, PresumedLoc Loc
,
184 DeclarationFragments Declaration
,
185 DeclarationFragments SubHeading
) {
186 return addTopLevelRecord(Macros
, USR
, Name
, Loc
, Declaration
, SubHeading
);
189 TypedefRecord
*APISet::addTypedef(StringRef Name
, StringRef USR
,
191 AvailabilitySet Availabilities
,
192 const DocComment
&Comment
,
193 DeclarationFragments Declaration
,
194 DeclarationFragments SubHeading
,
195 SymbolReference UnderlyingType
) {
196 return addTopLevelRecord(Typedefs
, USR
, Name
, Loc
, std::move(Availabilities
),
197 Comment
, Declaration
, SubHeading
, UnderlyingType
);
200 StringRef
APISet::recordUSR(const Decl
*D
) {
201 SmallString
<128> USR
;
202 index::generateUSRForDecl(D
, USR
);
203 return copyString(USR
);
206 StringRef
APISet::recordUSRForMacro(StringRef Name
, SourceLocation SL
,
207 const SourceManager
&SM
) {
208 SmallString
<128> USR
;
209 index::generateUSRForMacro(Name
, SL
, SM
, USR
);
210 return copyString(USR
);
213 StringRef
APISet::copyString(StringRef String
) {
217 // No need to allocate memory and copy if the string has already been stored.
218 if (StringAllocator
.identifyObject(String
.data()))
221 void *Ptr
= StringAllocator
.Allocate(String
.size(), 1);
222 memcpy(Ptr
, String
.data(), String
.size());
223 return StringRef(reinterpret_cast<const char *>(Ptr
), String
.size());
226 APIRecord::~APIRecord() {}
228 ObjCContainerRecord::~ObjCContainerRecord() {}
230 void GlobalFunctionRecord::anchor() {}
231 void GlobalVariableRecord::anchor() {}
232 void EnumConstantRecord::anchor() {}
233 void EnumRecord::anchor() {}
234 void StructFieldRecord::anchor() {}
235 void StructRecord::anchor() {}
236 void ObjCPropertyRecord::anchor() {}
237 void ObjCInstanceVariableRecord::anchor() {}
238 void ObjCMethodRecord::anchor() {}
239 void ObjCCategoryRecord::anchor() {}
240 void ObjCInterfaceRecord::anchor() {}
241 void ObjCProtocolRecord::anchor() {}
242 void MacroDefinitionRecord::anchor() {}
243 void TypedefRecord::anchor() {}