123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- //===- ExtractAPI/API.cpp ---------------------------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- ///
- /// \file
- /// This file implements the APIRecord and derived record structs,
- /// and the APISet class.
- ///
- //===----------------------------------------------------------------------===//
- #include "clang/ExtractAPI/API.h"
- #include "clang/AST/CommentCommandTraits.h"
- #include "clang/AST/CommentLexer.h"
- #include "clang/AST/RawCommentList.h"
- #include "clang/Index/USRGeneration.h"
- #include "llvm/ADT/STLFunctionalExtras.h"
- #include "llvm/ADT/StringRef.h"
- #include <memory>
- using namespace clang::extractapi;
- using namespace llvm;
- namespace {
- template <typename RecordTy, typename... CtorArgsTy>
- RecordTy *addTopLevelRecord(DenseMap<StringRef, APIRecord *> &USRLookupTable,
- APISet::RecordMap<RecordTy> &RecordMap,
- StringRef USR, CtorArgsTy &&...CtorArgs) {
- auto Result = RecordMap.insert({USR, nullptr});
- // Create the record if it does not already exist
- if (Result.second)
- Result.first->second =
- std::make_unique<RecordTy>(USR, std::forward<CtorArgsTy>(CtorArgs)...);
- auto *Record = Result.first->second.get();
- USRLookupTable.insert({USR, Record});
- return Record;
- }
- } // namespace
- GlobalVariableRecord *
- APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilitySet Availabilities, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Fragments,
- DeclarationFragments SubHeading, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, GlobalVariables, USR, Name, Loc,
- std::move(Availabilities), Linkage, Comment,
- Fragments, SubHeading, IsFromSystemHeader);
- }
- GlobalFunctionRecord *APISet::addGlobalFunction(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilitySet Availabilities, LinkageInfo Linkage,
- const DocComment &Comment, DeclarationFragments Fragments,
- DeclarationFragments SubHeading, FunctionSignature Signature,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, GlobalFunctions, USR, Name, Loc,
- std::move(Availabilities), Linkage, Comment,
- Fragments, SubHeading, Signature,
- IsFromSystemHeader);
- }
- EnumConstantRecord *APISet::addEnumConstant(EnumRecord *Enum, StringRef Name,
- StringRef USR, PresumedLoc Loc,
- AvailabilitySet Availabilities,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- auto Record = std::make_unique<EnumConstantRecord>(
- USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
- SubHeading, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Enum->USR, Enum->Name, Enum->getKind(), Enum);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Enum->Constants.emplace_back(std::move(Record)).get();
- }
- EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilitySet Availabilities,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Enums, USR, Name, Loc,
- std::move(Availabilities), Comment, Declaration,
- SubHeading, IsFromSystemHeader);
- }
- StructFieldRecord *APISet::addStructField(StructRecord *Struct, StringRef Name,
- StringRef USR, PresumedLoc Loc,
- AvailabilitySet Availabilities,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- auto Record = std::make_unique<StructFieldRecord>(
- USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
- SubHeading, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Struct->USR, Struct->Name, Struct->getKind(), Struct);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Struct->Fields.emplace_back(std::move(Record)).get();
- }
- StructRecord *APISet::addStruct(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilitySet Availabilities,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Structs, USR, Name, Loc,
- std::move(Availabilities), Comment, Declaration,
- SubHeading, IsFromSystemHeader);
- }
- ObjCCategoryRecord *APISet::addObjCCategory(
- StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilitySet Availabilities, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- SymbolReference Interface, bool IsFromSystemHeader) {
- // Create the category record.
- auto *Record =
- addTopLevelRecord(USRBasedLookupTable, ObjCCategories, USR, Name, Loc,
- std::move(Availabilities), Comment, Declaration,
- SubHeading, Interface, IsFromSystemHeader);
- // If this category is extending a known interface, associate it with the
- // ObjCInterfaceRecord.
- auto It = ObjCInterfaces.find(Interface.USR);
- if (It != ObjCInterfaces.end())
- It->second->Categories.push_back(Record);
- return Record;
- }
- ObjCInterfaceRecord *
- APISet::addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilitySet Availabilities, LinkageInfo Linkage,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- SymbolReference SuperClass, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, ObjCInterfaces, USR, Name, Loc,
- std::move(Availabilities), Linkage, Comment,
- Declaration, SubHeading, SuperClass,
- IsFromSystemHeader);
- }
- ObjCMethodRecord *APISet::addObjCMethod(
- ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- FunctionSignature Signature, bool IsInstanceMethod,
- bool IsFromSystemHeader) {
- std::unique_ptr<ObjCMethodRecord> Record;
- if (IsInstanceMethod)
- Record = std::make_unique<ObjCInstanceMethodRecord>(
- USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
- SubHeading, Signature, IsFromSystemHeader);
- else
- Record = std::make_unique<ObjCClassMethodRecord>(
- USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
- SubHeading, Signature, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Container->USR, Container->Name, Container->getKind(), Container);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Container->Methods.emplace_back(std::move(Record)).get();
- }
- ObjCPropertyRecord *APISet::addObjCProperty(
- ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName,
- StringRef SetterName, bool IsOptional, bool IsInstanceProperty,
- bool IsFromSystemHeader) {
- std::unique_ptr<ObjCPropertyRecord> Record;
- if (IsInstanceProperty)
- Record = std::make_unique<ObjCInstancePropertyRecord>(
- USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
- SubHeading, Attributes, GetterName, SetterName, IsOptional,
- IsFromSystemHeader);
- else
- Record = std::make_unique<ObjCClassPropertyRecord>(
- USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
- SubHeading, Attributes, GetterName, SetterName, IsOptional,
- IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Container->USR, Container->Name, Container->getKind(), Container);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Container->Properties.emplace_back(std::move(Record)).get();
- }
- ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable(
- ObjCContainerRecord *Container, StringRef Name, StringRef USR,
- PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment,
- DeclarationFragments Declaration, DeclarationFragments SubHeading,
- ObjCInstanceVariableRecord::AccessControl Access, bool IsFromSystemHeader) {
- auto Record = std::make_unique<ObjCInstanceVariableRecord>(
- USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
- SubHeading, Access, IsFromSystemHeader);
- Record->ParentInformation = APIRecord::HierarchyInformation(
- Container->USR, Container->Name, Container->getKind(), Container);
- USRBasedLookupTable.insert({USR, Record.get()});
- return Container->Ivars.emplace_back(std::move(Record)).get();
- }
- ObjCProtocolRecord *APISet::addObjCProtocol(StringRef Name, StringRef USR,
- PresumedLoc Loc,
- AvailabilitySet Availabilities,
- const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, ObjCProtocols, USR, Name, Loc,
- std::move(Availabilities), Comment, Declaration,
- SubHeading, IsFromSystemHeader);
- }
- MacroDefinitionRecord *
- APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Macros, USR, Name, Loc,
- Declaration, SubHeading, IsFromSystemHeader);
- }
- TypedefRecord *
- APISet::addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc,
- AvailabilitySet Availabilities, const DocComment &Comment,
- DeclarationFragments Declaration,
- DeclarationFragments SubHeading,
- SymbolReference UnderlyingType, bool IsFromSystemHeader) {
- return addTopLevelRecord(USRBasedLookupTable, Typedefs, USR, Name, Loc,
- std::move(Availabilities), Comment, Declaration,
- SubHeading, UnderlyingType, IsFromSystemHeader);
- }
- APIRecord *APISet::findRecordForUSR(StringRef USR) const {
- if (USR.empty())
- return nullptr;
- auto It = USRBasedLookupTable.find(USR);
- if (It != USRBasedLookupTable.end())
- return It->second;
- return nullptr;
- }
- StringRef APISet::recordUSR(const Decl *D) {
- SmallString<128> USR;
- index::generateUSRForDecl(D, USR);
- return copyString(USR);
- }
- StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL,
- const SourceManager &SM) {
- SmallString<128> USR;
- index::generateUSRForMacro(Name, SL, SM, USR);
- return copyString(USR);
- }
- StringRef APISet::copyString(StringRef String) {
- if (String.empty())
- return {};
- // No need to allocate memory and copy if the string has already been stored.
- if (StringAllocator.identifyObject(String.data()))
- return String;
- void *Ptr = StringAllocator.Allocate(String.size(), 1);
- memcpy(Ptr, String.data(), String.size());
- return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
- }
- APIRecord::~APIRecord() {}
- ObjCContainerRecord::~ObjCContainerRecord() {}
- ObjCMethodRecord::~ObjCMethodRecord() {}
- ObjCPropertyRecord::~ObjCPropertyRecord() {}
- void GlobalFunctionRecord::anchor() {}
- void GlobalVariableRecord::anchor() {}
- void EnumConstantRecord::anchor() {}
- void EnumRecord::anchor() {}
- void StructFieldRecord::anchor() {}
- void StructRecord::anchor() {}
- void ObjCInstancePropertyRecord::anchor() {}
- void ObjCClassPropertyRecord::anchor() {}
- void ObjCInstanceVariableRecord::anchor() {}
- void ObjCInstanceMethodRecord::anchor() {}
- void ObjCClassMethodRecord::anchor() {}
- void ObjCCategoryRecord::anchor() {}
- void ObjCInterfaceRecord::anchor() {}
- void ObjCProtocolRecord::anchor() {}
- void MacroDefinitionRecord::anchor() {}
- void TypedefRecord::anchor() {}
|