clang-tools 10.0.0

MDGenerator.cpp
Go to the documentation of this file.
1 //===-- MDGenerator.cpp - Markdown Generator --------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "Generators.h"
10 #include "Representation.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/Support/FileSystem.h"
13 #include "llvm/Support/Path.h"
14 #include <string>
15
16 using namespace llvm;
17
18 namespace clang {
19 namespace doc {
20
21 // Markdown generation
22
23 static std::string genItalic(const Twine &Text) {
24 return "*" + Text.str() + "*";
25 }
26
27 static std::string genEmphasis(const Twine &Text) {
28 return "**" + Text.str() + "**";
29 }
30
31 static std::string
32 genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs) {
33 std::string Buffer;
34 llvm::raw_string_ostream Stream(Buffer);
35 for (const auto &R : Refs) {
36 if (&R != Refs.begin())
37 Stream << ", ";
38 Stream << R.Name;
39 }
40 return Stream.str();
41 }
42
43 static void writeLine(const Twine &Text, raw_ostream &OS) {
44 OS << Text << "\n\n";
45 }
46
47 static void writeNewLine(raw_ostream &OS) { OS << "\n\n"; }
48
49 static void writeHeader(const Twine &Text, unsigned int Num, raw_ostream &OS) {
50 OS << std::string(Num, '#') + " " + Text << "\n\n";
51 }
52
53 static void writeFileDefinition(const Location &L, raw_ostream &OS) {
54 OS << genItalic("Defined at line " + std::to_string(L.LineNumber) + " of " +
55 L.Filename)
56 << "\n\n";
57 }
58
59 static void writeDescription(const CommentInfo &I, raw_ostream &OS) {
60 if (I.Kind == "FullComment") {
61 for (const auto &Child : I.Children)
62 writeDescription(*Child, OS);
63 } else if (I.Kind == "ParagraphComment") {
64 for (const auto &Child : I.Children)
65 writeDescription(*Child, OS);
66 writeNewLine(OS);
67 } else if (I.Kind == "BlockCommandComment") {
68 OS << genEmphasis(I.Name);
69 for (const auto &Child : I.Children)
70 writeDescription(*Child, OS);
71 } else if (I.Kind == "InlineCommandComment") {
72 OS << genEmphasis(I.Name) << " " << I.Text;
73 } else if (I.Kind == "ParamCommandComment") {
74 std::string Direction = I.Explicit ? (" " + I.Direction).str() : "";
75 OS << genEmphasis(I.ParamName) << I.Text << Direction << "\n\n";
76 } else if (I.Kind == "TParamCommandComment") {
77 std::string Direction = I.Explicit ? (" " + I.Direction).str() : "";
78 OS << genEmphasis(I.ParamName) << I.Text << Direction << "\n\n";
79 } else if (I.Kind == "VerbatimBlockComment") {
80 for (const auto &Child : I.Children)
81 writeDescription(*Child, OS);
82 } else if (I.Kind == "VerbatimBlockLineComment") {
83 OS << I.Text;
84 writeNewLine(OS);
85 } else if (I.Kind == "VerbatimLineComment") {
86 OS << I.Text;
87 writeNewLine(OS);
88 } else if (I.Kind == "HTMLStartTagComment") {
89 if (I.AttrKeys.size() != I.AttrValues.size())
90 return;
91 std::string Buffer;
92 llvm::raw_string_ostream Attrs(Buffer);
93 for (unsigned Idx = 0; Idx < I.AttrKeys.size(); ++Idx)
94 Attrs << " \"" << I.AttrKeys[Idx] << "=" << I.AttrValues[Idx] << "\"";
95
96 std::string CloseTag = I.SelfClosing ? "/>" : ">";
97 writeLine("<" + I.Name + Attrs.str() + CloseTag, OS);
98 } else if (I.Kind == "HTMLEndTagComment") {
99 writeLine("</" + I.Name + ">", OS);
100 } else if (I.Kind == "TextComment") {
101 OS << I.Text;
102 } else {
103 OS << "Unknown comment kind: " << I.Kind << ".\n\n";
104 }
105 }
106
107 static void genMarkdown(const EnumInfo &I, llvm::raw_ostream &OS) {
108 if (I.Scoped)
109 writeLine("| enum class " + I.Name + " |", OS);
110 else
111 writeLine("| enum " + I.Name + " |", OS);
112 writeLine("--", OS);
113
114 std::string Buffer;
115 llvm::raw_string_ostream Members(Buffer);
116 if (!I.Members.empty())
117 for (const auto &N : I.Members)
118 Members << "| " << N << " |\n";
119 writeLine(Members.str(), OS);
120 if (I.DefLoc)
121 writeFileDefinition(I.DefLoc.getValue(), OS);
122
123 for (const auto &C : I.Description)
124 writeDescription(C, OS);
125 }
126
127 static void genMarkdown(const FunctionInfo &I, llvm::raw_ostream &OS) {
128 std::string Buffer;
129 llvm::raw_string_ostream Stream(Buffer);
130 bool First = true;
131 for (const auto &N : I.Params) {
132 if (!First)
133 Stream << ", ";
134 Stream << N.Type.Name + " " + N.Name;
135 First = false;
136 }
137 writeHeader(I.Name, 3, OS);
138 std::string Access = getAccess(I.Access);
139 if (Access != "")
140 writeLine(genItalic(Access + " " + I.ReturnType.Type.Name + " " + I.Name +
141 "(" + Stream.str() + ")"),
142 OS);
143 else
144 writeLine(genItalic(I.ReturnType.Type.Name + " " + I.Name + "(" +
145 Stream.str() + ")"),
146 OS);
147 if (I.DefLoc)
148 writeFileDefinition(I.DefLoc.getValue(), OS);
149
150 for (const auto &C : I.Description)
151 writeDescription(C, OS);
152 }
153
154 static void genMarkdown(const NamespaceInfo &I, llvm::raw_ostream &OS) {
155 if (I.Name == "")
156 writeHeader("Global Namespace", 1, OS);
157 else
158 writeHeader("namespace " + I.Name, 1, OS);
159 writeNewLine(OS);
160
161 if (!I.Description.empty()) {
162 for (const auto &C : I.Description)
163 writeDescription(C, OS);
164 writeNewLine(OS);
165 }
166
167 if (!I.ChildNamespaces.empty()) {
168 writeHeader("Namespaces", 2, OS);
169 for (const auto &R : I.ChildNamespaces)
170 writeLine(R.Name, OS);
171 writeNewLine(OS);
172 }
173 if (!I.ChildRecords.empty()) {
174 writeHeader("Records", 2, OS);
175 for (const auto &R : I.ChildRecords)
176 writeLine(R.Name, OS);
177 writeNewLine(OS);
178 }
179 if (!I.ChildFunctions.empty()) {
180 writeHeader("Functions", 2, OS);
181 for (const auto &F : I.ChildFunctions)
182 genMarkdown(F, OS);
183 writeNewLine(OS);
184 }
185 if (!I.ChildEnums.empty()) {
186 writeHeader("Enums", 2, OS);
187 for (const auto &E : I.ChildEnums)
188 genMarkdown(E, OS);
189 writeNewLine(OS);
190 }
191 }
192
193 static void genMarkdown(const RecordInfo &I, llvm::raw_ostream &OS) {
194 writeHeader(getTagType(I.TagType) + " " + I.Name, 1, OS);
195 if (I.DefLoc)
196 writeFileDefinition(I.DefLoc.getValue(), OS);
197
198 if (!I.Description.empty()) {
199 for (const auto &C : I.Description)
200 writeDescription(C, OS);
201 writeNewLine(OS);
202 }
203
204 std::string Parents = genReferenceList(I.Parents);
205 std::string VParents = genReferenceList(I.VirtualParents);
206 if (!Parents.empty() || !VParents.empty()) {
207 if (Parents.empty())
208 writeLine("Inherits from " + VParents, OS);
209 else if (VParents.empty())
210 writeLine("Inherits from " + Parents, OS);
211 else
212 writeLine("Inherits from " + Parents + ", " + VParents, OS);
213 writeNewLine(OS);
214 }
215
216 if (!I.Members.empty()) {
217 writeHeader("Members", 2, OS);
218 for (const auto &Member : I.Members) {
219 std::string Access = getAccess(Member.Access);
220 if (Access != "")
221 writeLine(Access + " " + Member.Type.Name + " " + Member.Name, OS);
222 else
223 writeLine(Member.Type.Name + " " + Member.Name, OS);
224 }
225 writeNewLine(OS);
226 }
227
228 if (!I.ChildRecords.empty()) {
229 writeHeader("Records", 2, OS);
230 for (const auto &R : I.ChildRecords)
231 writeLine(R.Name, OS);
232 writeNewLine(OS);
233 }
234 if (!I.ChildFunctions.empty()) {
235 writeHeader("Functions", 2, OS);
236 for (const auto &F : I.ChildFunctions)
237 genMarkdown(F, OS);
238 writeNewLine(OS);
239 }
240 if (!I.ChildEnums.empty()) {
241 writeHeader("Enums", 2, OS);
242 for (const auto &E : I.ChildEnums)
243 genMarkdown(E, OS);
244 writeNewLine(OS);
245 }
246 }
247
248 /// Generator for Markdown documentation.
249 class MDGenerator : public Generator {
250 public:
251 static const char *Format;
252
253 llvm::Error generateDocForInfo(Info *I, llvm::raw_ostream &OS,
254 const ClangDocContext &CDCtx) override;
255 };
256
257 const char *MDGenerator::Format = "md";
258
259 llvm::Error MDGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
260 const ClangDocContext &CDCtx) {
261 switch (I->IT) {
262 case InfoType::IT_namespace:
263 genMarkdown(*static_cast<clang::doc::NamespaceInfo *>(I), OS);
264 break;
265 case InfoType::IT_record:
266 genMarkdown(*static_cast<clang::doc::RecordInfo *>(I), OS);
267 break;
268 case InfoType::IT_enum:
269 genMarkdown(*static_cast<clang::doc::EnumInfo *>(I), OS);
270 break;
271 case InfoType::IT_function:
272 genMarkdown(*static_cast<clang::doc::FunctionInfo *>(I), OS);
273 break;
274 case InfoType::IT_default:
275 return createStringError(llvm::inconvertibleErrorCode(),
276 "unexpected InfoType");
277 }
278 return llvm::Error::success();
279 }
280
281 static GeneratorRegistry::Add<MDGenerator> MD(MDGenerator::Format,
282 "Generator for MD output.");
283
284 // This anchor is used to force the linker to link in the generated object file
285 // and thus register the generator.
286 volatile int MDGeneratorAnchorSource = 0;
287
288 } // namespace doc
289 } // namespace clang
clang::doc::writeHeader
static void writeHeader(const Twine &Text, unsigned int Num, raw_ostream &OS)
Definition: MDGenerator.cpp:49
Representation.h
llvm
Some operations such as code completion produce a set of candidates.
Definition: YAMLGenerator.cpp:28
clang::doc::genReferenceList
static std::string genReferenceList(const llvm::SmallVectorImpl< Reference > &Refs)
Definition: MDGenerator.cpp:32
clang::doc::TypeInfo::Type
Reference Type
Definition: Representation.h:163
clang::doc::writeDescription
static void writeDescription(const CommentInfo &I, raw_ostream &OS)
Definition: MDGenerator.cpp:59
clang::doc::Reference::Name
SmallString< 16 > Name
Definition: Representation.h:139
clang::doc::SymbolInfo::DefLoc
llvm::Optional< Location > DefLoc
Definition: Representation.h:301
clang::doc::RecordInfo::ChildFunctions
std::vector< FunctionInfo > ChildFunctions
Definition: Representation.h:357
clang::doc::NamespaceInfo::ChildFunctions
std::vector< FunctionInfo > ChildFunctions
Definition: Representation.h:287
Generators.h
clang::doc::NamespaceInfo::ChildEnums
std::vector< EnumInfo > ChildEnums
Definition: Representation.h:288
clang::doc::EnumInfo::Scoped
bool Scoped
Definition: Representation.h:384
clang::doc::genMarkdown
static void genMarkdown(const RecordInfo &I, llvm::raw_ostream &OS)
Definition: MDGenerator.cpp:193
clang::doc::RecordInfo::ChildRecords
std::vector< Reference > ChildRecords
Definition: Representation.h:356
clang::doc::RecordInfo::VirtualParents
llvm::SmallVector< Reference, 4 > VirtualParents
Definition: Representation.h:347
clang::doc::FunctionInfo
Definition: Representation.h:307
clang::doc::CommentInfo::SelfClosing
bool SelfClosing
Definition: Representation.h:102
clang::doc::getAccess
std::string getAccess(AccessSpecifier AS)
Definition: Generators.cpp:30
clang::doc::FunctionInfo::Params
llvm::SmallVector< FieldTypeInfo, 4 > Params
Definition: Representation.h:316
clang::doc::genEmphasis
static std::string genEmphasis(const Twine &Text)
Definition: MDGenerator.cpp:27
clang::doc::EnumInfo::Members
llvm::SmallVector< SmallString< 16 >, 4 > Members
Definition: Representation.h:386
clang::doc::CommentInfo::AttrValues
llvm::SmallVector< SmallString< 16 >, 4 > AttrValues
Definition: Representation.h:108
clang::doc::Generator
Definition: Generators.h:24
clang::doc::Info::Description
std::vector< CommentInfo > Description
Definition: Representation.h:256
clang::doc::NamespaceInfo
Definition: Representation.h:271
clang::doc::RecordInfo
Definition: Representation.h:327
clang::doc::getTagType
std::string getTagType(TagTypeKind AS)
Definition: Generators.cpp:44
clang::doc::Info::Name
SmallString< 16 > Name
Definition: Representation.h:253
clang::doc::CommentInfo::Explicit
bool Explicit
Definition: Representation.h:103
clang::doc::Info
A base struct for Infos.
Definition: Representation.h:237
clang::doc::FunctionInfo::Access
AccessSpecifier Access
Definition: Representation.h:321
clang::doc::writeNewLine
static void writeNewLine(raw_ostream &OS)
Definition: MDGenerator.cpp:47
clang::doc::RecordInfo::Parents
llvm::SmallVector< Reference, 4 > Parents
Definition: Representation.h:343
clang::doc::writeLine
static void writeLine(const Twine &Text, raw_ostream &OS)
Definition: MDGenerator.cpp:43
clang::doc::MDGenerator::Format
static const char * Format
Definition: MDGenerator.cpp:251
clang::doc::Location
Definition: Representation.h:209
clang::doc::writeFileDefinition
static void writeFileDefinition(const Location &L, raw_ostream &OS)
Definition: MDGenerator.cpp:53
clang::doc::MDGeneratorAnchorSource
volatile int MDGeneratorAnchorSource
Definition: MDGenerator.cpp:286
clang::doc::CommentInfo::ParamName
SmallString< 16 > ParamName
Definition: Representation.h:100
clang::doc::RecordInfo::TagType
TagTypeKind TagType
Definition: Representation.h:337
clang::doc::EnumInfo
Definition: Representation.h:378
clang::doc::CommentInfo::AttrKeys
llvm::SmallVector< SmallString< 16 >, 4 > AttrKeys
Definition: Representation.h:106
clang::doc::CommentInfo::Name
SmallString< 16 > Name
Definition: Representation.h:98
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::doc::MD
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
clang::doc::NamespaceInfo::ChildNamespaces
std::vector< Reference > ChildNamespaces
Definition: Representation.h:285
clang::doc::NamespaceInfo::ChildRecords
std::vector< Reference > ChildRecords
Definition: Representation.h:286
clang::doc::MDGenerator
Generator for Markdown documentation.
Definition: MDGenerator.cpp:249
clang::doc::Location::Filename
SmallString< 32 > Filename
Definition: Representation.h:232
clang::doc::CommentInfo::Direction
SmallString< 8 > Direction
Definition: Representation.h:99
clang::doc::Info::IT
const InfoType IT
Definition: Representation.h:252
clang::doc::RecordInfo::ChildEnums
std::vector< EnumInfo > ChildEnums
Definition: Representation.h:358
clang::doc::FunctionInfo::ReturnType
TypeInfo ReturnType
Definition: Representation.h:315
E
const Expr * E
Definition: AvoidBindCheck.cpp:82
clang::doc::RecordInfo::Members
llvm::SmallVector< MemberTypeInfo, 4 > Members
Definition: Representation.h:342
clang::doc::CommentInfo::Kind
SmallString< 16 > Kind
Definition: Representation.h:92
Refs
RefSlab Refs
Definition: SymbolCollectorTests.cpp:296
clang::doc::CommentInfo::Children
std::vector< std::unique_ptr< CommentInfo > > Children
Definition: Representation.h:112
clang::doc::CommentInfo::Text
SmallString< 64 > Text
Definition: Representation.h:97
clang::doc::ClangDocContext
Definition: Representation.h:414
clang::doc::genItalic
static std::string genItalic(const Twine &Text)
Definition: MDGenerator.cpp:23
clang::doc::CommentInfo
Definition: Representation.h:46
clang::doc::Location::LineNumber
int LineNumber
Definition: Representation.h:231