clang-tools 8.0.0

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