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 "llvm/ADT/STLFunctionalExtras.h" 21 #include "llvm/ADT/StringRef.h" 22 #include <memory> 23 24 using namespace clang::extractapi; 25 using namespace llvm; 26 27 namespace { 28 29 template <typename RecordTy, typename... CtorArgsTy> 30 RecordTy *addTopLevelRecord(APISet::RecordMap<RecordTy> &RecordMap, 31 StringRef USR, CtorArgsTy &&...CtorArgs) { 32 auto Result = RecordMap.insert({USR, nullptr}); 33 34 // Create the record if it does not already exist 35 if (Result.second) 36 Result.first->second = 37 std::make_unique<RecordTy>(USR, std::forward<CtorArgsTy>(CtorArgs)...); 38 39 return Result.first->second.get(); 40 } 41 42 } // namespace 43 44 GlobalVariableRecord * 45 APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc, 46 AvailabilitySet Availabilities, LinkageInfo Linkage, 47 const DocComment &Comment, DeclarationFragments Fragments, 48 DeclarationFragments SubHeading) { 49 return addTopLevelRecord(GlobalVariables, USR, Name, Loc, 50 std::move(Availabilities), Linkage, Comment, 51 Fragments, SubHeading); 52 } 53 54 GlobalFunctionRecord *APISet::addGlobalFunction( 55 StringRef Name, StringRef USR, PresumedLoc Loc, 56 AvailabilitySet Availabilities, LinkageInfo Linkage, 57 const DocComment &Comment, DeclarationFragments Fragments, 58 DeclarationFragments SubHeading, FunctionSignature Signature) { 59 return addTopLevelRecord(GlobalFunctions, USR, Name, Loc, 60 std::move(Availabilities), Linkage, Comment, 61 Fragments, SubHeading, Signature); 62 } 63 64 EnumConstantRecord *APISet::addEnumConstant(EnumRecord *Enum, StringRef Name, 65 StringRef USR, PresumedLoc Loc, 66 AvailabilitySet Availabilities, 67 const DocComment &Comment, 68 DeclarationFragments Declaration, 69 DeclarationFragments SubHeading) { 70 auto Record = std::make_unique<EnumConstantRecord>( 71 USR, Name, Loc, std::move(Availabilities), Comment, Declaration, 72 SubHeading); 73 return Enum->Constants.emplace_back(std::move(Record)).get(); 74 } 75 76 EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc, 77 AvailabilitySet Availabilities, 78 const DocComment &Comment, 79 DeclarationFragments Declaration, 80 DeclarationFragments SubHeading) { 81 return addTopLevelRecord(Enums, USR, Name, Loc, std::move(Availabilities), 82 Comment, Declaration, SubHeading); 83 } 84 85 StructFieldRecord *APISet::addStructField(StructRecord *Struct, StringRef Name, 86 StringRef USR, PresumedLoc Loc, 87 AvailabilitySet Availabilities, 88 const DocComment &Comment, 89 DeclarationFragments Declaration, 90 DeclarationFragments SubHeading) { 91 auto Record = std::make_unique<StructFieldRecord>( 92 USR, Name, Loc, std::move(Availabilities), Comment, Declaration, 93 SubHeading); 94 return Struct->Fields.emplace_back(std::move(Record)).get(); 95 } 96 97 StructRecord *APISet::addStruct(StringRef Name, StringRef USR, PresumedLoc Loc, 98 AvailabilitySet Availabilities, 99 const DocComment &Comment, 100 DeclarationFragments Declaration, 101 DeclarationFragments SubHeading) { 102 return addTopLevelRecord(Structs, USR, Name, Loc, std::move(Availabilities), 103 Comment, Declaration, SubHeading); 104 } 105 106 ObjCCategoryRecord *APISet::addObjCCategory(StringRef Name, StringRef USR, 107 PresumedLoc Loc, 108 AvailabilitySet Availabilities, 109 const DocComment &Comment, 110 DeclarationFragments Declaration, 111 DeclarationFragments SubHeading, 112 SymbolReference Interface) { 113 // Create the category record. 114 auto *Record = addTopLevelRecord(ObjCCategories, USR, Name, Loc, 115 std::move(Availabilities), Comment, 116 Declaration, SubHeading, Interface); 117 118 // If this category is extending a known interface, associate it with the 119 // ObjCInterfaceRecord. 120 auto It = ObjCInterfaces.find(Interface.USR); 121 if (It != ObjCInterfaces.end()) 122 It->second->Categories.push_back(Record); 123 124 return Record; 125 } 126 127 ObjCInterfaceRecord *APISet::addObjCInterface( 128 StringRef Name, StringRef USR, PresumedLoc Loc, 129 AvailabilitySet Availabilities, LinkageInfo Linkage, 130 const DocComment &Comment, DeclarationFragments Declaration, 131 DeclarationFragments SubHeading, SymbolReference SuperClass) { 132 return addTopLevelRecord(ObjCInterfaces, USR, Name, Loc, 133 std::move(Availabilities), Linkage, Comment, 134 Declaration, SubHeading, SuperClass); 135 } 136 137 ObjCMethodRecord *APISet::addObjCMethod( 138 ObjCContainerRecord *Container, StringRef Name, StringRef USR, 139 PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, 140 DeclarationFragments Declaration, DeclarationFragments SubHeading, 141 FunctionSignature Signature, bool IsInstanceMethod) { 142 auto Record = std::make_unique<ObjCMethodRecord>( 143 USR, Name, Loc, std::move(Availabilities), Comment, Declaration, 144 SubHeading, Signature, IsInstanceMethod); 145 return Container->Methods.emplace_back(std::move(Record)).get(); 146 } 147 148 ObjCPropertyRecord *APISet::addObjCProperty( 149 ObjCContainerRecord *Container, StringRef Name, StringRef USR, 150 PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, 151 DeclarationFragments Declaration, DeclarationFragments SubHeading, 152 ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName, 153 StringRef SetterName, bool IsOptional) { 154 auto Record = std::make_unique<ObjCPropertyRecord>( 155 USR, Name, Loc, std::move(Availabilities), Comment, Declaration, 156 SubHeading, Attributes, GetterName, SetterName, IsOptional); 157 return Container->Properties.emplace_back(std::move(Record)).get(); 158 } 159 160 ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable( 161 ObjCContainerRecord *Container, StringRef Name, StringRef USR, 162 PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, 163 DeclarationFragments Declaration, DeclarationFragments SubHeading, 164 ObjCInstanceVariableRecord::AccessControl Access) { 165 auto Record = std::make_unique<ObjCInstanceVariableRecord>( 166 USR, Name, Loc, std::move(Availabilities), Comment, Declaration, 167 SubHeading, Access); 168 return Container->Ivars.emplace_back(std::move(Record)).get(); 169 } 170 171 ObjCProtocolRecord *APISet::addObjCProtocol(StringRef Name, StringRef USR, 172 PresumedLoc Loc, 173 AvailabilitySet Availabilities, 174 const DocComment &Comment, 175 DeclarationFragments Declaration, 176 DeclarationFragments SubHeading) { 177 return addTopLevelRecord(ObjCProtocols, USR, Name, Loc, 178 std::move(Availabilities), Comment, Declaration, 179 SubHeading); 180 } 181 182 MacroDefinitionRecord * 183 APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc, 184 DeclarationFragments Declaration, 185 DeclarationFragments SubHeading) { 186 return addTopLevelRecord(Macros, USR, Name, Loc, Declaration, SubHeading); 187 } 188 189 TypedefRecord *APISet::addTypedef(StringRef Name, StringRef USR, 190 PresumedLoc Loc, 191 AvailabilitySet Availabilities, 192 const DocComment &Comment, 193 DeclarationFragments Declaration, 194 DeclarationFragments SubHeading, 195 SymbolReference UnderlyingType) { 196 return addTopLevelRecord(Typedefs, USR, Name, Loc, std::move(Availabilities), 197 Comment, Declaration, SubHeading, UnderlyingType); 198 } 199 200 template <class RecordMap> 201 static APIRecord *getSymbolInRecordMapForUSR(StringRef USR, 202 const RecordMap &Records) { 203 auto It = Records.find(USR); 204 return (It != Records.end() ? It->second.get() : nullptr); 205 } 206 207 APIRecord *APISet::getSymbolForUSR(StringRef USR) const { 208 if (USR.empty()) 209 return nullptr; 210 if (auto *Record = getSymbolInRecordMapForUSR(USR, ObjCProtocols)) 211 return Record; 212 if (auto *Record = getSymbolInRecordMapForUSR(USR, ObjCInterfaces)) 213 return Record; 214 if (auto *Record = getSymbolInRecordMapForUSR(USR, ObjCCategories)) 215 return Record; 216 if (auto *Record = getSymbolInRecordMapForUSR(USR, ObjCCategories)) 217 return Record; 218 if (auto *Record = getSymbolInRecordMapForUSR(USR, Structs)) 219 return Record; 220 if (auto *Record = getSymbolInRecordMapForUSR(USR, Enums)) 221 return Record; 222 if (auto *Record = getSymbolInRecordMapForUSR(USR, Typedefs)) 223 return Record; 224 if (auto *Record = getSymbolInRecordMapForUSR(USR, GlobalFunctions)) 225 return Record; 226 if (auto *Record = getSymbolInRecordMapForUSR(USR, GlobalVariables)) 227 return Record; 228 if (auto *Record = getSymbolInRecordMapForUSR(USR, Macros)) 229 return Record; 230 return nullptr; 231 } 232 233 StringRef APISet::recordUSR(const Decl *D) { 234 SmallString<128> USR; 235 index::generateUSRForDecl(D, USR); 236 return copyString(USR); 237 } 238 239 StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL, 240 const SourceManager &SM) { 241 SmallString<128> USR; 242 index::generateUSRForMacro(Name, SL, SM, USR); 243 return copyString(USR); 244 } 245 246 StringRef APISet::copyString(StringRef String) { 247 if (String.empty()) 248 return {}; 249 250 // No need to allocate memory and copy if the string has already been stored. 251 if (StringAllocator.identifyObject(String.data())) 252 return String; 253 254 void *Ptr = StringAllocator.Allocate(String.size(), 1); 255 memcpy(Ptr, String.data(), String.size()); 256 return StringRef(reinterpret_cast<const char *>(Ptr), String.size()); 257 } 258 259 APIRecord::~APIRecord() {} 260 261 ObjCContainerRecord::~ObjCContainerRecord() {} 262 263 void GlobalFunctionRecord::anchor() {} 264 void GlobalVariableRecord::anchor() {} 265 void EnumConstantRecord::anchor() {} 266 void EnumRecord::anchor() {} 267 void StructFieldRecord::anchor() {} 268 void StructRecord::anchor() {} 269 void ObjCPropertyRecord::anchor() {} 270 void ObjCInstanceVariableRecord::anchor() {} 271 void ObjCMethodRecord::anchor() {} 272 void ObjCCategoryRecord::anchor() {} 273 void ObjCInterfaceRecord::anchor() {} 274 void ObjCProtocolRecord::anchor() {} 275 void MacroDefinitionRecord::anchor() {} 276 void TypedefRecord::anchor() {} 277