xref: /llvm-project/clang/lib/ExtractAPI/API.cpp (revision 529a0570f7e8c5144bd3ad057e43f00e3af58d1b)
1 //===- ExtractAPI/API.cpp ---------------------------------------*- 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 implements the APIRecord and derived record structs,
11 /// and the APISet class.
12 ///
13 //===----------------------------------------------------------------------===//
14 
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"
22 #include <memory>
23 
24 using namespace clang::extractapi;
25 using namespace llvm;
26 
27 namespace {
28 
29 template <typename RecordTy, typename... CtorArgsTy>
30 RecordTy *addTopLevelRecord(APISet::RecordMap<RecordTy> &RecordMap,
31                             StringRef Name, CtorArgsTy &&...CtorArgs) {
32   auto Result = RecordMap.insert({Name, nullptr});
33 
34   // Create the record if it does not already exist
35   if (Result.second)
36     Result.first->second =
37         std::make_unique<RecordTy>(Name, std::forward<CtorArgsTy>(CtorArgs)...);
38 
39   return Result.first->second.get();
40 }
41 
42 } // namespace
43 
44 GlobalRecord *APISet::addGlobal(GVKind Kind, StringRef Name, StringRef USR,
45                                 PresumedLoc Loc,
46                                 const AvailabilityInfo &Availability,
47                                 LinkageInfo Linkage, const DocComment &Comment,
48                                 DeclarationFragments Fragments,
49                                 DeclarationFragments SubHeading,
50                                 FunctionSignature Signature) {
51   return addTopLevelRecord(Globals, Name, USR, Loc, Availability, Linkage,
52                            Comment, Fragments, SubHeading, Kind, Signature);
53 }
54 
55 GlobalRecord *
56 APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
57                      const AvailabilityInfo &Availability, LinkageInfo Linkage,
58                      const DocComment &Comment, DeclarationFragments Fragments,
59                      DeclarationFragments SubHeading) {
60   return addGlobal(GVKind::Variable, Name, USR, Loc, Availability, Linkage,
61                    Comment, Fragments, SubHeading, {});
62 }
63 
64 GlobalRecord *
65 APISet::addFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
66                     const AvailabilityInfo &Availability, LinkageInfo Linkage,
67                     const DocComment &Comment, DeclarationFragments Fragments,
68                     DeclarationFragments SubHeading,
69                     FunctionSignature Signature) {
70   return addGlobal(GVKind::Function, Name, USR, Loc, Availability, Linkage,
71                    Comment, Fragments, SubHeading, Signature);
72 }
73 
74 EnumConstantRecord *APISet::addEnumConstant(
75     EnumRecord *Enum, StringRef Name, StringRef USR, PresumedLoc Loc,
76     const AvailabilityInfo &Availability, const DocComment &Comment,
77     DeclarationFragments Declaration, DeclarationFragments SubHeading) {
78   auto Record = std::make_unique<EnumConstantRecord>(
79       Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
80   return Enum->Constants.emplace_back(std::move(Record)).get();
81 }
82 
83 EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
84                             const AvailabilityInfo &Availability,
85                             const DocComment &Comment,
86                             DeclarationFragments Declaration,
87                             DeclarationFragments SubHeading) {
88   return addTopLevelRecord(Enums, Name, USR, Loc, Availability, Comment,
89                            Declaration, SubHeading);
90 }
91 
92 StructFieldRecord *APISet::addStructField(StructRecord *Struct, StringRef Name,
93                                           StringRef USR, PresumedLoc Loc,
94                                           const AvailabilityInfo &Availability,
95                                           const DocComment &Comment,
96                                           DeclarationFragments Declaration,
97                                           DeclarationFragments SubHeading) {
98   auto Record = std::make_unique<StructFieldRecord>(
99       Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
100   return Struct->Fields.emplace_back(std::move(Record)).get();
101 }
102 
103 StructRecord *APISet::addStruct(StringRef Name, StringRef USR, PresumedLoc Loc,
104                                 const AvailabilityInfo &Availability,
105                                 const DocComment &Comment,
106                                 DeclarationFragments Declaration,
107                                 DeclarationFragments SubHeading) {
108   return addTopLevelRecord(Structs, Name, USR, Loc, Availability, Comment,
109                            Declaration, SubHeading);
110 }
111 
112 ObjCInterfaceRecord *APISet::addObjCInterface(
113     StringRef Name, StringRef USR, PresumedLoc Loc,
114     const AvailabilityInfo &Availability, LinkageInfo Linkage,
115     const DocComment &Comment, DeclarationFragments Declaration,
116     DeclarationFragments SubHeading, SymbolReference SuperClass) {
117   return addTopLevelRecord(ObjCInterfaces, Name, USR, Loc, Availability,
118                            Linkage, Comment, Declaration, SubHeading,
119                            SuperClass);
120 }
121 
122 ObjCMethodRecord *APISet::addObjCMethod(
123     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
124     PresumedLoc Loc, const AvailabilityInfo &Availability,
125     const DocComment &Comment, DeclarationFragments Declaration,
126     DeclarationFragments SubHeading, FunctionSignature Signature,
127     bool IsInstanceMethod) {
128   auto Record = std::make_unique<ObjCMethodRecord>(
129       Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Signature,
130       IsInstanceMethod);
131   return Container->Methods.emplace_back(std::move(Record)).get();
132 }
133 
134 ObjCPropertyRecord *APISet::addObjCProperty(
135     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
136     PresumedLoc Loc, const AvailabilityInfo &Availability,
137     const DocComment &Comment, DeclarationFragments Declaration,
138     DeclarationFragments SubHeading,
139     ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName,
140     StringRef SetterName, bool IsOptional) {
141   auto Record = std::make_unique<ObjCPropertyRecord>(
142       Name, USR, Loc, Availability, Comment, Declaration, SubHeading,
143       Attributes, GetterName, SetterName, IsOptional);
144   return Container->Properties.emplace_back(std::move(Record)).get();
145 }
146 
147 ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable(
148     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
149     PresumedLoc Loc, const AvailabilityInfo &Availability,
150     const DocComment &Comment, DeclarationFragments Declaration,
151     DeclarationFragments SubHeading,
152     ObjCInstanceVariableRecord::AccessControl Access) {
153   auto Record = std::make_unique<ObjCInstanceVariableRecord>(
154       Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Access);
155   return Container->Ivars.emplace_back(std::move(Record)).get();
156 }
157 
158 ObjCProtocolRecord *APISet::addObjCProtocol(
159     StringRef Name, StringRef USR, PresumedLoc Loc,
160     const AvailabilityInfo &Availability, const DocComment &Comment,
161     DeclarationFragments Declaration, DeclarationFragments SubHeading) {
162   return addTopLevelRecord(ObjCProtocols, Name, USR, Loc, Availability, Comment,
163                            Declaration, SubHeading);
164 }
165 
166 MacroDefinitionRecord *
167 APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc,
168                            DeclarationFragments Declaration,
169                            DeclarationFragments SubHeading) {
170   return addTopLevelRecord(Macros, Name, USR, Loc, Declaration, SubHeading);
171 }
172 
173 StringRef APISet::recordUSR(const Decl *D) {
174   SmallString<128> USR;
175   index::generateUSRForDecl(D, USR);
176   return copyString(USR);
177 }
178 
179 StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL,
180                                     const SourceManager &SM) {
181   SmallString<128> USR;
182   index::generateUSRForMacro(Name, SL, SM, USR);
183   return copyString(USR);
184 }
185 
186 StringRef APISet::copyString(StringRef String) {
187   if (String.empty())
188     return {};
189 
190   // No need to allocate memory and copy if the string has already been stored.
191   if (StringAllocator.identifyObject(String.data()))
192     return String;
193 
194   void *Ptr = StringAllocator.Allocate(String.size(), 1);
195   memcpy(Ptr, String.data(), String.size());
196   return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
197 }
198 
199 APIRecord::~APIRecord() {}
200 
201 ObjCContainerRecord::~ObjCContainerRecord() {}
202 
203 void GlobalRecord::anchor() {}
204 void EnumConstantRecord::anchor() {}
205 void EnumRecord::anchor() {}
206 void StructFieldRecord::anchor() {}
207 void StructRecord::anchor() {}
208 void ObjCPropertyRecord::anchor() {}
209 void ObjCInstanceVariableRecord::anchor() {}
210 void ObjCMethodRecord::anchor() {}
211 void ObjCInterfaceRecord::anchor() {}
212 void ObjCProtocolRecord::anchor() {}
213 void MacroDefinitionRecord::anchor() {}
214