23#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/StringMap.h"
25#include "llvm/Support/Error.h"
26#include "llvm/Support/Path.h"
33 thread_local llvm::BumpPtrAllocator TransientArena;
34 return TransientArena;
38 thread_local llvm::BumpPtrAllocator PersistentArena;
39 return PersistentArena;
48 static const llvm::StringMap<CommentKind> KindMap = {
63 auto It = KindMap.find(KindStr);
64 if (It != KindMap.end()) {
75 return "ParagraphComment";
79 return "InlineCommandComment";
81 return "HTMLStartTagComment";
83 return "HTMLEndTagComment";
85 return "BlockCommandComment";
87 return "ParamCommandComment";
89 return "TParamCommandComment";
91 return "VerbatimBlockComment";
93 return "VerbatimBlockLineComment";
95 return "VerbatimLineComment";
99 llvm_unreachable(
"Unhandled CommentKind");
105static llvm::Expected<Info *>
reduce(SmallVectorImpl<Info *> &Values) {
106 if (Values.empty() || !Values[0])
107 return llvm::createStringError(llvm::inconvertibleErrorCode(),
108 "no value to reduce");
110 for (
auto &I : Values)
111 Merged->merge(std::move(*cast<T>(I)));
117 while (!ChildrenToMerge.empty()) {
118 T *Ptr = ChildrenToMerge.front().Ptr;
119 ChildrenToMerge.pop_front();
121 auto It = llvm::find_if(
122 Children, [Ptr](
const auto &C) {
return C.Ptr->USR == Ptr->USR; });
124 if (It == Children.end()) {
126 NewNode->Ptr->merge(std::move(*Ptr));
127 Children.push_back(*NewNode);
129 It->Ptr->merge(std::move(*Ptr));
137 while (!ChildrenToMerge.empty()) {
138 Reference *Ptr = ChildrenToMerge.front().Ptr;
139 ChildrenToMerge.pop_front();
141 auto It = llvm::find_if(
142 Children, [Ptr](
const auto &C) {
return C.Ptr->USR == Ptr->
USR; });
143 if (It == Children.end()) {
145 NewNode->Ptr->USR = Ptr->
USR;
146 NewNode->Ptr->RefType = Ptr->
RefType;
147 NewNode->Ptr->merge(std::move(*Ptr));
148 Children.push_back(*NewNode);
150 It->Ptr->merge(std::move(*Ptr));
157 while (!Source.empty()) {
158 T *Ptr = Source.front().Ptr;
161 if (!llvm::any_of(Target,
162 [Ptr](
const auto &E) {
return *E.Ptr == *Ptr; })) {
171 while (!Source.empty()) {
175 if (llvm::none_of(Target,
176 [Ptr](
const auto &E) {
return *E.Ptr == *Ptr; })) {
185 llvm::BumpPtrAllocator &Arena) {
188 cast<T>(Reduced)->merge(std::move(*cast<T>(NewInfo)));
189 return llvm::Error::success();
193 llvm::BumpPtrAllocator &Arena) {
194 if (Reduced && Reduced->
IT != NewInfo->
IT)
195 return llvm::createStringError(llvm::inconvertibleErrorCode(),
196 "info types mismatch");
198 switch (NewInfo->
IT) {
216 return llvm::createStringError(llvm::inconvertibleErrorCode(),
217 "unknown info type");
220 return llvm::Error::success();
224llvm::Expected<Info *>
mergeInfos(SmallVectorImpl<Info *> &Values) {
225 if (Values.empty() || !Values[0])
226 return llvm::createStringError(llvm::inconvertibleErrorCode(),
227 "no info values to merge");
229 switch (Values[0]->IT) {
247 return llvm::createStringError(llvm::inconvertibleErrorCode(),
248 "unexpected info type");
250 llvm_unreachable(
"unhandled enumerator");
260 llvm::BumpPtrAllocator &Arena) {
289 if (FirstCI < SecondCI)
292 if (FirstCI == SecondCI) {
302 llvm::BumpPtrAllocator &Arena) {
316 for (
size_t Idx = 0; Idx < Other.
Children.size(); ++Idx) {
323static llvm::SmallString<64>
325 const StringRef &Name,
const StringRef &CurrentPath) {
326 llvm::SmallString<64> FilePath;
328 if (CurrentPath != Path) {
330 for (llvm::sys::path::const_iterator I =
331 llvm::sys::path::begin(CurrentPath);
332 I != llvm::sys::path::end(CurrentPath); ++I)
333 llvm::sys::path::append(FilePath,
"..");
334 llvm::sys::path::append(FilePath, Path);
340 llvm::sys::path::append(FilePath, Name);
342 return llvm::sys::path::relative_path(FilePath);
376 "Merging reference with default InfoType");
393 Ref.merge(std::move(Other.Ref));
394 SymbolInfo::merge(std::move(Other));
404 if (!Other.
Params.empty())
431 if (
Namespace.empty() && !Other.Namespace.empty())
448 if (!Other.
Loc.empty()) {
449 for (const auto &L : Other.Loc) {
450 Location *NewL = allocatePtr<Location>(Arena, L);
451 Loc.push_back(*allocateListNode<Location>(Arena, NewL));
459 DefLoc = std::move(Other.DefLoc);
504 llvm::BumpPtrAllocator &Arena)
507 for (const auto &Desc : Other.Description) {
508 CommentInfo *NewDesc = allocatePtr<CommentInfo>(Arena, Desc, Arena);
509 Description.push_back(*allocateListNode<CommentInfo>(Arena, NewDesc));
516 if (!llvm::to_underlying(
TagType))
519 if (
Members.empty() && !Other.Members.empty())
521 if (
Bases.empty() && !Other.Bases.empty())
523 if (
Parents.empty() && !Other.Parents.empty())
527 if (
Friends.empty() && !Other.Friends.empty())
536 SymbolInfo::merge(std::move(Other));
540 llvm::BumpPtrAllocator &Arena)
543 for (const auto &Desc : Other.Description) {
544 CommentInfo *NewDesc = allocatePtr<CommentInfo>(Arena, Desc, Arena);
545 Description.push_back(*allocateListNode<CommentInfo>(Arena, NewDesc));
555 BaseType = std::move(Other.BaseType);
556 if (
Members.empty() && !Other.Members.empty())
558 SymbolInfo::merge(std::move(Other));
570 Parent = std::move(Other.Parent);
571 if (
Params.empty() && !Other.Params.empty())
575 SymbolInfo::merge(std::move(Other));
586 SymbolInfo::merge(std::move(Other));
595 if (
Template.Constraints.empty() && !Other.Template.Constraints.empty())
598 if (
Template.Params.empty() && !Other.Template.Params.empty())
601 SymbolInfo::merge(std::move(Other));
609 Type = std::move(Other.Type);
610 SymbolInfo::merge(std::move(Other));
616 llvm::BumpPtrAllocator &Arena)
637 return "@GlobalNamespace";
641 return "GlobalNamespace";
643 return internString(
"@nonymous_record_" + toHex(llvm::toStringRef(
USR)));
645 return internString(
"@nonymous_enum_" + toHex(llvm::toStringRef(
USR)));
647 return internString(
"@nonymous_typedef_" + toHex(llvm::toStringRef(
USR)));
649 return internString(
"@nonymous_function_" + toHex(llvm::toStringRef(
USR)));
651 return internString(
"@nonymous_concept_" + toHex(llvm::toStringRef(
USR)));
653 return internString(
"@nonymous_variable_" + toHex(llvm::toStringRef(
USR)));
655 return internString(
"@nonymous_friend_" + toHex(llvm::toStringRef(
USR)));
659 llvm_unreachable(
"Invalid InfoType.");
668 int Cmp =
Name.compare_insensitive(Other.
Name);
678 std::vector<const Index *> SortedChildren;
679 SortedChildren.reserve(
Children.size());
681 SortedChildren.push_back(&C);
682 llvm::sort(SortedChildren,
683 [](
const Index *A,
const Index *B) {
return *A < *B; });
684 return SortedChildren;
702 llvm::SmallString<128> SourceRootDir(
SourceRoot);
705 llvm::sys::fs::current_path(SourceRootDir);
706 this->SourceRoot = std::string(SourceRootDir);
711 this->RepositoryUrl->insert(0,
"https://");
static llvm::Error mergeTypedInfo(Info *&Reduced, Info *NewInfo, llvm::BumpPtrAllocator &Arena)
T * allocatePtr(llvm::BumpPtrAllocator &Alloc, Args &&...args)
void reduceChildren< Reference >(DocList< Reference > &Children, DocList< Reference > &&ChildrenToMerge)
static void mergeUnkeyed(DocList< T > &Target, DocList< T > &&Source)
@ CK_InlineCommandComment
@ CK_VerbatimBlockLineComment
@ CK_VerbatimBlockComment
@ CK_TParamCommandComment
static llvm::SmallString< 64 > calculateRelativeFilePath(const InfoType &Type, const StringRef &Path, const StringRef &Name, const StringRef &CurrentPath)
llvm::simple_ilist< InfoNode< T > > DocList
llvm::BumpPtrAllocator & getPersistentArena()
T * allocateTransient(Args &&...args)
void mergeUnkeyed< CommentInfo >(DocList< CommentInfo > &Target, DocList< CommentInfo > &&Source)
ConcurrentStringPool & getGlobalStringPool()
CommentKind stringToCommentKind(llvm::StringRef KindStr)
llvm::ArrayRef< T > deepCopyArray(llvm::ArrayRef< T > V, llvm::BumpPtrAllocator &Alloc)
InfoNode< T > * allocateListNodePersistent(Args &&...args)
InfoNode< T > * allocateListNode(llvm::BumpPtrAllocator &Alloc, Args &&...args)
StringRef internString(const Twine &T)
llvm::ArrayRef< T > allocateArray(llvm::SmallVectorImpl< T > &V, llvm::BumpPtrAllocator &Alloc)
llvm::Expected< Info * > mergeInfos(SmallVectorImpl< Info * > &Values)
static void reduceChildren(DocList< T > &Children, DocList< T > &&ChildrenToMerge)
static llvm::Expected< Info * > reduce(SmallVectorImpl< Info * > &Values)
llvm::BumpPtrAllocator & getTransientArena()
std::array< uint8_t, 20 > SymbolID
llvm::StringRef commentKindToString(CommentKind Kind)
llvm::Error mergeSingleInfo(doc::Info *&Reduced, doc::Info *NewInfo, llvm::BumpPtrAllocator &Arena)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::optional< std::string > RepositoryUrl
std::vector< std::string > UserStylesheets
tooling::ExecutionContext * ECtx
clang::DiagnosticsEngine & Diags
ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName, bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot, StringRef RepositoryUrl, StringRef RepositoryCodeLinePrefix, StringRef Base, std::vector< std::string > UserStylesheets, clang::DiagnosticsEngine &Diags, OutputFormatTy Format, bool FTimeTrace=false, bool Pretty=false)
std::optional< std::string > RepositoryLinePrefix
void merge(ConceptInfo &&I)
StringRef ConstraintExpression
llvm::ArrayRef< EnumValueInfo > Members
std::optional< TypeInfo > BaseType
DocList< CommentInfo > Description
Comment description of this field.
EnumValueInfo(StringRef Name=StringRef(), StringRef Value=StringRef("0"), StringRef ValueExpr=StringRef())
std::optional< TypeInfo > ReturnType
void merge(FriendInfo &&Other)
llvm::ArrayRef< FieldTypeInfo > Params
std::optional< TemplateInfo > Template
bool mergeable(const FriendInfo &Other)
FunctionInfo(SymbolID USR=SymbolID())
llvm::ArrayRef< FieldTypeInfo > Params
void merge(FunctionInfo &&I)
std::optional< TemplateInfo > Template
bool operator<(const Index &Other) const
llvm::StringMap< Index > Children
std::vector< const Index * > getSortedChildren() const
StringRef getRelativeFilePath(const StringRef &CurrentPath) const
Returns the file path for this Info relative to CurrentPath.
Info(InfoType IT=InfoType::IT_default, SymbolID USR=SymbolID(), StringRef Name=StringRef(), StringRef Path=StringRef())
bool mergeable(const Info &Other)
DocList< CommentInfo > Description
llvm::ArrayRef< Reference > Namespace
StringRef extractName() const
StringRef DocumentationFileName
StringRef getFileBaseName() const
Returns the basename that should be used for this Info.
DocList< CommentInfo > Description
NamespaceInfo(SymbolID USR=SymbolID(), StringRef Name=StringRef(), StringRef Path=StringRef())
void merge(NamespaceInfo &&I)
llvm::ArrayRef< BaseRecordInfo > Bases
llvm::ArrayRef< FriendInfo > Friends
RecordInfo(SymbolID USR=SymbolID(), StringRef Name=StringRef(), StringRef Path=StringRef())
llvm::ArrayRef< Reference > VirtualParents
std::optional< TemplateInfo > Template
llvm::ArrayRef< Reference > Parents
llvm::ArrayRef< MemberTypeInfo > Members
void merge(RecordInfo &&I)
void merge(Reference &&I)
StringRef DocumentationFileName
Reference(SymbolID USR=SymbolID(), StringRef Name=StringRef(), InfoType IT=InfoType::IT_default)
bool mergeable(const Reference &Other)
StringRef getFileBaseName() const
Returns the basename that should be used for this Reference.
StringRef getRelativeFilePath(const StringRef &CurrentPath) const
Returns the path for this Reference relative to CurrentPath.
DocList< Reference > Records
DocList< EnumInfo > Enums
DocList< ConceptInfo > Concepts
DocList< VarInfo > Variables
DocList< FunctionInfo > Functions
DocList< Reference > Namespaces
DocList< TypedefInfo > Typedefs
SymbolInfo(InfoType IT, SymbolID USR=SymbolID(), StringRef Name=StringRef(), StringRef Path=StringRef())
std::optional< Location > DefLoc
llvm::ArrayRef< TemplateParamInfo > Params
llvm::ArrayRef< ConstraintInfo > Constraints
std::optional< TemplateSpecializationInfo > Specialization
SymbolID SpecializationOf
TemplateSpecializationInfo()=default
llvm::ArrayRef< TemplateParamInfo > Params
void merge(TypedefInfo &&I)
std::optional< TemplateInfo > Template
TypedefInfo(SymbolID USR=SymbolID())