///===-- Representation.h - ClangDoc Representation -------------*- 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 // //===----------------------------------------------------------------------===// // // This file defines the internal representations of different declaration // types for the clang-doc tool. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H #include "clang/AST/Type.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/Specifiers.h" #include "clang/Tooling/Execution.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/simple_ilist.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/StringSaver.h" #include #include #include #include namespace clang { namespace doc { class ConcurrentStringPool { public: StringRef intern(StringRef Name) { if (Name.empty()) return StringRef(); llvm::sys::SmartScopedLock Lock(PoolMutex); return Saver.save(Name); } private: llvm::sys::SmartMutex PoolMutex; llvm::BumpPtrAllocator Alloc; llvm::UniqueStringSaver Saver{Alloc}; }; ConcurrentStringPool &getGlobalStringPool(); extern thread_local llvm::BumpPtrAllocator TransientArena; extern thread_local llvm::BumpPtrAllocator PersistentArena; inline StringRef internString(const Twine &T) { if (T.isTriviallyEmpty()) return StringRef(); if (T.isSingleStringRef()) { StringRef S = T.getSingleStringRef(); if (S.empty()) return StringRef(); return getGlobalStringPool().intern(S); } SmallString<128> Buffer; StringRef S = T.toStringRef(Buffer); if (S.empty()) return StringRef(); return getGlobalStringPool().intern(S); } template llvm::ArrayRef allocateArray(llvm::SmallVectorImpl &V, llvm::BumpPtrAllocator &Alloc) { if (V.empty()) return llvm::ArrayRef(); T *Allocated = static_cast(Alloc.Allocate(V.size())); std::uninitialized_move(V.begin(), V.end(), Allocated); return llvm::ArrayRef(Allocated, V.size()); } template llvm::ArrayRef allocateArray(llvm::ArrayRef V, llvm::BumpPtrAllocator &Alloc) { if (V.empty()) return llvm::ArrayRef(); T *Allocated = static_cast(Alloc.Allocate(V.size())); std::uninitialized_move(V.begin(), V.end(), Allocated); return llvm::ArrayRef(Allocated, V.size()); } template llvm::ArrayRef deepCopyArray(llvm::ArrayRef V, llvm::BumpPtrAllocator &Alloc) { if (V.empty()) return llvm::ArrayRef(); T *Allocated = static_cast(Alloc.Allocate(V.size())); for (size_t Idx = 0; Idx < V.size(); ++Idx) { new (Allocated + Idx) T(V[Idx], Alloc); } return llvm::ArrayRef(Allocated, V.size()); } // A helper function to create an owned pointer, abstracting away the memory // allocation mechanism. template T *allocateTransient(Args &&...args) { return new (TransientArena.Allocate()) T(std::forward(args)...); } // A helper function to create memory allocated in the TransientArena. template T *allocatePersistent(Args &&...args) { return new (PersistentArena.Allocate()) T(std::forward(args)...); } // An overload to explicitly allocate on an arena, returning a bare pointer. template T *allocatePtr(llvm::BumpPtrAllocator &Alloc, Args &&...args) { return new (Alloc.Allocate()) T(std::forward(args)...); } template struct InfoNode : public llvm::ilist_node> { InfoNode(T *P) : Ptr(P) {} T *Ptr = nullptr; operator T &() { return *Ptr; } operator const T &() const { return *Ptr; } T &operator*() { return *Ptr; } const T &operator*() const { return *Ptr; } T *operator->() { return Ptr; } const T *operator->() const { return Ptr; } bool operator==(const InfoNode &Other) const { if (!Ptr || !Other.Ptr) return Ptr == Other.Ptr; return *Ptr == *Other.Ptr; } bool operator!=(const InfoNode &Other) const { return !(*this == Other); } bool operator<(const InfoNode &Other) const { if (!Ptr || !Other.Ptr) return Ptr < Other.Ptr; return *Ptr < *Other.Ptr; } }; template InfoNode *allocateListNode(llvm::BumpPtrAllocator &Alloc, Args &&...args) { T *Item = allocatePtr(Alloc, std::forward(args)...); return allocatePtr>(Alloc, Item); } template InfoNode *allocateListNodeTransient(Args &&...args) { return allocateListNode(TransientArena, std::forward(args)...); } template InfoNode *allocateListNode(llvm::BumpPtrAllocator &Alloc, T *Item) { return allocatePtr>(Alloc, Item); } template InfoNode *allocateListNodeTransient(T *Item) { return allocateListNode(TransientArena, Item); } template InfoNode *allocateListNodePersistent(Args &&...args) { return allocateListNode(PersistentArena, std::forward(args)...); } template InfoNode *allocateListNodePersistent(T *Item) { return allocateListNode(PersistentArena, Item); } // An abstraction for lists that are dynamically managed (inserted/removed). // To be eventually transitioned to llvm::simple_ilist. template using DocList = llvm::simple_ilist>; // SHA1'd hash of a USR. using SymbolID = std::array; constexpr SymbolID GlobalNamespaceID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; struct BaseRecordInfo; struct EnumInfo; struct FunctionInfo; struct Info; struct TypedefInfo; struct ConceptInfo; struct VarInfo; enum class InfoType { IT_default, IT_namespace, IT_record, IT_function, IT_enum, IT_typedef, IT_concept, IT_variable, IT_friend }; enum class CommentKind { CK_FullComment, CK_ParagraphComment, CK_TextComment, CK_InlineCommandComment, CK_HTMLStartTagComment, CK_HTMLEndTagComment, CK_BlockCommandComment, CK_ParamCommandComment, CK_TParamCommandComment, CK_VerbatimBlockComment, CK_VerbatimBlockLineComment, CK_VerbatimLineComment, CK_Unknown }; enum OutputFormatTy { md, yaml, html, json, md_mustache }; CommentKind stringToCommentKind(llvm::StringRef KindStr); llvm::StringRef commentKindToString(CommentKind Kind); struct CommentInfo; // A representation of a parsed comment. struct CommentInfo { CommentInfo() = default; CommentInfo(const CommentInfo &Other) = default; CommentInfo &operator=(const CommentInfo &Other) = default; CommentInfo(const CommentInfo &Other, llvm::BumpPtrAllocator &Arena); CommentInfo(CommentInfo &&Other) = default; CommentInfo &operator=(CommentInfo &&Other) = default; CommentInfo(CommentKind Kind, llvm::ArrayRef Children = {}, StringRef Text = StringRef(), StringRef Name = StringRef(), StringRef CloseName = StringRef(), StringRef Direction = StringRef(), StringRef ParamName = StringRef(), bool Explicit = false, bool SelfClosing = false, llvm::ArrayRef AttrKeys = {}, llvm::ArrayRef AttrValues = {}) : Children(Children), Direction(Direction), Name(Name), ParamName(ParamName), CloseName(CloseName), Text(Text), AttrKeys(AttrKeys), AttrValues(AttrValues), Kind(Kind), SelfClosing(SelfClosing), Explicit(Explicit) {} bool operator==(const CommentInfo &Other) const; // This operator is used to sort a vector of CommentInfos. // No specific order (attributes more important than others) is required. Any // sort is enough, the order is only needed to call std::unique after sorting // the vector. bool operator<(const CommentInfo &Other) const; // List of child comments for this CommentInfo. ArrayRef Children = {}; // Parameter direction (for (T)ParamCommand). StringRef Direction = {}; // Name of the comment (for Verbatim and HTML). StringRef Name = {}; // Parameter name (for (T)ParamCommand). StringRef ParamName = {}; // Closing tag name (for VerbatimBlock). StringRef CloseName = {}; // Text of the comment. StringRef Text = {}; // List of attribute keys (for HTML). ArrayRef AttrKeys = {}; // List of attribute values for each key (for HTML). ArrayRef AttrValues = {}; // List of arguments to commands (for InlineCommand). ArrayRef Args = {}; // Type of comment. Unknown by default. CommentKind Kind = CommentKind::CK_Unknown; // Indicates if tag is self-closing (for HTML). bool SelfClosing = false; // Indicates if the direction of a param is explicit (for (T)ParamCommand). bool Explicit = false; }; struct Reference { // This variant (that takes no qualified name parameter) uses the Name as the // QualName (very useful in unit tests to reduce verbosity). This can't use an // empty string to indicate the default because we need to accept the empty // string as a valid input for the global namespace (it will have // "GlobalNamespace" as the name, but an empty QualName). Reference(SymbolID USR = SymbolID(), StringRef Name = StringRef(), InfoType IT = InfoType::IT_default) : USR(USR), RefType(IT), Name(internString(Name)), QualName(internString(Name)) {} Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName, StringRef Path = StringRef()) : USR(USR), RefType(IT), Name(internString(Name)), QualName(internString(QualName)), Path(internString(Path)) {} Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName, StringRef Path, StringRef DocumentationFileName) : USR(USR), RefType(IT), Name(internString(Name)), QualName(internString(QualName)), Path(internString(Path)), DocumentationFileName(internString(DocumentationFileName)) {} bool operator==(const Reference &Other) const { return std::tie(USR, Name, QualName, RefType) == std::tie(Other.USR, Other.Name, Other.QualName, Other.RefType); } bool mergeable(const Reference &Other); void merge(Reference &&I); bool operator<(const Reference &Other) const { return Name < Other.Name; } /// Returns the path for this Reference relative to CurrentPath. StringRef getRelativeFilePath(const StringRef &CurrentPath) const; /// Returns the basename that should be used for this Reference. StringRef getFileBaseName() const; SymbolID USR = SymbolID(); // Unique identifier for referenced decl InfoType RefType = InfoType::IT_default; // Indicates the type of this // Reference (namespace, record, // function, enum, default). // Name of type (possibly unresolved). Not including namespaces or template // parameters (so for a std::vector this would be "vector"). See also // QualName. StringRef Name = {}; // Full qualified name of this type, including namespaces and template // parameter (for example this could be "std::vector"). Contrast to // Name. StringRef QualName = {}; // Path of directory where the clang-doc generated file will be saved // (possibly unresolved) StringRef Path = {}; StringRef DocumentationFileName = {}; }; // A Context is a reference that holds a relative path from a certain Info's // location. struct Context : public Reference { Context(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName, StringRef Path, StringRef DocumentationFileName) : Reference(USR, Name, IT, QualName, Path, DocumentationFileName) {} explicit Context(const Info &I); StringRef RelativePath = {}; }; // Holds the children of a record or namespace. struct ScopeChildren { // Namespaces and Records are references because they will be properly // documented in their own info, while the entirety of Functions and Enums are // included here because they should not have separate documentation from // their scope. // // Namespaces are not syntactically valid as children of records, but making // this general for all possible container types reduces code complexity. DocList Namespaces = {}; DocList Records = {}; DocList Functions = {}; DocList Enums = {}; DocList Typedefs = {}; DocList Concepts = {}; DocList Variables = {}; void sort(); }; // A base struct for TypeInfos struct TypeInfo { TypeInfo() = default; TypeInfo(const Reference &R) : Type(R) {} // Convenience constructor for when there is no symbol ID or info type // (normally used for built-in types in tests). TypeInfo(StringRef Name, StringRef Path = StringRef()) : Type(SymbolID(), Name, InfoType::IT_default, Name, Path) {} bool operator==(const TypeInfo &Other) const { return Type == Other.Type; } Reference Type; // Referenced type in this info. bool IsTemplate = false; bool IsBuiltIn = false; }; // Represents one template parameter. // // This is a very simple serialization of the text of the source code of the // template parameter. It is saved in a struct so there is a place to add the // name and default values in the future if needed. struct TemplateParamInfo { TemplateParamInfo() = default; explicit TemplateParamInfo(StringRef Contents) : Contents(internString(Contents)) {} // The literal contents of the code for that specifies this template parameter // for this declaration. Typical values will be "class T" and // "typename T = int". StringRef Contents = {}; }; struct TemplateSpecializationInfo { TemplateSpecializationInfo() = default; TemplateSpecializationInfo(const TemplateSpecializationInfo &Other, llvm::BumpPtrAllocator &Arena); // Indicates the declaration that this specializes. SymbolID SpecializationOf; // Template parameters applying to the specialized record/function. llvm::ArrayRef Params = {}; }; struct ConstraintInfo { ConstraintInfo() = default; ConstraintInfo(SymbolID USR, StringRef Name) : ConceptRef(USR, Name, InfoType::IT_concept) {} Reference ConceptRef; StringRef ConstraintExpr = {}; }; // Records the template information for a struct or function that is a template // or an explicit template specialization. struct TemplateInfo { TemplateInfo() = default; TemplateInfo(const TemplateInfo &Other, llvm::BumpPtrAllocator &Arena); // May be empty for non-partial specializations. llvm::ArrayRef Params = {}; // Set when this is a specialization of another record/function. std::optional Specialization; llvm::ArrayRef Constraints = {}; }; // Info for field types. struct FieldTypeInfo : public TypeInfo { FieldTypeInfo() = default; FieldTypeInfo(const TypeInfo &TI, StringRef Name = StringRef(), StringRef DefaultValue = StringRef()) : TypeInfo(TI), Name(internString(Name)), DefaultValue(internString(DefaultValue)) {} bool operator==(const FieldTypeInfo &Other) const { return std::tie(Type, Name, DefaultValue) == std::tie(Other.Type, Other.Name, Other.DefaultValue); } StringRef Name = {}; // Name associated with this info. // When used for function parameters, contains the string representing the // expression of the default value, if any. StringRef DefaultValue = {}; }; // Info for member types. struct MemberTypeInfo : public FieldTypeInfo { MemberTypeInfo() = default; MemberTypeInfo(const MemberTypeInfo &Other, llvm::BumpPtrAllocator &Arena); MemberTypeInfo(const TypeInfo &TI, StringRef Name, AccessSpecifier Access, bool IsStatic = false) : FieldTypeInfo(TI, Name), Access(Access), IsStatic(IsStatic) {} bool operator==(const MemberTypeInfo &Other) const { if (std::tie(Type, Name, Access, IsStatic) != std::tie(Other.Type, Other.Name, Other.Access, Other.IsStatic)) return false; return std::equal(Description.begin(), Description.end(), Other.Description.begin(), Other.Description.end()); } DocList Description; // Access level associated with this info (public, protected, private, none). // AS_public is set as default because the bitcode writer requires the enum // with value 0 to be used as the default. // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3) AccessSpecifier Access = AccessSpecifier::AS_public; bool IsStatic = false; }; struct Location { Location(int StartLineNumber = 0, int EndLineNumber = 0, StringRef Filename = StringRef(), bool IsFileInRootDir = false) : Filename(internString(Filename)), StartLineNumber(StartLineNumber), EndLineNumber(EndLineNumber), IsFileInRootDir(IsFileInRootDir) {} bool operator==(const Location &Other) const { return std::tie(StartLineNumber, EndLineNumber, Filename) == std::tie(Other.StartLineNumber, Other.EndLineNumber, Other.Filename); } bool operator!=(const Location &Other) const { return !(*this == Other); } // This operator is used to sort a vector of Locations. // No specific order (attributes more important than others) is required. Any // sort is enough, the order is only needed to call std::unique after sorting // the vector. bool operator<(const Location &Other) const { return std::tie(StartLineNumber, EndLineNumber, Filename) < std::tie(Other.StartLineNumber, Other.EndLineNumber, Other.Filename); } StringRef Filename = {}; int StartLineNumber = 0; int EndLineNumber = 0; bool IsFileInRootDir = false; }; /// A base struct for Infos. struct Info { Info(InfoType IT = InfoType::IT_default, SymbolID USR = SymbolID(), StringRef Name = StringRef(), StringRef Path = StringRef()) : Path(internString(Path)), Name(internString(Name)), USR(USR), IT(IT) {} Info(const Info &Other, llvm::BumpPtrAllocator &Arena); Info(const Info &Other) = delete; Info(Info &&Other) = default; Info &operator=(Info &&Other) = default; void mergeBase(Info &&I); bool mergeable(const Info &Other); StringRef extractName() const; /// Returns the file path for this Info relative to CurrentPath. StringRef getRelativeFilePath(const StringRef &CurrentPath) const; /// Returns the basename that should be used for this Info. StringRef getFileBaseName() const; // Path of directory where the clang-doc generated file will be saved. StringRef Path = {}; // Unqualified name of the decl. StringRef Name = {}; // The name used for the file that this info is documented in. // In the JSON generator, infos are documented in files with mangled names. // Thus, we keep track of the physical filename for linking purposes. StringRef DocumentationFileName = {}; // List of parent namespaces for this decl. llvm::ArrayRef Namespace; // Unique identifier for the decl described by this Info. SymbolID USR = SymbolID(); // Currently only used for namespaces and records. SymbolID ParentUSR = SymbolID(); // InfoType of this particular Info. InfoType IT = InfoType::IT_default; // Comment description of this decl. DocList Description = {}; }; inline Context::Context(const Info &I) : Reference(I.USR, I.Name, I.IT, I.Name, I.Path, I.DocumentationFileName) {} // Info for namespaces. struct NamespaceInfo : public Info { NamespaceInfo(SymbolID USR = SymbolID(), StringRef Name = StringRef(), StringRef Path = StringRef()); void merge(NamespaceInfo &&I); ScopeChildren Children; }; // Info for symbols. struct SymbolInfo : public Info { SymbolInfo(InfoType IT, SymbolID USR = SymbolID(), StringRef Name = StringRef(), StringRef Path = StringRef()) : Info(IT, USR, Name, Path) {} SymbolInfo(const SymbolInfo &Other, llvm::BumpPtrAllocator &Arena); void merge(SymbolInfo &&I); bool operator<(const SymbolInfo &Other) const { // Sort by declaration location since we want the doc to be // generated in the order of the source code. // If the declaration location is the same, or not present // we sort by defined location otherwise fallback to the extracted name if (!Loc.empty() && !Other.Loc.empty() && Loc.front() != Other.Loc.front()) return Loc.front() < Other.Loc.front(); if (DefLoc && Other.DefLoc && *DefLoc != *Other.DefLoc) return *DefLoc < *Other.DefLoc; return extractName() < Other.extractName(); } std::optional DefLoc; // Location where this decl is defined. DocList Loc = {}; // Locations where this decl is declared. StringRef MangledName = {}; bool IsStatic = false; }; struct FriendInfo : public SymbolInfo { FriendInfo() : SymbolInfo(InfoType::IT_friend) {} FriendInfo(SymbolID USR) : SymbolInfo(InfoType::IT_friend, USR) {} FriendInfo(const InfoType IT, const SymbolID &USR, const StringRef Name = StringRef()) : SymbolInfo(IT, USR, Name) {} FriendInfo(const FriendInfo &Other, llvm::BumpPtrAllocator &Arena); bool mergeable(const FriendInfo &Other); void merge(FriendInfo &&Other); Reference Ref; std::optional Template; std::optional ReturnType; llvm::ArrayRef Params = {}; bool IsClass = false; }; struct VarInfo : public SymbolInfo { VarInfo() : SymbolInfo(InfoType::IT_variable) {} explicit VarInfo(SymbolID USR) : SymbolInfo(InfoType::IT_variable, USR) {} void merge(VarInfo &&I); TypeInfo Type; }; // TODO: Expand to allow for documenting templating and default args. // Info for functions. struct FunctionInfo : public SymbolInfo { FunctionInfo(SymbolID USR = SymbolID()) : SymbolInfo(InfoType::IT_function, USR) {} void merge(FunctionInfo &&I); Reference Parent; TypeInfo ReturnType; llvm::ArrayRef Params = {}; StringRef Prototype = {}; // When present, this function is a template or specialization. std::optional Template; // Access level for this method (public, private, protected, none). // AS_public is set as default because the bitcode writer requires the enum // with value 0 to be used as the default. // (AS_public = 0, AS_protected = 1, AS_private = 2, AS_none = 3) AccessSpecifier Access = AccessSpecifier::AS_public; bool IsMethod = false; }; // TODO: Expand to allow for documenting templating, inheritance access, // friend classes // Info for types. struct RecordInfo : public SymbolInfo { RecordInfo(SymbolID USR = SymbolID(), StringRef Name = StringRef(), StringRef Path = StringRef()); RecordInfo(const RecordInfo &Other, llvm::BumpPtrAllocator &Arena); void merge(RecordInfo &&I); // Type of this record (struct, class, union, interface). TagTypeKind TagType = TagTypeKind::Struct; // Indicates if the record was declared using a typedef. Things like anonymous // structs in a typedef: // typedef struct { ... } foo_t; // are converted into records with the typedef as the Name + this flag set. bool IsTypeDef = false; // When present, this record is a template or specialization. std::optional Template; llvm::ArrayRef Members = {}; // List of info about record members. llvm::ArrayRef Parents = {}; // List of base/parent records (does not include virtual parents). llvm::ArrayRef VirtualParents = {}; // List of virtual base/parent records. llvm::ArrayRef Bases = {}; // List of base/parent records; this includes inherited methods and // attributes llvm::ArrayRef Friends = {}; ScopeChildren Children; }; // Info for typedef and using statements. struct TypedefInfo : public SymbolInfo { TypedefInfo(SymbolID USR = SymbolID()) : SymbolInfo(InfoType::IT_typedef, USR) {} void merge(TypedefInfo &&I); TypeInfo Underlying = {}; // Only type aliases can be templates. std::optional Template; // Underlying type declaration StringRef TypeDeclaration = {}; // Indicates if this is a new C++ "using"-style typedef: // using MyVector = std::vector // False means it's a C-style typedef: // typedef std::vector MyVector; bool IsUsing = false; }; struct BaseRecordInfo : public RecordInfo { BaseRecordInfo(); BaseRecordInfo(const BaseRecordInfo &Other, llvm::BumpPtrAllocator &Arena); BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, bool IsVirtual, AccessSpecifier Access, bool IsParent); // Access level associated with this inherited info (public, protected, // private). AccessSpecifier Access = AccessSpecifier::AS_public; // Indicates if base corresponds to a virtual inheritance bool IsVirtual = false; bool IsParent = false; // Indicates if this base is a direct parent }; // Information for a single possible value of an enumeration. struct EnumValueInfo { explicit EnumValueInfo(StringRef Name = StringRef(), StringRef Value = StringRef("0"), StringRef ValueExpr = StringRef()) : Name(internString(Name)), Value(internString(Value)), ValueExpr(internString(ValueExpr)) {} EnumValueInfo(const EnumValueInfo &Other, llvm::BumpPtrAllocator &Arena); bool operator==(const EnumValueInfo &Other) const { return std::tie(Name, Value, ValueExpr) == std::tie(Other.Name, Other.Value, Other.ValueExpr); } StringRef Name = {}; // The computed value of the enumeration constant. This could be the result of // evaluating the ValueExpr, or it could be automatically generated according // to C rules. StringRef Value = {}; // Stores the user-supplied initialization expression for this enumeration // constant. This will be empty for implicit enumeration values. StringRef ValueExpr = {}; /// Comment description of this field. DocList Description; }; // TODO: Expand to allow for documenting templating. // Info for types. struct EnumInfo : public SymbolInfo { EnumInfo() : SymbolInfo(InfoType::IT_enum) {} EnumInfo(SymbolID USR) : SymbolInfo(InfoType::IT_enum, USR) {} void merge(EnumInfo &&I); // Indicates whether this enum is scoped (e.g. enum class). bool Scoped = false; // Set to nonempty to the type when this is an explicitly typed enum. For // enum Foo : short { ... }; // this will be "short". std::optional BaseType; llvm::ArrayRef Members = {}; // List of enum members. }; struct ConceptInfo : public SymbolInfo { ConceptInfo() : SymbolInfo(InfoType::IT_concept) {} ConceptInfo(SymbolID USR) : SymbolInfo(InfoType::IT_concept, USR) {} void merge(ConceptInfo &&I); bool IsType = false; TemplateInfo Template; StringRef ConstraintExpression = {}; }; struct Index : public Reference { Index() = default; Index(StringRef Name) : Reference(SymbolID(), Name) {} Index(StringRef Name, StringRef JumpToSection) : Reference(SymbolID(), Name), JumpToSection(JumpToSection) {} Index(SymbolID USR, StringRef Name, InfoType IT, StringRef Path) : Reference(USR, Name, IT, Name, Path) {} // This is used to look for a USR in a vector of Indexes using std::find bool operator==(const SymbolID &Other) const { return USR == Other; } bool operator<(const Index &Other) const; std::optional JumpToSection; llvm::StringMap Children; std::vector getSortedChildren() const; void sort(); }; // TODO: Add functionality to include separate markdown pages. // A standalone function to call to merge a vector of infos into one. // This assumes that all infos in the vector are of the same type, and will fail // if they are different. llvm::Expected mergeInfos(SmallVectorImpl &Values); // Merges a single new Info into an existing Reduced Info (allocating it if // needed). llvm::Error mergeSingleInfo(doc::Info *&Reduced, doc::Info *NewInfo, llvm::BumpPtrAllocator &Arena); struct ClangDocContext { ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName, bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot, StringRef RepositoryUrl, StringRef RepositoryCodeLinePrefix, StringRef Base, std::vector UserStylesheets, clang::DiagnosticsEngine &Diags, OutputFormatTy Format, bool FTimeTrace = false, bool Pretty = false); tooling::ExecutionContext *ECtx; std::string ProjectName; // Name of project clang-doc is documenting. std::string OutDirectory; // Directory for outputting generated files. std::string SourceRoot; // Directory where processed files are stored. Links // to definition locations will only be generated if // the file is in this dir. // URL of repository that hosts code used for links to definition locations. std::optional RepositoryUrl; // Prefix of line code for repository. std::optional RepositoryLinePrefix; // Path of CSS stylesheets that will be copied to OutDirectory and used to // style all HTML files. std::vector UserStylesheets; // JavaScript files that will be imported in all HTML files. std::vector JsScripts; // Base directory for remote repositories. StringRef Base; // Maps mustache template types to specific mustache template files. // Ex. comment-template -> /path/to/comment-template.mustache llvm::StringMap MustacheTemplates; // A pointer to a DiagnosticsEngine for error reporting. clang::DiagnosticsEngine &Diags; Index Idx; OutputFormatTy Format; int Granularity; // Granularity of ftime trace bool PublicOnly; // Indicates if only public declarations are documented. bool FTimeTrace; // Indicates if ftime trace is turned on bool Pretty; // Indicates if JSON is emitted with whitespace. }; // Ensure arena allocated types remain safe to allocate in the arena. // Only trivially destructible types are safe, so enforce that at compile-time. static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); static_assert(std::is_trivially_destructible_v); } // namespace doc } // namespace clang #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_REPRESENTATION_H