189f6b26fSZixu Wang //===- ExtractAPI/API.cpp ---------------------------------------*- C++ -*-===//
289f6b26fSZixu Wang //
389f6b26fSZixu Wang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
489f6b26fSZixu Wang // See https://llvm.org/LICENSE.txt for license information.
589f6b26fSZixu Wang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
689f6b26fSZixu Wang //
789f6b26fSZixu Wang //===----------------------------------------------------------------------===//
889f6b26fSZixu Wang ///
989f6b26fSZixu Wang /// \file
1089f6b26fSZixu Wang /// This file implements the APIRecord and derived record structs,
1189f6b26fSZixu Wang /// and the APISet class.
1289f6b26fSZixu Wang ///
1389f6b26fSZixu Wang //===----------------------------------------------------------------------===//
1489f6b26fSZixu Wang 
1589f6b26fSZixu Wang #include "clang/ExtractAPI/API.h"
1689f6b26fSZixu Wang #include "clang/AST/CommentCommandTraits.h"
1789f6b26fSZixu Wang #include "clang/AST/CommentLexer.h"
1889f6b26fSZixu Wang #include "clang/AST/RawCommentList.h"
1989f6b26fSZixu Wang #include "clang/Index/USRGeneration.h"
20529a0570SDaniel Grumberg #include "llvm/ADT/STLFunctionalExtras.h"
21529a0570SDaniel Grumberg #include "llvm/ADT/StringRef.h"
220ee06c31SDaniel Grumberg #include <memory>
2389f6b26fSZixu Wang 
2489f6b26fSZixu Wang using namespace clang::extractapi;
2589f6b26fSZixu Wang using namespace llvm;
2689f6b26fSZixu Wang 
27529a0570SDaniel Grumberg namespace {
28529a0570SDaniel Grumberg 
29529a0570SDaniel Grumberg template <typename RecordTy, typename... CtorArgsTy>
30529a0570SDaniel Grumberg RecordTy *addTopLevelRecord(APISet::RecordMap<RecordTy> &RecordMap,
31529a0570SDaniel Grumberg                             StringRef Name, CtorArgsTy &&...CtorArgs) {
32529a0570SDaniel Grumberg   auto Result = RecordMap.insert({Name, nullptr});
33529a0570SDaniel Grumberg 
34529a0570SDaniel Grumberg   // Create the record if it does not already exist
35529a0570SDaniel Grumberg   if (Result.second)
36529a0570SDaniel Grumberg     Result.first->second =
37529a0570SDaniel Grumberg         std::make_unique<RecordTy>(Name, std::forward<CtorArgsTy>(CtorArgs)...);
38529a0570SDaniel Grumberg 
39529a0570SDaniel Grumberg   return Result.first->second.get();
40529a0570SDaniel Grumberg }
41529a0570SDaniel Grumberg 
42529a0570SDaniel Grumberg } // namespace
43529a0570SDaniel Grumberg 
4489f6b26fSZixu Wang GlobalRecord *APISet::addGlobal(GVKind Kind, StringRef Name, StringRef USR,
4589f6b26fSZixu Wang                                 PresumedLoc Loc,
4689f6b26fSZixu Wang                                 const AvailabilityInfo &Availability,
4789f6b26fSZixu Wang                                 LinkageInfo Linkage, const DocComment &Comment,
4889f6b26fSZixu Wang                                 DeclarationFragments Fragments,
4989f6b26fSZixu Wang                                 DeclarationFragments SubHeading,
5089f6b26fSZixu Wang                                 FunctionSignature Signature) {
51529a0570SDaniel Grumberg   return addTopLevelRecord(Globals, Name, USR, Loc, Availability, Linkage,
52529a0570SDaniel Grumberg                            Comment, Fragments, SubHeading, Kind, Signature);
5389f6b26fSZixu Wang }
5489f6b26fSZixu Wang 
5589f6b26fSZixu Wang GlobalRecord *
5689f6b26fSZixu Wang APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
5789f6b26fSZixu Wang                      const AvailabilityInfo &Availability, LinkageInfo Linkage,
5889f6b26fSZixu Wang                      const DocComment &Comment, DeclarationFragments Fragments,
5989f6b26fSZixu Wang                      DeclarationFragments SubHeading) {
6089f6b26fSZixu Wang   return addGlobal(GVKind::Variable, Name, USR, Loc, Availability, Linkage,
6189f6b26fSZixu Wang                    Comment, Fragments, SubHeading, {});
6289f6b26fSZixu Wang }
6389f6b26fSZixu Wang 
6489f6b26fSZixu Wang GlobalRecord *
6589f6b26fSZixu Wang APISet::addFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
6689f6b26fSZixu Wang                     const AvailabilityInfo &Availability, LinkageInfo Linkage,
6789f6b26fSZixu Wang                     const DocComment &Comment, DeclarationFragments Fragments,
6889f6b26fSZixu Wang                     DeclarationFragments SubHeading,
6989f6b26fSZixu Wang                     FunctionSignature Signature) {
7089f6b26fSZixu Wang   return addGlobal(GVKind::Function, Name, USR, Loc, Availability, Linkage,
7189f6b26fSZixu Wang                    Comment, Fragments, SubHeading, Signature);
7289f6b26fSZixu Wang }
7389f6b26fSZixu Wang 
7471b4c226SZixu Wang EnumConstantRecord *APISet::addEnumConstant(
7571b4c226SZixu Wang     EnumRecord *Enum, StringRef Name, StringRef USR, PresumedLoc Loc,
7671b4c226SZixu Wang     const AvailabilityInfo &Availability, const DocComment &Comment,
7771b4c226SZixu Wang     DeclarationFragments Declaration, DeclarationFragments SubHeading) {
780ee06c31SDaniel Grumberg   auto Record = std::make_unique<EnumConstantRecord>(
790ee06c31SDaniel Grumberg       Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
8071b4c226SZixu Wang   return Enum->Constants.emplace_back(std::move(Record)).get();
8171b4c226SZixu Wang }
8271b4c226SZixu Wang 
8371b4c226SZixu Wang EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
8471b4c226SZixu Wang                             const AvailabilityInfo &Availability,
8571b4c226SZixu Wang                             const DocComment &Comment,
8671b4c226SZixu Wang                             DeclarationFragments Declaration,
8771b4c226SZixu Wang                             DeclarationFragments SubHeading) {
88529a0570SDaniel Grumberg   return addTopLevelRecord(Enums, Name, USR, Loc, Availability, Comment,
89529a0570SDaniel Grumberg                            Declaration, SubHeading);
9071b4c226SZixu Wang }
9171b4c226SZixu Wang 
925bb5704cSZixu Wang StructFieldRecord *APISet::addStructField(StructRecord *Struct, StringRef Name,
935bb5704cSZixu Wang                                           StringRef USR, PresumedLoc Loc,
945bb5704cSZixu Wang                                           const AvailabilityInfo &Availability,
955bb5704cSZixu Wang                                           const DocComment &Comment,
965bb5704cSZixu Wang                                           DeclarationFragments Declaration,
975bb5704cSZixu Wang                                           DeclarationFragments SubHeading) {
980ee06c31SDaniel Grumberg   auto Record = std::make_unique<StructFieldRecord>(
990ee06c31SDaniel Grumberg       Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
1005bb5704cSZixu Wang   return Struct->Fields.emplace_back(std::move(Record)).get();
1015bb5704cSZixu Wang }
1025bb5704cSZixu Wang 
1035bb5704cSZixu Wang StructRecord *APISet::addStruct(StringRef Name, StringRef USR, PresumedLoc Loc,
1045bb5704cSZixu Wang                                 const AvailabilityInfo &Availability,
1055bb5704cSZixu Wang                                 const DocComment &Comment,
1065bb5704cSZixu Wang                                 DeclarationFragments Declaration,
1075bb5704cSZixu Wang                                 DeclarationFragments SubHeading) {
108529a0570SDaniel Grumberg   return addTopLevelRecord(Structs, Name, USR, Loc, Availability, Comment,
109529a0570SDaniel Grumberg                            Declaration, SubHeading);
1105bb5704cSZixu Wang }
1115bb5704cSZixu Wang 
1129b36e126SZixu Wang ObjCInterfaceRecord *APISet::addObjCInterface(
1139b36e126SZixu Wang     StringRef Name, StringRef USR, PresumedLoc Loc,
1149b36e126SZixu Wang     const AvailabilityInfo &Availability, LinkageInfo Linkage,
1159b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
1169b36e126SZixu Wang     DeclarationFragments SubHeading, SymbolReference SuperClass) {
117529a0570SDaniel Grumberg   return addTopLevelRecord(ObjCInterfaces, Name, USR, Loc, Availability,
118529a0570SDaniel Grumberg                            Linkage, Comment, Declaration, SubHeading,
1199b36e126SZixu Wang                            SuperClass);
1209b36e126SZixu Wang }
1219b36e126SZixu Wang 
1229b36e126SZixu Wang ObjCMethodRecord *APISet::addObjCMethod(
1239b36e126SZixu Wang     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
1249b36e126SZixu Wang     PresumedLoc Loc, const AvailabilityInfo &Availability,
1259b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
1269b36e126SZixu Wang     DeclarationFragments SubHeading, FunctionSignature Signature,
1279b36e126SZixu Wang     bool IsInstanceMethod) {
1289b36e126SZixu Wang   auto Record = std::make_unique<ObjCMethodRecord>(
1299b36e126SZixu Wang       Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Signature,
1309b36e126SZixu Wang       IsInstanceMethod);
1319b36e126SZixu Wang   return Container->Methods.emplace_back(std::move(Record)).get();
1329b36e126SZixu Wang }
1339b36e126SZixu Wang 
1349b36e126SZixu Wang ObjCPropertyRecord *APISet::addObjCProperty(
1359b36e126SZixu Wang     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
1369b36e126SZixu Wang     PresumedLoc Loc, const AvailabilityInfo &Availability,
1379b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
1389b36e126SZixu Wang     DeclarationFragments SubHeading,
1399b36e126SZixu Wang     ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName,
1409b36e126SZixu Wang     StringRef SetterName, bool IsOptional) {
1419b36e126SZixu Wang   auto Record = std::make_unique<ObjCPropertyRecord>(
1429b36e126SZixu Wang       Name, USR, Loc, Availability, Comment, Declaration, SubHeading,
1439b36e126SZixu Wang       Attributes, GetterName, SetterName, IsOptional);
1449b36e126SZixu Wang   return Container->Properties.emplace_back(std::move(Record)).get();
1459b36e126SZixu Wang }
1469b36e126SZixu Wang 
1479b36e126SZixu Wang ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable(
1489b36e126SZixu Wang     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
1499b36e126SZixu Wang     PresumedLoc Loc, const AvailabilityInfo &Availability,
1509b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
1519b36e126SZixu Wang     DeclarationFragments SubHeading,
1529b36e126SZixu Wang     ObjCInstanceVariableRecord::AccessControl Access) {
1539b36e126SZixu Wang   auto Record = std::make_unique<ObjCInstanceVariableRecord>(
1549b36e126SZixu Wang       Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Access);
1559b36e126SZixu Wang   return Container->Ivars.emplace_back(std::move(Record)).get();
1569b36e126SZixu Wang }
1579b36e126SZixu Wang 
158d1d34bafSZixu Wang ObjCProtocolRecord *APISet::addObjCProtocol(
159d1d34bafSZixu Wang     StringRef Name, StringRef USR, PresumedLoc Loc,
160d1d34bafSZixu Wang     const AvailabilityInfo &Availability, const DocComment &Comment,
161d1d34bafSZixu Wang     DeclarationFragments Declaration, DeclarationFragments SubHeading) {
162529a0570SDaniel Grumberg   return addTopLevelRecord(ObjCProtocols, Name, USR, Loc, Availability, Comment,
163529a0570SDaniel Grumberg                            Declaration, SubHeading);
164d1d34bafSZixu Wang }
165529a0570SDaniel Grumberg 
166529a0570SDaniel Grumberg MacroDefinitionRecord *
167529a0570SDaniel Grumberg APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc,
168529a0570SDaniel Grumberg                            DeclarationFragments Declaration,
169529a0570SDaniel Grumberg                            DeclarationFragments SubHeading) {
170529a0570SDaniel Grumberg   return addTopLevelRecord(Macros, Name, USR, Loc, Declaration, SubHeading);
171d1d34bafSZixu Wang }
172d1d34bafSZixu Wang 
173*9fc45ca0SDaniel Grumberg TypedefRecord *APISet::addTypedef(StringRef Name, StringRef USR,
174*9fc45ca0SDaniel Grumberg                                   PresumedLoc Loc,
175*9fc45ca0SDaniel Grumberg                                   const AvailabilityInfo &Availability,
176*9fc45ca0SDaniel Grumberg                                   const DocComment &Comment,
177*9fc45ca0SDaniel Grumberg                                   DeclarationFragments Declaration,
178*9fc45ca0SDaniel Grumberg                                   DeclarationFragments SubHeading,
179*9fc45ca0SDaniel Grumberg                                   SymbolReference UnderlyingType) {
180*9fc45ca0SDaniel Grumberg   return addTopLevelRecord(Typedefs, Name, USR, Loc, Availability, Comment,
181*9fc45ca0SDaniel Grumberg                            Declaration, SubHeading, UnderlyingType);
182*9fc45ca0SDaniel Grumberg }
183*9fc45ca0SDaniel Grumberg 
18489f6b26fSZixu Wang StringRef APISet::recordUSR(const Decl *D) {
18589f6b26fSZixu Wang   SmallString<128> USR;
18689f6b26fSZixu Wang   index::generateUSRForDecl(D, USR);
18789f6b26fSZixu Wang   return copyString(USR);
18889f6b26fSZixu Wang }
18989f6b26fSZixu Wang 
190529a0570SDaniel Grumberg StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL,
191529a0570SDaniel Grumberg                                     const SourceManager &SM) {
192529a0570SDaniel Grumberg   SmallString<128> USR;
193529a0570SDaniel Grumberg   index::generateUSRForMacro(Name, SL, SM, USR);
194529a0570SDaniel Grumberg   return copyString(USR);
195529a0570SDaniel Grumberg }
196529a0570SDaniel Grumberg 
19789f6b26fSZixu Wang StringRef APISet::copyString(StringRef String) {
19889f6b26fSZixu Wang   if (String.empty())
19989f6b26fSZixu Wang     return {};
20089f6b26fSZixu Wang 
20189f6b26fSZixu Wang   // No need to allocate memory and copy if the string has already been stored.
2020ee06c31SDaniel Grumberg   if (StringAllocator.identifyObject(String.data()))
20389f6b26fSZixu Wang     return String;
20489f6b26fSZixu Wang 
2050ee06c31SDaniel Grumberg   void *Ptr = StringAllocator.Allocate(String.size(), 1);
20689f6b26fSZixu Wang   memcpy(Ptr, String.data(), String.size());
20789f6b26fSZixu Wang   return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
20889f6b26fSZixu Wang }
20989f6b26fSZixu Wang 
21089f6b26fSZixu Wang APIRecord::~APIRecord() {}
21189f6b26fSZixu Wang 
2129b36e126SZixu Wang ObjCContainerRecord::~ObjCContainerRecord() {}
2139b36e126SZixu Wang 
21489f6b26fSZixu Wang void GlobalRecord::anchor() {}
215e5a7d272SZixu Wang void EnumConstantRecord::anchor() {}
216e5a7d272SZixu Wang void EnumRecord::anchor() {}
217e5a7d272SZixu Wang void StructFieldRecord::anchor() {}
218e5a7d272SZixu Wang void StructRecord::anchor() {}
2199b36e126SZixu Wang void ObjCPropertyRecord::anchor() {}
2209b36e126SZixu Wang void ObjCInstanceVariableRecord::anchor() {}
2219b36e126SZixu Wang void ObjCMethodRecord::anchor() {}
2229b36e126SZixu Wang void ObjCInterfaceRecord::anchor() {}
223d1d34bafSZixu Wang void ObjCProtocolRecord::anchor() {}
224529a0570SDaniel Grumberg void MacroDefinitionRecord::anchor() {}
225*9fc45ca0SDaniel Grumberg void TypedefRecord::anchor() {}
226