#ifndef LLVM_CLANG_EXTRACTAPI_API_H
#define LLVM_CLANG_EXTRACTAPI_API_H
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/RawCommentList.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/ExtractAPI/AvailabilityInfo.h"
#include "clang/ExtractAPI/DeclarationFragments.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include <memory>
#include <type_traits>
namespace clang {
namespace extractapi {
using DocComment = std::vector<RawComment::CommentLine>;
struct APIRecord {
StringRef USR;
StringRef Name;
PresumedLoc Location;
AvailabilityInfo Availability;
LinkageInfo Linkage;
DocComment Comment;
DeclarationFragments Declaration;
DeclarationFragments SubHeading;
enum RecordKind {
RK_GlobalFunction,
RK_GlobalVariable,
RK_EnumConstant,
RK_Enum,
RK_StructField,
RK_Struct,
RK_ObjCProperty,
RK_ObjCIvar,
RK_ObjCMethod,
RK_ObjCInterface,
RK_ObjCCategory,
RK_ObjCProtocol,
RK_MacroDefinition,
RK_Typedef,
};
private:
const RecordKind Kind;
public:
RecordKind getKind() const { return Kind; }
APIRecord() = delete;
APIRecord(RecordKind Kind, StringRef USR, StringRef Name,
PresumedLoc Location, const AvailabilityInfo &Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading)
: USR(USR), Name(Name), Location(Location), Availability(Availability),
Linkage(Linkage), Comment(Comment), Declaration(Declaration),
SubHeading(SubHeading), Kind(Kind) {}
virtual ~APIRecord() = 0;
};
struct GlobalFunctionRecord : APIRecord {
FunctionSignature Signature;
GlobalFunctionRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature)
: APIRecord(RK_GlobalFunction, USR, Name, Loc, Availability, Linkage,
Comment, Declaration, SubHeading),
Signature(Signature) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_GlobalFunction;
}
private:
virtual void anchor();
};
struct GlobalVariableRecord : APIRecord {
GlobalVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading)
: APIRecord(RK_GlobalVariable, USR, Name, Loc, Availability, Linkage,
Comment, Declaration, SubHeading) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_GlobalVariable;
}
private:
virtual void anchor();
};
struct EnumConstantRecord : APIRecord {
EnumConstantRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading)
: APIRecord(RK_EnumConstant, USR, Name, Loc, Availability,
LinkageInfo::none(), Comment, Declaration, SubHeading) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_EnumConstant;
}
private:
virtual void anchor();
};
struct EnumRecord : APIRecord {
SmallVector<std::unique_ptr<EnumConstantRecord>> Constants;
EnumRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading)
: APIRecord(RK_Enum, USR, Name, Loc, Availability, LinkageInfo::none(),
Comment, Declaration, SubHeading) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_Enum;
}
private:
virtual void anchor();
};
struct StructFieldRecord : APIRecord {
StructFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading)
: APIRecord(RK_StructField, USR, Name, Loc, Availability,
LinkageInfo::none(), Comment, Declaration, SubHeading) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_StructField;
}
private:
virtual void anchor();
};
struct StructRecord : APIRecord {
SmallVector<std::unique_ptr<StructFieldRecord>> Fields;
StructRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading)
: APIRecord(RK_Struct, USR, Name, Loc, Availability, LinkageInfo::none(),
Comment, Declaration, SubHeading) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_Struct;
}
private:
virtual void anchor();
};
struct ObjCPropertyRecord : APIRecord {
enum AttributeKind : unsigned {
NoAttr = 0,
ReadOnly = 1,
Class = 1 << 1,
Dynamic = 1 << 2,
};
AttributeKind Attributes;
StringRef GetterName;
StringRef SetterName;
bool IsOptional;
ObjCPropertyRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AttributeKind Attributes,
StringRef GetterName, StringRef SetterName,
bool IsOptional)
: APIRecord(RK_ObjCProperty, USR, Name, Loc, Availability,
LinkageInfo::none(), Comment, Declaration, SubHeading),
Attributes(Attributes), GetterName(GetterName), SetterName(SetterName),
IsOptional(IsOptional) {}
bool isReadOnly() const { return Attributes & ReadOnly; }
bool isDynamic() const { return Attributes & Dynamic; }
bool isClassProperty() const { return Attributes & Class; }
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_ObjCProperty;
}
private:
virtual void anchor();
};
struct ObjCInstanceVariableRecord : APIRecord {
using AccessControl = ObjCIvarDecl::AccessControl;
AccessControl Access;
ObjCInstanceVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
AccessControl Access)
: APIRecord(RK_ObjCIvar, USR, Name, Loc, Availability,
LinkageInfo::none(), Comment, Declaration, SubHeading),
Access(Access) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_ObjCIvar;
}
private:
virtual void anchor();
};
struct ObjCMethodRecord : APIRecord {
FunctionSignature Signature;
bool IsInstanceMethod;
ObjCMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsInstanceMethod)
: APIRecord(RK_ObjCMethod, USR, Name, Loc, Availability,
LinkageInfo::none(), Comment, Declaration, SubHeading),
Signature(Signature), IsInstanceMethod(IsInstanceMethod) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_ObjCMethod;
}
private:
virtual void anchor();
};
struct SymbolReference {
StringRef Name;
StringRef USR;
StringRef Source;
SymbolReference() = default;
SymbolReference(StringRef Name, StringRef USR = "", StringRef Source = "")
: Name(Name), USR(USR), Source(Source) {}
SymbolReference(const APIRecord &Record)
: Name(Record.Name), USR(Record.USR) {}
bool empty() const { return Name.empty() && USR.empty() && Source.empty(); }
};
struct ObjCContainerRecord : APIRecord {
SmallVector<std::unique_ptr<ObjCMethodRecord>> Methods;
SmallVector<std::unique_ptr<ObjCPropertyRecord>> Properties;
SmallVector<std::unique_ptr<ObjCInstanceVariableRecord>> Ivars;
SmallVector<SymbolReference> Protocols;
ObjCContainerRecord() = delete;
ObjCContainerRecord(RecordKind Kind, StringRef USR, StringRef Name,
PresumedLoc Loc, const AvailabilityInfo &Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading)
: APIRecord(Kind, USR, Name, Loc, Availability, Linkage, Comment,
Declaration, SubHeading) {}
virtual ~ObjCContainerRecord() = 0;
};
struct ObjCCategoryRecord : ObjCContainerRecord {
SymbolReference Interface;
ObjCCategoryRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference Interface)
: ObjCContainerRecord(RK_ObjCCategory, USR, Name, Loc, Availability,
LinkageInfo::none(), Comment, Declaration,
SubHeading),
Interface(Interface) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_ObjCCategory;
}
private:
virtual void anchor();
};
struct ObjCInterfaceRecord : ObjCContainerRecord {
SymbolReference SuperClass;
SmallVector<ObjCCategoryRecord *> Categories;
ObjCInterfaceRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
SymbolReference SuperClass)
: ObjCContainerRecord(RK_ObjCInterface, USR, Name, Loc, Availability,
Linkage, Comment, Declaration, SubHeading),
SuperClass(SuperClass) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_ObjCInterface;
}
private:
virtual void anchor();
};
struct ObjCProtocolRecord : ObjCContainerRecord {
ObjCProtocolRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading)
: ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Loc, Availability,
LinkageInfo::none(), Comment, Declaration,
SubHeading) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_ObjCProtocol;
}
private:
virtual void anchor();
};
struct MacroDefinitionRecord : APIRecord {
MacroDefinitionRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
DeclarationFragments Declaration,
DeclarationFragments SubHeading)
: APIRecord(RK_MacroDefinition, USR, Name, Loc, AvailabilityInfo(),
LinkageInfo(), {}, Declaration, SubHeading) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_MacroDefinition;
}
private:
virtual void anchor();
};
struct TypedefRecord : APIRecord {
SymbolReference UnderlyingType;
TypedefRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
const AvailabilityInfo &Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference UnderlyingType)
: APIRecord(RK_Typedef, USR, Name, Loc, Availability, LinkageInfo(),
Comment, Declaration, SubHeading),
UnderlyingType(UnderlyingType) {}
static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_Typedef;
}
private:
virtual void anchor();
};
template <typename RecordTy>
struct has_function_signature : public std::false_type {};
template <>
struct has_function_signature<GlobalFunctionRecord> : public std::true_type {};
template <>
struct has_function_signature<ObjCMethodRecord> : public std::true_type {};
class APISet {
public:
GlobalVariableRecord *
addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
const AvailabilityInfo &Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading);
GlobalFunctionRecord *
addGlobalFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
const AvailabilityInfo &Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature);
EnumConstantRecord *addEnumConstant(EnumRecord *Enum, StringRef Name,
StringRef USR, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading);
EnumRecord *addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading);
StructFieldRecord *addStructField(StructRecord *Struct, StringRef Name,
StringRef USR, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading);
StructRecord *addStruct(StringRef Name, StringRef USR, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading);
ObjCCategoryRecord *
addObjCCategory(StringRef Name, StringRef USR, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference Interface);
ObjCInterfaceRecord *
addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
const AvailabilityInfo &Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference SuperClass);
ObjCMethodRecord *
addObjCMethod(ObjCContainerRecord *Container, StringRef Name, StringRef USR,
PresumedLoc Loc, const AvailabilityInfo &Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsInstanceMethod);
ObjCPropertyRecord *
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);
ObjCInstanceVariableRecord *addObjCInstanceVariable(
ObjCContainerRecord *Container, StringRef Name, StringRef USR,
PresumedLoc Loc, const AvailabilityInfo &Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading,
ObjCInstanceVariableRecord::AccessControl Access);
ObjCProtocolRecord *addObjCProtocol(StringRef Name, StringRef USR,
PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading);
MacroDefinitionRecord *addMacroDefinition(StringRef Name, StringRef USR,
PresumedLoc Loc,
DeclarationFragments Declaration,
DeclarationFragments SubHeading);
TypedefRecord *addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc,
const AvailabilityInfo &Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
SymbolReference UnderlyingType);
template <typename RecordTy,
typename =
std::enable_if_t<std::is_base_of<APIRecord, RecordTy>::value>>
using RecordMap = llvm::MapVector<StringRef, std::unique_ptr<RecordTy>>;
const llvm::Triple &getTarget() const { return Target; }
Language getLanguage() const { return Lang; }
const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const {
return GlobalFunctions;
}
const RecordMap<GlobalVariableRecord> &getGlobalVariables() const {
return GlobalVariables;
}
const RecordMap<EnumRecord> &getEnums() const { return Enums; }
const RecordMap<StructRecord> &getStructs() const { return Structs; }
const RecordMap<ObjCCategoryRecord> &getObjCCategories() const {
return ObjCCategories;
}
const RecordMap<ObjCInterfaceRecord> &getObjCInterfaces() const {
return ObjCInterfaces;
}
const RecordMap<ObjCProtocolRecord> &getObjCProtocols() const {
return ObjCProtocols;
}
const RecordMap<MacroDefinitionRecord> &getMacros() const { return Macros; }
const RecordMap<TypedefRecord> &getTypedefs() const { return Typedefs; }
StringRef recordUSR(const Decl *D);
StringRef recordUSRForMacro(StringRef Name, SourceLocation SL,
const SourceManager &SM);
StringRef copyString(StringRef String);
APISet(const llvm::Triple &Target, Language Lang)
: Target(Target), Lang(Lang) {}
private:
llvm::BumpPtrAllocator StringAllocator;
const llvm::Triple Target;
const Language Lang;
RecordMap<GlobalFunctionRecord> GlobalFunctions;
RecordMap<GlobalVariableRecord> GlobalVariables;
RecordMap<EnumRecord> Enums;
RecordMap<StructRecord> Structs;
RecordMap<ObjCCategoryRecord> ObjCCategories;
RecordMap<ObjCInterfaceRecord> ObjCInterfaces;
RecordMap<ObjCProtocolRecord> ObjCProtocols;
RecordMap<MacroDefinitionRecord> Macros;
RecordMap<TypedefRecord> Typedefs;
};
} }
#endif