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 <memory> 21 22 using namespace clang::extractapi; 23 using namespace llvm; 24 25 GlobalRecord *APISet::addGlobal(GVKind Kind, StringRef Name, StringRef USR, 26 PresumedLoc Loc, 27 const AvailabilityInfo &Availability, 28 LinkageInfo Linkage, const DocComment &Comment, 29 DeclarationFragments Fragments, 30 DeclarationFragments SubHeading, 31 FunctionSignature Signature) { 32 auto Result = Globals.insert({Name, nullptr}); 33 if (Result.second) { 34 // Create the record if it does not already exist. 35 auto Record = std::make_unique<GlobalRecord>( 36 Kind, Name, USR, Loc, Availability, Linkage, Comment, Fragments, 37 SubHeading, Signature); 38 Result.first->second = std::move(Record); 39 } 40 return Result.first->second.get(); 41 } 42 43 GlobalRecord * 44 APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc, 45 const AvailabilityInfo &Availability, LinkageInfo Linkage, 46 const DocComment &Comment, DeclarationFragments Fragments, 47 DeclarationFragments SubHeading) { 48 return addGlobal(GVKind::Variable, Name, USR, Loc, Availability, Linkage, 49 Comment, Fragments, SubHeading, {}); 50 } 51 52 GlobalRecord * 53 APISet::addFunction(StringRef Name, StringRef USR, PresumedLoc Loc, 54 const AvailabilityInfo &Availability, LinkageInfo Linkage, 55 const DocComment &Comment, DeclarationFragments Fragments, 56 DeclarationFragments SubHeading, 57 FunctionSignature Signature) { 58 return addGlobal(GVKind::Function, Name, USR, Loc, Availability, Linkage, 59 Comment, Fragments, SubHeading, Signature); 60 } 61 62 EnumConstantRecord *APISet::addEnumConstant( 63 EnumRecord *Enum, StringRef Name, StringRef USR, PresumedLoc Loc, 64 const AvailabilityInfo &Availability, const DocComment &Comment, 65 DeclarationFragments Declaration, DeclarationFragments SubHeading) { 66 auto Record = std::make_unique<EnumConstantRecord>( 67 Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 68 return Enum->Constants.emplace_back(std::move(Record)).get(); 69 } 70 71 EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc, 72 const AvailabilityInfo &Availability, 73 const DocComment &Comment, 74 DeclarationFragments Declaration, 75 DeclarationFragments SubHeading) { 76 auto Result = Enums.insert({Name, nullptr}); 77 if (Result.second) { 78 // Create the record if it does not already exist. 79 auto Record = std::make_unique<EnumRecord>( 80 Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 81 Result.first->second = std::move(Record); 82 } 83 return Result.first->second.get(); 84 } 85 86 StructFieldRecord *APISet::addStructField(StructRecord *Struct, StringRef Name, 87 StringRef USR, PresumedLoc Loc, 88 const AvailabilityInfo &Availability, 89 const DocComment &Comment, 90 DeclarationFragments Declaration, 91 DeclarationFragments SubHeading) { 92 auto Record = std::make_unique<StructFieldRecord>( 93 Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 94 return Struct->Fields.emplace_back(std::move(Record)).get(); 95 } 96 97 StructRecord *APISet::addStruct(StringRef Name, StringRef USR, PresumedLoc Loc, 98 const AvailabilityInfo &Availability, 99 const DocComment &Comment, 100 DeclarationFragments Declaration, 101 DeclarationFragments SubHeading) { 102 auto Result = Structs.insert({Name, nullptr}); 103 if (Result.second) { 104 // Create the record if it does not already exist. 105 auto Record = std::make_unique<StructRecord>( 106 Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 107 Result.first->second = std::move(Record); 108 } 109 return Result.first->second.get(); 110 } 111 112 ObjCInterfaceRecord *APISet::addObjCInterface( 113 StringRef Name, StringRef USR, PresumedLoc Loc, 114 const AvailabilityInfo &Availability, LinkageInfo Linkage, 115 const DocComment &Comment, DeclarationFragments Declaration, 116 DeclarationFragments SubHeading, SymbolReference SuperClass) { 117 auto Result = ObjCInterfaces.insert({Name, nullptr}); 118 if (Result.second) { 119 // Create the record if it does not already exist. 120 auto Record = std::make_unique<ObjCInterfaceRecord>( 121 Name, USR, Loc, Availability, Linkage, Comment, Declaration, SubHeading, 122 SuperClass); 123 Result.first->second = std::move(Record); 124 } 125 return Result.first->second.get(); 126 } 127 128 ObjCMethodRecord *APISet::addObjCMethod( 129 ObjCContainerRecord *Container, StringRef Name, StringRef USR, 130 PresumedLoc Loc, const AvailabilityInfo &Availability, 131 const DocComment &Comment, DeclarationFragments Declaration, 132 DeclarationFragments SubHeading, FunctionSignature Signature, 133 bool IsInstanceMethod) { 134 auto Record = std::make_unique<ObjCMethodRecord>( 135 Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Signature, 136 IsInstanceMethod); 137 return Container->Methods.emplace_back(std::move(Record)).get(); 138 } 139 140 ObjCPropertyRecord *APISet::addObjCProperty( 141 ObjCContainerRecord *Container, StringRef Name, StringRef USR, 142 PresumedLoc Loc, const AvailabilityInfo &Availability, 143 const DocComment &Comment, DeclarationFragments Declaration, 144 DeclarationFragments SubHeading, 145 ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName, 146 StringRef SetterName, bool IsOptional) { 147 auto Record = std::make_unique<ObjCPropertyRecord>( 148 Name, USR, Loc, Availability, Comment, Declaration, SubHeading, 149 Attributes, GetterName, SetterName, IsOptional); 150 return Container->Properties.emplace_back(std::move(Record)).get(); 151 } 152 153 ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable( 154 ObjCContainerRecord *Container, StringRef Name, StringRef USR, 155 PresumedLoc Loc, const AvailabilityInfo &Availability, 156 const DocComment &Comment, DeclarationFragments Declaration, 157 DeclarationFragments SubHeading, 158 ObjCInstanceVariableRecord::AccessControl Access) { 159 auto Record = std::make_unique<ObjCInstanceVariableRecord>( 160 Name, USR, Loc, Availability, Comment, Declaration, SubHeading, Access); 161 return Container->Ivars.emplace_back(std::move(Record)).get(); 162 } 163 164 ObjCProtocolRecord *APISet::addObjCProtocol( 165 StringRef Name, StringRef USR, PresumedLoc Loc, 166 const AvailabilityInfo &Availability, const DocComment &Comment, 167 DeclarationFragments Declaration, DeclarationFragments SubHeading) { 168 auto Result = ObjCProtocols.insert({Name, nullptr}); 169 if (Result.second) { 170 // Create the record if it does not already exist. 171 auto Record = std::make_unique<ObjCProtocolRecord>( 172 Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 173 Result.first->second = std::move(Record); 174 } 175 return Result.first->second.get(); 176 } 177 178 StringRef APISet::recordUSR(const Decl *D) { 179 SmallString<128> USR; 180 index::generateUSRForDecl(D, USR); 181 return copyString(USR); 182 } 183 184 StringRef APISet::copyString(StringRef String) { 185 if (String.empty()) 186 return {}; 187 188 // No need to allocate memory and copy if the string has already been stored. 189 if (StringAllocator.identifyObject(String.data())) 190 return String; 191 192 void *Ptr = StringAllocator.Allocate(String.size(), 1); 193 memcpy(Ptr, String.data(), String.size()); 194 return StringRef(reinterpret_cast<const char *>(Ptr), String.size()); 195 } 196 197 APIRecord::~APIRecord() {} 198 199 ObjCContainerRecord::~ObjCContainerRecord() {} 200 201 void GlobalRecord::anchor() {} 202 void EnumConstantRecord::anchor() {} 203 void EnumRecord::anchor() {} 204 void StructFieldRecord::anchor() {} 205 void StructRecord::anchor() {} 206 void ObjCPropertyRecord::anchor() {} 207 void ObjCInstanceVariableRecord::anchor() {} 208 void ObjCMethodRecord::anchor() {} 209 void ObjCInterfaceRecord::anchor() {} 210 void ObjCProtocolRecord::anchor() {} 211