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"
200ee06c31SDaniel Grumberg #include <memory>
2189f6b26fSZixu Wang 
2289f6b26fSZixu Wang using namespace clang::extractapi;
2389f6b26fSZixu Wang using namespace llvm;
2489f6b26fSZixu Wang 
2589f6b26fSZixu Wang GlobalRecord *APISet::addGlobal(GVKind Kind, StringRef Name, StringRef USR,
2689f6b26fSZixu Wang                                 PresumedLoc Loc,
2789f6b26fSZixu Wang                                 const AvailabilityInfo &Availability,
2889f6b26fSZixu Wang                                 LinkageInfo Linkage, const DocComment &Comment,
2989f6b26fSZixu Wang                                 DeclarationFragments Fragments,
3089f6b26fSZixu Wang                                 DeclarationFragments SubHeading,
3189f6b26fSZixu Wang                                 FunctionSignature Signature) {
3289f6b26fSZixu Wang   auto Result = Globals.insert({Name, nullptr});
3389f6b26fSZixu Wang   if (Result.second) {
3489f6b26fSZixu Wang     // Create the record if it does not already exist.
350ee06c31SDaniel Grumberg     auto Record = std::make_unique<GlobalRecord>(
3689f6b26fSZixu Wang         Kind, Name, USR, Loc, Availability, Linkage, Comment, Fragments,
370ee06c31SDaniel Grumberg         SubHeading, Signature);
3889f6b26fSZixu Wang     Result.first->second = std::move(Record);
3989f6b26fSZixu Wang   }
4089f6b26fSZixu Wang   return Result.first->second.get();
4189f6b26fSZixu Wang }
4289f6b26fSZixu Wang 
4389f6b26fSZixu Wang GlobalRecord *
4489f6b26fSZixu Wang APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
4589f6b26fSZixu Wang                      const AvailabilityInfo &Availability, LinkageInfo Linkage,
4689f6b26fSZixu Wang                      const DocComment &Comment, DeclarationFragments Fragments,
4789f6b26fSZixu Wang                      DeclarationFragments SubHeading) {
4889f6b26fSZixu Wang   return addGlobal(GVKind::Variable, Name, USR, Loc, Availability, Linkage,
4989f6b26fSZixu Wang                    Comment, Fragments, SubHeading, {});
5089f6b26fSZixu Wang }
5189f6b26fSZixu Wang 
5289f6b26fSZixu Wang GlobalRecord *
5389f6b26fSZixu Wang APISet::addFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
5489f6b26fSZixu Wang                     const AvailabilityInfo &Availability, LinkageInfo Linkage,
5589f6b26fSZixu Wang                     const DocComment &Comment, DeclarationFragments Fragments,
5689f6b26fSZixu Wang                     DeclarationFragments SubHeading,
5789f6b26fSZixu Wang                     FunctionSignature Signature) {
5889f6b26fSZixu Wang   return addGlobal(GVKind::Function, Name, USR, Loc, Availability, Linkage,
5989f6b26fSZixu Wang                    Comment, Fragments, SubHeading, Signature);
6089f6b26fSZixu Wang }
6189f6b26fSZixu Wang 
6271b4c226SZixu Wang EnumConstantRecord *APISet::addEnumConstant(
6371b4c226SZixu Wang     EnumRecord *Enum, StringRef Name, StringRef USR, PresumedLoc Loc,
6471b4c226SZixu Wang     const AvailabilityInfo &Availability, const DocComment &Comment,
6571b4c226SZixu Wang     DeclarationFragments Declaration, DeclarationFragments SubHeading) {
660ee06c31SDaniel Grumberg   auto Record = std::make_unique<EnumConstantRecord>(
670ee06c31SDaniel Grumberg       Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
6871b4c226SZixu Wang   return Enum->Constants.emplace_back(std::move(Record)).get();
6971b4c226SZixu Wang }
7071b4c226SZixu Wang 
7171b4c226SZixu Wang EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
7271b4c226SZixu Wang                             const AvailabilityInfo &Availability,
7371b4c226SZixu Wang                             const DocComment &Comment,
7471b4c226SZixu Wang                             DeclarationFragments Declaration,
7571b4c226SZixu Wang                             DeclarationFragments SubHeading) {
7671b4c226SZixu Wang   auto Result = Enums.insert({Name, nullptr});
7771b4c226SZixu Wang   if (Result.second) {
7871b4c226SZixu Wang     // Create the record if it does not already exist.
790ee06c31SDaniel Grumberg     auto Record = std::make_unique<EnumRecord>(
800ee06c31SDaniel Grumberg         Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
8171b4c226SZixu Wang     Result.first->second = std::move(Record);
8271b4c226SZixu Wang   }
8371b4c226SZixu Wang   return Result.first->second.get();
8471b4c226SZixu Wang }
8571b4c226SZixu Wang 
865bb5704cSZixu Wang StructFieldRecord *APISet::addStructField(StructRecord *Struct, StringRef Name,
875bb5704cSZixu Wang                                           StringRef USR, PresumedLoc Loc,
885bb5704cSZixu Wang                                           const AvailabilityInfo &Availability,
895bb5704cSZixu Wang                                           const DocComment &Comment,
905bb5704cSZixu Wang                                           DeclarationFragments Declaration,
915bb5704cSZixu Wang                                           DeclarationFragments SubHeading) {
920ee06c31SDaniel Grumberg   auto Record = std::make_unique<StructFieldRecord>(
930ee06c31SDaniel Grumberg       Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
945bb5704cSZixu Wang   return Struct->Fields.emplace_back(std::move(Record)).get();
955bb5704cSZixu Wang }
965bb5704cSZixu Wang 
975bb5704cSZixu Wang StructRecord *APISet::addStruct(StringRef Name, StringRef USR, PresumedLoc Loc,
985bb5704cSZixu Wang                                 const AvailabilityInfo &Availability,
995bb5704cSZixu Wang                                 const DocComment &Comment,
1005bb5704cSZixu Wang                                 DeclarationFragments Declaration,
1015bb5704cSZixu Wang                                 DeclarationFragments SubHeading) {
1025bb5704cSZixu Wang   auto Result = Structs.insert({Name, nullptr});
1035bb5704cSZixu Wang   if (Result.second) {
1045bb5704cSZixu Wang     // Create the record if it does not already exist.
1050ee06c31SDaniel Grumberg     auto Record = std::make_unique<StructRecord>(
1060ee06c31SDaniel Grumberg         Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
1075bb5704cSZixu Wang     Result.first->second = std::move(Record);
1085bb5704cSZixu Wang   }
1095bb5704cSZixu Wang   return Result.first->second.get();
1105bb5704cSZixu Wang }
1115bb5704cSZixu Wang 
112*9b36e126SZixu Wang ObjCInterfaceRecord *APISet::addObjCInterface(
113*9b36e126SZixu Wang     StringRef Name, StringRef USR, PresumedLoc Loc,
114*9b36e126SZixu Wang     const AvailabilityInfo &Availability, LinkageInfo Linkage,
115*9b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
116*9b36e126SZixu Wang     DeclarationFragments SubHeading, SymbolReference SuperClass) {
117*9b36e126SZixu Wang   auto Result = ObjCInterfaces.insert({Name, nullptr});
118*9b36e126SZixu Wang   if (Result.second) {
119*9b36e126SZixu Wang     // Create the record if it does not already exist.
120*9b36e126SZixu Wang     auto Record = std::make_unique<ObjCInterfaceRecord>(
121*9b36e126SZixu Wang         Name, USR, Loc, Availability, Linkage, Comment, Declaration, SubHeading,
122*9b36e126SZixu Wang         SuperClass);
123*9b36e126SZixu Wang     Result.first->second = std::move(Record);
124*9b36e126SZixu Wang   }
125*9b36e126SZixu Wang   return Result.first->second.get();
126*9b36e126SZixu Wang }
127*9b36e126SZixu Wang 
128*9b36e126SZixu Wang ObjCMethodRecord *APISet::addObjCMethod(
129*9b36e126SZixu Wang     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
130*9b36e126SZixu Wang     PresumedLoc Loc, const AvailabilityInfo &Availability,
131*9b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
132*9b36e126SZixu Wang     DeclarationFragments SubHeading, FunctionSignature Signature,
133*9b36e126SZixu Wang     bool IsInstanceMethod) {
134*9b36e126SZixu Wang   auto Record = std::make_unique<ObjCMethodRecord>(
135*9b36e126SZixu Wang       Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Signature,
136*9b36e126SZixu Wang       IsInstanceMethod);
137*9b36e126SZixu Wang   return Container->Methods.emplace_back(std::move(Record)).get();
138*9b36e126SZixu Wang }
139*9b36e126SZixu Wang 
140*9b36e126SZixu Wang ObjCPropertyRecord *APISet::addObjCProperty(
141*9b36e126SZixu Wang     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
142*9b36e126SZixu Wang     PresumedLoc Loc, const AvailabilityInfo &Availability,
143*9b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
144*9b36e126SZixu Wang     DeclarationFragments SubHeading,
145*9b36e126SZixu Wang     ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName,
146*9b36e126SZixu Wang     StringRef SetterName, bool IsOptional) {
147*9b36e126SZixu Wang   auto Record = std::make_unique<ObjCPropertyRecord>(
148*9b36e126SZixu Wang       Name, USR, Loc, Availability, Comment, Declaration, SubHeading,
149*9b36e126SZixu Wang       Attributes, GetterName, SetterName, IsOptional);
150*9b36e126SZixu Wang   return Container->Properties.emplace_back(std::move(Record)).get();
151*9b36e126SZixu Wang }
152*9b36e126SZixu Wang 
153*9b36e126SZixu Wang ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable(
154*9b36e126SZixu Wang     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
155*9b36e126SZixu Wang     PresumedLoc Loc, const AvailabilityInfo &Availability,
156*9b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
157*9b36e126SZixu Wang     DeclarationFragments SubHeading,
158*9b36e126SZixu Wang     ObjCInstanceVariableRecord::AccessControl Access) {
159*9b36e126SZixu Wang   auto Record = std::make_unique<ObjCInstanceVariableRecord>(
160*9b36e126SZixu Wang       Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Access);
161*9b36e126SZixu Wang   return Container->Ivars.emplace_back(std::move(Record)).get();
162*9b36e126SZixu Wang }
163*9b36e126SZixu Wang 
16489f6b26fSZixu Wang StringRef APISet::recordUSR(const Decl *D) {
16589f6b26fSZixu Wang   SmallString<128> USR;
16689f6b26fSZixu Wang   index::generateUSRForDecl(D, USR);
16789f6b26fSZixu Wang   return copyString(USR);
16889f6b26fSZixu Wang }
16989f6b26fSZixu Wang 
17089f6b26fSZixu Wang StringRef APISet::copyString(StringRef String) {
17189f6b26fSZixu Wang   if (String.empty())
17289f6b26fSZixu Wang     return {};
17389f6b26fSZixu Wang 
17489f6b26fSZixu Wang   // No need to allocate memory and copy if the string has already been stored.
1750ee06c31SDaniel Grumberg   if (StringAllocator.identifyObject(String.data()))
17689f6b26fSZixu Wang     return String;
17789f6b26fSZixu Wang 
1780ee06c31SDaniel Grumberg   void *Ptr = StringAllocator.Allocate(String.size(), 1);
17989f6b26fSZixu Wang   memcpy(Ptr, String.data(), String.size());
18089f6b26fSZixu Wang   return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
18189f6b26fSZixu Wang }
18289f6b26fSZixu Wang 
18389f6b26fSZixu Wang APIRecord::~APIRecord() {}
18489f6b26fSZixu Wang 
185*9b36e126SZixu Wang ObjCContainerRecord::~ObjCContainerRecord() {}
186*9b36e126SZixu Wang 
18789f6b26fSZixu Wang void GlobalRecord::anchor() {}
188e5a7d272SZixu Wang void EnumConstantRecord::anchor() {}
189e5a7d272SZixu Wang void EnumRecord::anchor() {}
190e5a7d272SZixu Wang void StructFieldRecord::anchor() {}
191e5a7d272SZixu Wang void StructRecord::anchor() {}
192*9b36e126SZixu Wang void ObjCPropertyRecord::anchor() {}
193*9b36e126SZixu Wang void ObjCInstanceVariableRecord::anchor() {}
194*9b36e126SZixu Wang void ObjCMethodRecord::anchor() {}
195*9b36e126SZixu Wang void ObjCInterfaceRecord::anchor() {}
196