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 112*178aad9bSZixu Wang ObjCCategoryRecord *APISet::addObjCCategory( 113*178aad9bSZixu Wang StringRef Name, StringRef USR, PresumedLoc Loc, 114*178aad9bSZixu Wang const AvailabilityInfo &Availability, const DocComment &Comment, 115*178aad9bSZixu Wang DeclarationFragments Declaration, DeclarationFragments SubHeading, 116*178aad9bSZixu Wang SymbolReference Interface) { 117*178aad9bSZixu Wang // Create the category record. 118*178aad9bSZixu Wang auto *Record = addTopLevelRecord(ObjCCategories, Name, USR, Loc, Availability, 119*178aad9bSZixu Wang Comment, Declaration, SubHeading, Interface); 120*178aad9bSZixu Wang 121*178aad9bSZixu Wang // If this category is extending a known interface, associate it with the 122*178aad9bSZixu Wang // ObjCInterfaceRecord. 123*178aad9bSZixu Wang auto It = ObjCInterfaces.find(Interface.Name); 124*178aad9bSZixu Wang if (It != ObjCInterfaces.end()) 125*178aad9bSZixu Wang It->second->Categories.push_back(Record); 126*178aad9bSZixu Wang 127*178aad9bSZixu Wang return Record; 128*178aad9bSZixu Wang } 129*178aad9bSZixu Wang 1309b36e126SZixu Wang ObjCInterfaceRecord *APISet::addObjCInterface( 1319b36e126SZixu Wang StringRef Name, StringRef USR, PresumedLoc Loc, 1329b36e126SZixu Wang const AvailabilityInfo &Availability, LinkageInfo Linkage, 1339b36e126SZixu Wang const DocComment &Comment, DeclarationFragments Declaration, 1349b36e126SZixu Wang DeclarationFragments SubHeading, SymbolReference SuperClass) { 135529a0570SDaniel Grumberg return addTopLevelRecord(ObjCInterfaces, Name, USR, Loc, Availability, 136529a0570SDaniel Grumberg Linkage, Comment, Declaration, SubHeading, 1379b36e126SZixu Wang SuperClass); 1389b36e126SZixu Wang } 1399b36e126SZixu Wang 1409b36e126SZixu Wang ObjCMethodRecord *APISet::addObjCMethod( 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, FunctionSignature Signature, 1459b36e126SZixu Wang bool IsInstanceMethod) { 1469b36e126SZixu Wang auto Record = std::make_unique<ObjCMethodRecord>( 1479b36e126SZixu Wang Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Signature, 1489b36e126SZixu Wang IsInstanceMethod); 1499b36e126SZixu Wang return Container->Methods.emplace_back(std::move(Record)).get(); 1509b36e126SZixu Wang } 1519b36e126SZixu Wang 1529b36e126SZixu Wang ObjCPropertyRecord *APISet::addObjCProperty( 1539b36e126SZixu Wang ObjCContainerRecord *Container, StringRef Name, StringRef USR, 1549b36e126SZixu Wang PresumedLoc Loc, const AvailabilityInfo &Availability, 1559b36e126SZixu Wang const DocComment &Comment, DeclarationFragments Declaration, 1569b36e126SZixu Wang DeclarationFragments SubHeading, 1579b36e126SZixu Wang ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName, 1589b36e126SZixu Wang StringRef SetterName, bool IsOptional) { 1599b36e126SZixu Wang auto Record = std::make_unique<ObjCPropertyRecord>( 1609b36e126SZixu Wang Name, USR, Loc, Availability, Comment, Declaration, SubHeading, 1619b36e126SZixu Wang Attributes, GetterName, SetterName, IsOptional); 1629b36e126SZixu Wang return Container->Properties.emplace_back(std::move(Record)).get(); 1639b36e126SZixu Wang } 1649b36e126SZixu Wang 1659b36e126SZixu Wang ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable( 1669b36e126SZixu Wang ObjCContainerRecord *Container, StringRef Name, StringRef USR, 1679b36e126SZixu Wang PresumedLoc Loc, const AvailabilityInfo &Availability, 1689b36e126SZixu Wang const DocComment &Comment, DeclarationFragments Declaration, 1699b36e126SZixu Wang DeclarationFragments SubHeading, 1709b36e126SZixu Wang ObjCInstanceVariableRecord::AccessControl Access) { 1719b36e126SZixu Wang auto Record = std::make_unique<ObjCInstanceVariableRecord>( 1729b36e126SZixu Wang Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Access); 1739b36e126SZixu Wang return Container->Ivars.emplace_back(std::move(Record)).get(); 1749b36e126SZixu Wang } 1759b36e126SZixu Wang 176d1d34bafSZixu Wang ObjCProtocolRecord *APISet::addObjCProtocol( 177d1d34bafSZixu Wang StringRef Name, StringRef USR, PresumedLoc Loc, 178d1d34bafSZixu Wang const AvailabilityInfo &Availability, const DocComment &Comment, 179d1d34bafSZixu Wang DeclarationFragments Declaration, DeclarationFragments SubHeading) { 180529a0570SDaniel Grumberg return addTopLevelRecord(ObjCProtocols, Name, USR, Loc, Availability, Comment, 181529a0570SDaniel Grumberg Declaration, SubHeading); 182d1d34bafSZixu Wang } 183529a0570SDaniel Grumberg 184529a0570SDaniel Grumberg MacroDefinitionRecord * 185529a0570SDaniel Grumberg APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc, 186529a0570SDaniel Grumberg DeclarationFragments Declaration, 187529a0570SDaniel Grumberg DeclarationFragments SubHeading) { 188529a0570SDaniel Grumberg return addTopLevelRecord(Macros, Name, USR, Loc, Declaration, SubHeading); 189d1d34bafSZixu Wang } 190d1d34bafSZixu Wang 1919fc45ca0SDaniel Grumberg TypedefRecord *APISet::addTypedef(StringRef Name, StringRef USR, 1929fc45ca0SDaniel Grumberg PresumedLoc Loc, 1939fc45ca0SDaniel Grumberg const AvailabilityInfo &Availability, 1949fc45ca0SDaniel Grumberg const DocComment &Comment, 1959fc45ca0SDaniel Grumberg DeclarationFragments Declaration, 1969fc45ca0SDaniel Grumberg DeclarationFragments SubHeading, 1979fc45ca0SDaniel Grumberg SymbolReference UnderlyingType) { 1989fc45ca0SDaniel Grumberg return addTopLevelRecord(Typedefs, Name, USR, Loc, Availability, Comment, 1999fc45ca0SDaniel Grumberg Declaration, SubHeading, UnderlyingType); 2009fc45ca0SDaniel Grumberg } 2019fc45ca0SDaniel Grumberg 20289f6b26fSZixu Wang StringRef APISet::recordUSR(const Decl *D) { 20389f6b26fSZixu Wang SmallString<128> USR; 20489f6b26fSZixu Wang index::generateUSRForDecl(D, USR); 20589f6b26fSZixu Wang return copyString(USR); 20689f6b26fSZixu Wang } 20789f6b26fSZixu Wang 208529a0570SDaniel Grumberg StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL, 209529a0570SDaniel Grumberg const SourceManager &SM) { 210529a0570SDaniel Grumberg SmallString<128> USR; 211529a0570SDaniel Grumberg index::generateUSRForMacro(Name, SL, SM, USR); 212529a0570SDaniel Grumberg return copyString(USR); 213529a0570SDaniel Grumberg } 214529a0570SDaniel Grumberg 21589f6b26fSZixu Wang StringRef APISet::copyString(StringRef String) { 21689f6b26fSZixu Wang if (String.empty()) 21789f6b26fSZixu Wang return {}; 21889f6b26fSZixu Wang 21989f6b26fSZixu Wang // No need to allocate memory and copy if the string has already been stored. 2200ee06c31SDaniel Grumberg if (StringAllocator.identifyObject(String.data())) 22189f6b26fSZixu Wang return String; 22289f6b26fSZixu Wang 2230ee06c31SDaniel Grumberg void *Ptr = StringAllocator.Allocate(String.size(), 1); 22489f6b26fSZixu Wang memcpy(Ptr, String.data(), String.size()); 22589f6b26fSZixu Wang return StringRef(reinterpret_cast<const char *>(Ptr), String.size()); 22689f6b26fSZixu Wang } 22789f6b26fSZixu Wang 22889f6b26fSZixu Wang APIRecord::~APIRecord() {} 22989f6b26fSZixu Wang 2309b36e126SZixu Wang ObjCContainerRecord::~ObjCContainerRecord() {} 2319b36e126SZixu Wang 23289f6b26fSZixu Wang void GlobalRecord::anchor() {} 233e5a7d272SZixu Wang void EnumConstantRecord::anchor() {} 234e5a7d272SZixu Wang void EnumRecord::anchor() {} 235e5a7d272SZixu Wang void StructFieldRecord::anchor() {} 236e5a7d272SZixu Wang void StructRecord::anchor() {} 2379b36e126SZixu Wang void ObjCPropertyRecord::anchor() {} 2389b36e126SZixu Wang void ObjCInstanceVariableRecord::anchor() {} 2399b36e126SZixu Wang void ObjCMethodRecord::anchor() {} 240*178aad9bSZixu Wang void ObjCCategoryRecord::anchor() {} 2419b36e126SZixu Wang void ObjCInterfaceRecord::anchor() {} 242d1d34bafSZixu Wang void ObjCProtocolRecord::anchor() {} 243529a0570SDaniel Grumberg void MacroDefinitionRecord::anchor() {} 2449fc45ca0SDaniel Grumberg void TypedefRecord::anchor() {} 245