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