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>
addTopLevelRecord(APISet::RecordMap<RecordTy> & RecordMap,StringRef USR,CtorArgsTy &&...CtorArgs)30529a0570SDaniel Grumberg RecordTy *addTopLevelRecord(APISet::RecordMap<RecordTy> &RecordMap,
31*7443a504SDaniel Grumberg                             StringRef USR, CtorArgsTy &&...CtorArgs) {
32*7443a504SDaniel Grumberg   auto Result = RecordMap.insert({USR, nullptr});
33529a0570SDaniel Grumberg 
34529a0570SDaniel Grumberg   // Create the record if it does not already exist
35529a0570SDaniel Grumberg   if (Result.second)
36529a0570SDaniel Grumberg     Result.first->second =
37*7443a504SDaniel Grumberg         std::make_unique<RecordTy>(USR, std::forward<CtorArgsTy>(CtorArgs)...);
38529a0570SDaniel Grumberg 
39529a0570SDaniel Grumberg   return Result.first->second.get();
40529a0570SDaniel Grumberg }
41529a0570SDaniel Grumberg 
42529a0570SDaniel Grumberg } // namespace
43529a0570SDaniel Grumberg 
44236b6a0eSDaniel Grumberg GlobalVariableRecord *
addGlobalVar(StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,LinkageInfo Linkage,const DocComment & Comment,DeclarationFragments Fragments,DeclarationFragments SubHeading)4589f6b26fSZixu Wang APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
4689f6b26fSZixu Wang                      const AvailabilityInfo &Availability, LinkageInfo Linkage,
4789f6b26fSZixu Wang                      const DocComment &Comment, DeclarationFragments Fragments,
4889f6b26fSZixu Wang                      DeclarationFragments SubHeading) {
49*7443a504SDaniel Grumberg   return addTopLevelRecord(GlobalVariables, USR, Name, Loc, Availability,
50236b6a0eSDaniel Grumberg                            Linkage, Comment, Fragments, SubHeading);
5189f6b26fSZixu Wang }
5289f6b26fSZixu Wang 
addGlobalFunction(StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,LinkageInfo Linkage,const DocComment & Comment,DeclarationFragments Fragments,DeclarationFragments SubHeading,FunctionSignature Signature)53236b6a0eSDaniel Grumberg GlobalFunctionRecord *APISet::addGlobalFunction(
54236b6a0eSDaniel Grumberg     StringRef Name, StringRef USR, PresumedLoc Loc,
5589f6b26fSZixu Wang     const AvailabilityInfo &Availability, LinkageInfo Linkage,
5689f6b26fSZixu Wang     const DocComment &Comment, DeclarationFragments Fragments,
57236b6a0eSDaniel Grumberg     DeclarationFragments SubHeading, FunctionSignature Signature) {
58*7443a504SDaniel Grumberg   return addTopLevelRecord(GlobalFunctions, USR, Name, Loc, Availability,
59236b6a0eSDaniel Grumberg                            Linkage, Comment, Fragments, SubHeading, Signature);
6089f6b26fSZixu Wang }
6189f6b26fSZixu Wang 
addEnumConstant(EnumRecord * Enum,StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,const DocComment & Comment,DeclarationFragments Declaration,DeclarationFragments SubHeading)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>(
67*7443a504SDaniel Grumberg       USR, Name, Loc, Availability, Comment, Declaration, SubHeading);
6871b4c226SZixu Wang   return Enum->Constants.emplace_back(std::move(Record)).get();
6971b4c226SZixu Wang }
7071b4c226SZixu Wang 
addEnum(StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,const DocComment & Comment,DeclarationFragments Declaration,DeclarationFragments SubHeading)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) {
76*7443a504SDaniel Grumberg   return addTopLevelRecord(Enums, USR, Name, Loc, Availability, Comment,
77529a0570SDaniel Grumberg                            Declaration, SubHeading);
7871b4c226SZixu Wang }
7971b4c226SZixu Wang 
addStructField(StructRecord * Struct,StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,const DocComment & Comment,DeclarationFragments Declaration,DeclarationFragments SubHeading)805bb5704cSZixu Wang StructFieldRecord *APISet::addStructField(StructRecord *Struct, StringRef Name,
815bb5704cSZixu Wang                                           StringRef USR, PresumedLoc Loc,
825bb5704cSZixu Wang                                           const AvailabilityInfo &Availability,
835bb5704cSZixu Wang                                           const DocComment &Comment,
845bb5704cSZixu Wang                                           DeclarationFragments Declaration,
855bb5704cSZixu Wang                                           DeclarationFragments SubHeading) {
860ee06c31SDaniel Grumberg   auto Record = std::make_unique<StructFieldRecord>(
87*7443a504SDaniel Grumberg       USR, Name, Loc, Availability, Comment, Declaration, SubHeading);
885bb5704cSZixu Wang   return Struct->Fields.emplace_back(std::move(Record)).get();
895bb5704cSZixu Wang }
905bb5704cSZixu Wang 
addStruct(StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,const DocComment & Comment,DeclarationFragments Declaration,DeclarationFragments SubHeading)915bb5704cSZixu Wang StructRecord *APISet::addStruct(StringRef Name, StringRef USR, PresumedLoc Loc,
925bb5704cSZixu Wang                                 const AvailabilityInfo &Availability,
935bb5704cSZixu Wang                                 const DocComment &Comment,
945bb5704cSZixu Wang                                 DeclarationFragments Declaration,
955bb5704cSZixu Wang                                 DeclarationFragments SubHeading) {
96*7443a504SDaniel Grumberg   return addTopLevelRecord(Structs, USR, Name, Loc, Availability, Comment,
97529a0570SDaniel Grumberg                            Declaration, SubHeading);
985bb5704cSZixu Wang }
995bb5704cSZixu Wang 
addObjCCategory(StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,const DocComment & Comment,DeclarationFragments Declaration,DeclarationFragments SubHeading,SymbolReference Interface)100178aad9bSZixu Wang ObjCCategoryRecord *APISet::addObjCCategory(
101178aad9bSZixu Wang     StringRef Name, StringRef USR, PresumedLoc Loc,
102178aad9bSZixu Wang     const AvailabilityInfo &Availability, const DocComment &Comment,
103178aad9bSZixu Wang     DeclarationFragments Declaration, DeclarationFragments SubHeading,
104178aad9bSZixu Wang     SymbolReference Interface) {
105178aad9bSZixu Wang   // Create the category record.
106*7443a504SDaniel Grumberg   auto *Record = addTopLevelRecord(ObjCCategories, USR, Name, Loc, Availability,
107178aad9bSZixu Wang                                    Comment, Declaration, SubHeading, Interface);
108178aad9bSZixu Wang 
109178aad9bSZixu Wang   // If this category is extending a known interface, associate it with the
110178aad9bSZixu Wang   // ObjCInterfaceRecord.
111*7443a504SDaniel Grumberg   auto It = ObjCInterfaces.find(Interface.USR);
112178aad9bSZixu Wang   if (It != ObjCInterfaces.end())
113178aad9bSZixu Wang     It->second->Categories.push_back(Record);
114178aad9bSZixu Wang 
115178aad9bSZixu Wang   return Record;
116178aad9bSZixu Wang }
117178aad9bSZixu Wang 
addObjCInterface(StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,LinkageInfo Linkage,const DocComment & Comment,DeclarationFragments Declaration,DeclarationFragments SubHeading,SymbolReference SuperClass)1189b36e126SZixu Wang ObjCInterfaceRecord *APISet::addObjCInterface(
1199b36e126SZixu Wang     StringRef Name, StringRef USR, PresumedLoc Loc,
1209b36e126SZixu Wang     const AvailabilityInfo &Availability, LinkageInfo Linkage,
1219b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
1229b36e126SZixu Wang     DeclarationFragments SubHeading, SymbolReference SuperClass) {
123*7443a504SDaniel Grumberg   return addTopLevelRecord(ObjCInterfaces, USR, Name, Loc, Availability,
124529a0570SDaniel Grumberg                            Linkage, Comment, Declaration, SubHeading,
1259b36e126SZixu Wang                            SuperClass);
1269b36e126SZixu Wang }
1279b36e126SZixu Wang 
addObjCMethod(ObjCContainerRecord * Container,StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,const DocComment & Comment,DeclarationFragments Declaration,DeclarationFragments SubHeading,FunctionSignature Signature,bool IsInstanceMethod)1289b36e126SZixu Wang ObjCMethodRecord *APISet::addObjCMethod(
1299b36e126SZixu Wang     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
1309b36e126SZixu Wang     PresumedLoc Loc, const AvailabilityInfo &Availability,
1319b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
1329b36e126SZixu Wang     DeclarationFragments SubHeading, FunctionSignature Signature,
1339b36e126SZixu Wang     bool IsInstanceMethod) {
1349b36e126SZixu Wang   auto Record = std::make_unique<ObjCMethodRecord>(
135*7443a504SDaniel Grumberg       USR, Name, Loc, Availability, Comment, Declaration, SubHeading, Signature,
1369b36e126SZixu Wang       IsInstanceMethod);
1379b36e126SZixu Wang   return Container->Methods.emplace_back(std::move(Record)).get();
1389b36e126SZixu Wang }
1399b36e126SZixu Wang 
addObjCProperty(ObjCContainerRecord * Container,StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,const DocComment & Comment,DeclarationFragments Declaration,DeclarationFragments SubHeading,ObjCPropertyRecord::AttributeKind Attributes,StringRef GetterName,StringRef SetterName,bool IsOptional)1409b36e126SZixu Wang ObjCPropertyRecord *APISet::addObjCProperty(
1419b36e126SZixu Wang     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
1429b36e126SZixu Wang     PresumedLoc Loc, const AvailabilityInfo &Availability,
1439b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
1449b36e126SZixu Wang     DeclarationFragments SubHeading,
1459b36e126SZixu Wang     ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName,
1469b36e126SZixu Wang     StringRef SetterName, bool IsOptional) {
1479b36e126SZixu Wang   auto Record = std::make_unique<ObjCPropertyRecord>(
148*7443a504SDaniel Grumberg       USR, Name, Loc, Availability, Comment, Declaration, SubHeading,
1499b36e126SZixu Wang       Attributes, GetterName, SetterName, IsOptional);
1509b36e126SZixu Wang   return Container->Properties.emplace_back(std::move(Record)).get();
1519b36e126SZixu Wang }
1529b36e126SZixu Wang 
addObjCInstanceVariable(ObjCContainerRecord * Container,StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,const DocComment & Comment,DeclarationFragments Declaration,DeclarationFragments SubHeading,ObjCInstanceVariableRecord::AccessControl Access)1539b36e126SZixu Wang ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable(
1549b36e126SZixu Wang     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
1559b36e126SZixu Wang     PresumedLoc Loc, const AvailabilityInfo &Availability,
1569b36e126SZixu Wang     const DocComment &Comment, DeclarationFragments Declaration,
1579b36e126SZixu Wang     DeclarationFragments SubHeading,
1589b36e126SZixu Wang     ObjCInstanceVariableRecord::AccessControl Access) {
1599b36e126SZixu Wang   auto Record = std::make_unique<ObjCInstanceVariableRecord>(
160*7443a504SDaniel Grumberg       USR, Name, Loc, Availability, Comment, Declaration, SubHeading, Access);
1619b36e126SZixu Wang   return Container->Ivars.emplace_back(std::move(Record)).get();
1629b36e126SZixu Wang }
1639b36e126SZixu Wang 
addObjCProtocol(StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,const DocComment & Comment,DeclarationFragments Declaration,DeclarationFragments SubHeading)164d1d34bafSZixu Wang ObjCProtocolRecord *APISet::addObjCProtocol(
165d1d34bafSZixu Wang     StringRef Name, StringRef USR, PresumedLoc Loc,
166d1d34bafSZixu Wang     const AvailabilityInfo &Availability, const DocComment &Comment,
167d1d34bafSZixu Wang     DeclarationFragments Declaration, DeclarationFragments SubHeading) {
168*7443a504SDaniel Grumberg   return addTopLevelRecord(ObjCProtocols, USR, Name, Loc, Availability, Comment,
169529a0570SDaniel Grumberg                            Declaration, SubHeading);
170d1d34bafSZixu Wang }
171529a0570SDaniel Grumberg 
172529a0570SDaniel Grumberg MacroDefinitionRecord *
addMacroDefinition(StringRef Name,StringRef USR,PresumedLoc Loc,DeclarationFragments Declaration,DeclarationFragments SubHeading)173529a0570SDaniel Grumberg APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc,
174529a0570SDaniel Grumberg                            DeclarationFragments Declaration,
175529a0570SDaniel Grumberg                            DeclarationFragments SubHeading) {
176*7443a504SDaniel Grumberg   return addTopLevelRecord(Macros, USR, Name, Loc, Declaration, SubHeading);
177d1d34bafSZixu Wang }
178d1d34bafSZixu Wang 
addTypedef(StringRef Name,StringRef USR,PresumedLoc Loc,const AvailabilityInfo & Availability,const DocComment & Comment,DeclarationFragments Declaration,DeclarationFragments SubHeading,SymbolReference UnderlyingType)1799fc45ca0SDaniel Grumberg TypedefRecord *APISet::addTypedef(StringRef Name, StringRef USR,
1809fc45ca0SDaniel Grumberg                                   PresumedLoc Loc,
1819fc45ca0SDaniel Grumberg                                   const AvailabilityInfo &Availability,
1829fc45ca0SDaniel Grumberg                                   const DocComment &Comment,
1839fc45ca0SDaniel Grumberg                                   DeclarationFragments Declaration,
1849fc45ca0SDaniel Grumberg                                   DeclarationFragments SubHeading,
1859fc45ca0SDaniel Grumberg                                   SymbolReference UnderlyingType) {
186*7443a504SDaniel Grumberg   return addTopLevelRecord(Typedefs, USR, Name, Loc, Availability, Comment,
1879fc45ca0SDaniel Grumberg                            Declaration, SubHeading, UnderlyingType);
1889fc45ca0SDaniel Grumberg }
1899fc45ca0SDaniel Grumberg 
recordUSR(const Decl * D)19089f6b26fSZixu Wang StringRef APISet::recordUSR(const Decl *D) {
19189f6b26fSZixu Wang   SmallString<128> USR;
19289f6b26fSZixu Wang   index::generateUSRForDecl(D, USR);
19389f6b26fSZixu Wang   return copyString(USR);
19489f6b26fSZixu Wang }
19589f6b26fSZixu Wang 
recordUSRForMacro(StringRef Name,SourceLocation SL,const SourceManager & SM)196529a0570SDaniel Grumberg StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL,
197529a0570SDaniel Grumberg                                     const SourceManager &SM) {
198529a0570SDaniel Grumberg   SmallString<128> USR;
199529a0570SDaniel Grumberg   index::generateUSRForMacro(Name, SL, SM, USR);
200529a0570SDaniel Grumberg   return copyString(USR);
201529a0570SDaniel Grumberg }
202529a0570SDaniel Grumberg 
copyString(StringRef String)20389f6b26fSZixu Wang StringRef APISet::copyString(StringRef String) {
20489f6b26fSZixu Wang   if (String.empty())
20589f6b26fSZixu Wang     return {};
20689f6b26fSZixu Wang 
20789f6b26fSZixu Wang   // No need to allocate memory and copy if the string has already been stored.
2080ee06c31SDaniel Grumberg   if (StringAllocator.identifyObject(String.data()))
20989f6b26fSZixu Wang     return String;
21089f6b26fSZixu Wang 
2110ee06c31SDaniel Grumberg   void *Ptr = StringAllocator.Allocate(String.size(), 1);
21289f6b26fSZixu Wang   memcpy(Ptr, String.data(), String.size());
21389f6b26fSZixu Wang   return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
21489f6b26fSZixu Wang }
21589f6b26fSZixu Wang 
~APIRecord()21689f6b26fSZixu Wang APIRecord::~APIRecord() {}
21789f6b26fSZixu Wang 
~ObjCContainerRecord()2189b36e126SZixu Wang ObjCContainerRecord::~ObjCContainerRecord() {}
2199b36e126SZixu Wang 
anchor()220236b6a0eSDaniel Grumberg void GlobalFunctionRecord::anchor() {}
anchor()221236b6a0eSDaniel Grumberg void GlobalVariableRecord::anchor() {}
anchor()222e5a7d272SZixu Wang void EnumConstantRecord::anchor() {}
anchor()223e5a7d272SZixu Wang void EnumRecord::anchor() {}
anchor()224e5a7d272SZixu Wang void StructFieldRecord::anchor() {}
anchor()225e5a7d272SZixu Wang void StructRecord::anchor() {}
anchor()2269b36e126SZixu Wang void ObjCPropertyRecord::anchor() {}
anchor()2279b36e126SZixu Wang void ObjCInstanceVariableRecord::anchor() {}
anchor()2289b36e126SZixu Wang void ObjCMethodRecord::anchor() {}
anchor()229178aad9bSZixu Wang void ObjCCategoryRecord::anchor() {}
anchor()2309b36e126SZixu Wang void ObjCInterfaceRecord::anchor() {}
anchor()231d1d34bafSZixu Wang void ObjCProtocolRecord::anchor() {}
anchor()232529a0570SDaniel Grumberg void MacroDefinitionRecord::anchor() {}
anchor()2339fc45ca0SDaniel Grumberg void TypedefRecord::anchor() {}
234