11#include "llvm/ADT/ArrayRef.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/Support/FileSystem.h"
14#include "llvm/Support/FormatVariadic.h"
15#include "llvm/Support/Path.h"
16#include "llvm/Support/raw_ostream.h"
25 return "*" + Text.str() +
"*";
29 return "**" + Text.str() +
"**";
34 llvm::raw_string_ostream Stream(Buffer);
35 for (
const auto &R : Refs) {
36 if (&R != Refs.begin())
43static void writeLine(
const Twine &Text, raw_ostream &OS) {
49static void writeHeader(
const Twine &Text,
unsigned int Num, raw_ostream &OS) {
50 OS << std::string(Num,
'#') +
" " + Text <<
"\n\n";
57 OS <<
"*Defined at " << L.
Filename <<
"#"
61 OS << formatv(
"*Defined at [#{0}{1}{2}](#{0}{1}{3})*",
83 for (
const auto &C : Comments)
84 writeTableSafeComment(C);
95 void insertSeparator() {
98 if (NeedsParagraphBreak) {
100 NeedsParagraphBreak =
false;
107 void writeTableSafeComment(
const CommentInfo &I) {
109 case CommentKind::CK_FullComment:
110 for (
const auto &Child : I.
Children)
111 writeTableSafeComment(Child);
114 case CommentKind::CK_ParagraphComment:
115 for (
const auto &Child : I.
Children)
116 writeTableSafeComment(Child);
118 NeedsParagraphBreak =
true;
121 case CommentKind::CK_TextComment:
122 if (!I.
Text.empty()) {
131 for (
const auto &Child : I.
Children)
132 writeTableSafeComment(Child);
137 llvm::raw_ostream &OS;
138 bool Started =
false;
139 bool NeedsParagraphBreak =
false;
144 const std::optional<Location> &DefLoc) {
152 for (
const auto &Child : I.
Children)
157 for (
const auto &Child : I.
Children)
164 for (
const auto &Child : I.
Children)
176 for (
const auto &Child : I.
Children)
182 for (
const auto &Child : I.
Children)
196 llvm::raw_string_ostream Attrs(Buffer);
197 for (
unsigned Idx = 0; Idx < I.
AttrKeys.size(); ++Idx)
214 OS <<
"Unknown comment kind: " <<
static_cast<int>(I.
Kind) <<
".\n\n";
220 llvm::raw_ostream &OS) {
223 llvm::sys::path::native(Path, llvm::sys::path::Style::posix);
224 llvm::sys::path::append(Path, llvm::sys::path::Style::posix,
226 OS <<
"[" << R.
Name <<
"](" << Path <<
")";
230 llvm::raw_ostream &OS) {
234 OS << (I.
Name.empty() ?
"(unnamed)" : StringRef(I.
Name)) <<
" ";
236 OS <<
": " << I.
BaseType->Type.QualName <<
" ";
240 OS <<
"| Name | Value |";
242 bool HasComments =
false;
243 for (
const auto &Member : I.
Members) {
244 if (!Member.Description.empty()) {
254 for (
const auto &N : I.
Members) {
255 OS <<
"| " << N.Name <<
" ";
256 if (!N.Value.empty())
257 OS <<
"| " << N.Value <<
" ";
261 CommentWriter.
write(N.Description);
276 llvm::raw_ostream &OS) {
278 llvm::raw_string_ostream Stream(Buffer);
280 for (
const auto &N : I.
Params) {
283 Stream << N.Type.QualName +
" " + N.Name;
287 StringRef Access = getAccessSpelling(I.
Access);
291 "(" + Twine(Stream.str()) +
")"),
301 llvm::raw_ostream &OS) {
351 llvm::raw_ostream &OS) {
364 if (!Parents.empty() || !VParents.empty()) {
366 writeLine(
"Inherits from " + VParents, OS);
367 else if (VParents.empty())
368 writeLine(
"Inherits from " + Parents, OS);
370 writeLine(
"Inherits from " + Parents +
", " + VParents, OS);
376 for (
const auto &Member : I.
Members) {
377 StringRef Access = getAccessSpelling(Member.Access);
378 writeLine(Twine(Access) + (Access.empty() ?
"" :
" ") +
379 (Member.IsStatic ?
"static " :
"") +
380 Member.Type.Name.str() +
" " + Member.Name.str(),
407 llvm::raw_ostream &OS) {
414 OS <<
"##" << std::string(Level,
'#') <<
" ";
420 std::error_code FileErr;
421 llvm::SmallString<128> FilePath;
423 llvm::sys::path::append(FilePath,
"all_files.md");
424 llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_Text);
426 return llvm::createStringError(llvm::inconvertibleErrorCode(),
427 "error creating index file: " +
437 for (
const auto *C : Children)
440 return llvm::Error::success();
444 std::error_code FileErr;
445 llvm::SmallString<128> FilePath;
447 llvm::sys::path::append(FilePath,
"index.md");
448 llvm::raw_fd_ostream OS(FilePath, FileErr, llvm::sys::fs::OF_Text);
450 return llvm::createStringError(llvm::inconvertibleErrorCode(),
451 "error creating index file: " +
454 OS <<
"# " << CDCtx.
ProjectName <<
" C/C++ Reference\n\n";
456 for (
const auto *C : Children) {
457 if (!C->Children.empty()) {
459 switch (C->RefType) {
487 OS <<
"* " << Type <<
": [" << C->Name <<
"](";
488 if (!C->Path.empty())
489 OS << C->Path <<
"/";
490 OS << C->Name <<
")\n";
493 return llvm::Error::success();
500 static StringRef Format;
502 llvm::Error generateDocumentation(StringRef RootDir,
503 llvm::StringMap<Info *> Infos,
504 const ClangDocContext &CDCtx,
505 std::string DirName)
override;
506 llvm::Error createResources(ClangDocContext &CDCtx)
override;
507 llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS,
508 const ClangDocContext &CDCtx)
override;
512StringRef MDGenerator::Format =
"md";
514llvm::Error MDGenerator::generateDocumentation(StringRef RootDir,
515 llvm::StringMap<Info *> Infos,
517 std::string DirName) {
519 llvm::StringSet<> CreatedDirs;
522 llvm::StringMap<std::vector<Info *>> FileToInfos;
523 for (
const auto &Group : Infos) {
526 llvm::SmallString<128>
Path;
527 llvm::sys::path::native(RootDir, Path);
528 llvm::sys::path::append(Path,
Info->getRelativeFilePath(
""));
529 if (!CreatedDirs.contains(Path)) {
530 if (std::error_code Err = llvm::sys::fs::create_directories(Path);
531 Err != std::error_code()) {
532 return llvm::createStringError(Err,
"Failed to create directory '%s'.",
535 CreatedDirs.insert(Path);
538 llvm::sys::path::append(Path,
Info->getFileBaseName() +
".md");
539 FileToInfos[
Path].push_back(Info);
542 for (
const auto &Group : FileToInfos) {
543 std::error_code FileErr;
544 llvm::raw_fd_ostream InfoOS(Group.getKey(), FileErr,
545 llvm::sys::fs::OF_Text);
547 return llvm::createStringError(FileErr,
"Error opening file '%s'",
548 Group.getKey().str().c_str());
551 for (
const auto &Info : Group.getValue()) {
552 if (llvm::Error Err = generateDocForInfo(Info, InfoOS, CDCtx)) {
558 return llvm::Error::success();
561llvm::Error MDGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
562 const ClangDocContext &CDCtx) {
564 case InfoType::IT_namespace:
567 case InfoType::IT_record:
570 case InfoType::IT_enum:
573 case InfoType::IT_function:
576 case InfoType::IT_typedef:
579 case InfoType::IT_concept:
580 case InfoType::IT_variable:
581 case InfoType::IT_friend:
583 case InfoType::IT_default:
584 return createStringError(llvm::inconvertibleErrorCode(),
585 "unexpected InfoType");
587 return llvm::Error::success();
590llvm::Error MDGenerator::createResources(ClangDocContext &CDCtx) {
601 return llvm::Error::success();
604static GeneratorRegistry::Add<MDGenerator>
MD(MDGenerator::Format,
605 "Generator for MD output.");
static std::string genItalic(const Twine &Text)
static std::string genEmphasis(const Twine &Text)
static void writeSourceFileRef(const ClangDocContext &CDCtx, const Location &L, raw_ostream &OS)
static llvm::Error genIndex(ClangDocContext &CDCtx)
static void writeLine(const Twine &Text, raw_ostream &OS)
static std::string genReferenceList(llvm::ArrayRef< Reference > Refs)
static void writeNameLink(const StringRef &CurrentPath, const Reference &R, llvm::raw_ostream &OS)
static void genMarkdown(const ClangDocContext &CDCtx, const EnumInfo &I, llvm::raw_ostream &OS)
static void serializeReference(llvm::raw_fd_ostream &OS, const Index &I, int Level)
static llvm::Error serializeIndex(ClangDocContext &CDCtx)
static void writeDescription(const CommentInfo &I, raw_ostream &OS)
static void writeNewLine(raw_ostream &OS)
static void writeHeader(const Twine &Text, unsigned int Num, raw_ostream &OS)
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
static void maybeWriteSourceFileRef(llvm::raw_ostream &OS, const ClangDocContext &CDCtx, const std::optional< Location > &DefLoc)
@ Info
An information message.
std::string Path
A typedef to represent a file path.
@ CK_InlineCommandComment
@ CK_VerbatimBlockLineComment
@ CK_VerbatimBlockComment
@ CK_TParamCommandComment
llvm::simple_ilist< InfoNode< T > > DocList
llvm::StringRef getTagType(TagTypeKind AS)
volatile int MDGeneratorAnchorSource
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Some operations such as code completion produce a set of candidates.
std::optional< std::string > RepositoryUrl
std::optional< std::string > RepositoryLinePrefix
llvm::ArrayRef< EnumValueInfo > Members
std::optional< TypeInfo > BaseType
llvm::ArrayRef< FieldTypeInfo > Params
std::vector< const Index * > getSortedChildren() const
StringRef getRelativeFilePath(const StringRef &CurrentPath) const
Returns the file path for this Info relative to CurrentPath.
DocList< CommentInfo > Description
llvm::ArrayRef< Reference > VirtualParents
llvm::ArrayRef< Reference > Parents
llvm::ArrayRef< MemberTypeInfo > Members
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< FunctionInfo > Functions
DocList< Reference > Namespaces
std::optional< Location > DefLoc