@@ -50,10 +50,20 @@ static void writeHeader(const Twine &Text, unsigned int Num, raw_ostream &OS) {
50
50
OS << std::string (Num, ' #' ) + " " + Text << " \n\n " ;
51
51
}
52
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 " ;
53
+ static void writeFileDefinition (const ClangDocContext &CDCtx, const Location &L,
54
+ raw_ostream &OS) {
55
+
56
+ if (!CDCtx.RepositoryUrl ) {
57
+ OS << " *Defined at " << L.Filename << " #" << std::to_string (L.LineNumber )
58
+ << " *" ;
59
+ } else {
60
+ OS << " *Defined at [" << L.Filename << " #" << std::to_string (L.LineNumber )
61
+ << " ](" << StringRef{CDCtx.RepositoryUrl .getValue ()}
62
+ << llvm::sys::path::relative_path (L.Filename ) << " #"
63
+ << std::to_string (L.LineNumber ) << " )"
64
+ << " *" ;
65
+ }
66
+ OS << " \n\n " ;
57
67
}
58
68
59
69
static void writeDescription (const CommentInfo &I, raw_ostream &OS) {
@@ -104,7 +114,16 @@ static void writeDescription(const CommentInfo &I, raw_ostream &OS) {
104
114
}
105
115
}
106
116
107
- static void genMarkdown (const EnumInfo &I, llvm::raw_ostream &OS) {
117
+ static void writeNameLink (const StringRef &CurrentPath, const Reference &R,
118
+ llvm::raw_ostream &OS) {
119
+
120
+ llvm::SmallString<64 > Path = R.getRelativeFilePath (CurrentPath);
121
+ llvm::sys::path::append (Path, R.getFileBaseName () + " .md" );
122
+ OS << " [" << R.Name << " ](" << Path << " )" ;
123
+ }
124
+
125
+ static void genMarkdown (const ClangDocContext &CDCtx, const EnumInfo &I,
126
+ llvm::raw_ostream &OS) {
108
127
if (I.Scoped )
109
128
writeLine (" | enum class " + I.Name + " |" , OS);
110
129
else
@@ -118,13 +137,14 @@ static void genMarkdown(const EnumInfo &I, llvm::raw_ostream &OS) {
118
137
Members << " | " << N << " |\n " ;
119
138
writeLine (Members.str (), OS);
120
139
if (I.DefLoc )
121
- writeFileDefinition (I.DefLoc .getValue (), OS);
140
+ writeFileDefinition (CDCtx, I.DefLoc .getValue (), OS);
122
141
123
142
for (const auto &C : I.Description )
124
143
writeDescription (C, OS);
125
144
}
126
145
127
- static void genMarkdown (const FunctionInfo &I, llvm::raw_ostream &OS) {
146
+ static void genMarkdown (const ClangDocContext &CDCtx, const FunctionInfo &I,
147
+ llvm::raw_ostream &OS) {
128
148
std::string Buffer;
129
149
llvm::raw_string_ostream Stream (Buffer);
130
150
bool First = true ;
@@ -145,13 +165,14 @@ static void genMarkdown(const FunctionInfo &I, llvm::raw_ostream &OS) {
145
165
Stream.str () + " )" ),
146
166
OS);
147
167
if (I.DefLoc )
148
- writeFileDefinition (I.DefLoc .getValue (), OS);
168
+ writeFileDefinition (CDCtx, I.DefLoc .getValue (), OS);
149
169
150
170
for (const auto &C : I.Description )
151
171
writeDescription (C, OS);
152
172
}
153
173
154
- static void genMarkdown (const NamespaceInfo &I, llvm::raw_ostream &OS) {
174
+ static void genMarkdown (const ClangDocContext &CDCtx, const NamespaceInfo &I,
175
+ llvm::raw_ostream &OS) {
155
176
if (I.Name == " " )
156
177
writeHeader (" Global Namespace" , 1 , OS);
157
178
else
@@ -164,36 +185,47 @@ static void genMarkdown(const NamespaceInfo &I, llvm::raw_ostream &OS) {
164
185
writeNewLine (OS);
165
186
}
166
187
188
+ llvm::SmallString<64 > BasePath = I.getRelativeFilePath (" " );
189
+
167
190
if (!I.ChildNamespaces .empty ()) {
168
191
writeHeader (" Namespaces" , 2 , OS);
169
- for (const auto &R : I.ChildNamespaces )
170
- writeLine (R.Name , OS);
192
+ for (const auto &R : I.ChildNamespaces ) {
193
+ OS << " * " ;
194
+ writeNameLink (BasePath, R, OS);
195
+ OS << " \n " ;
196
+ }
171
197
writeNewLine (OS);
172
198
}
199
+
173
200
if (!I.ChildRecords .empty ()) {
174
201
writeHeader (" Records" , 2 , OS);
175
- for (const auto &R : I.ChildRecords )
176
- writeLine (R.Name , OS);
202
+ for (const auto &R : I.ChildRecords ) {
203
+ OS << " * " ;
204
+ writeNameLink (BasePath, R, OS);
205
+ OS << " \n " ;
206
+ }
177
207
writeNewLine (OS);
178
208
}
209
+
179
210
if (!I.ChildFunctions .empty ()) {
180
211
writeHeader (" Functions" , 2 , OS);
181
212
for (const auto &F : I.ChildFunctions )
182
- genMarkdown (F, OS);
213
+ genMarkdown (CDCtx, F, OS);
183
214
writeNewLine (OS);
184
215
}
185
216
if (!I.ChildEnums .empty ()) {
186
217
writeHeader (" Enums" , 2 , OS);
187
218
for (const auto &E : I.ChildEnums )
188
- genMarkdown (E, OS);
219
+ genMarkdown (CDCtx, E, OS);
189
220
writeNewLine (OS);
190
221
}
191
222
}
192
223
193
- static void genMarkdown (const RecordInfo &I, llvm::raw_ostream &OS) {
224
+ static void genMarkdown (const ClangDocContext &CDCtx, const RecordInfo &I,
225
+ llvm::raw_ostream &OS) {
194
226
writeHeader (getTagType (I.TagType ) + " " + I.Name , 1 , OS);
195
227
if (I.DefLoc )
196
- writeFileDefinition (I.DefLoc .getValue (), OS);
228
+ writeFileDefinition (CDCtx, I.DefLoc .getValue (), OS);
197
229
198
230
if (!I.Description .empty ()) {
199
231
for (const auto &C : I.Description )
@@ -234,24 +266,94 @@ static void genMarkdown(const RecordInfo &I, llvm::raw_ostream &OS) {
234
266
if (!I.ChildFunctions .empty ()) {
235
267
writeHeader (" Functions" , 2 , OS);
236
268
for (const auto &F : I.ChildFunctions )
237
- genMarkdown (F, OS);
269
+ genMarkdown (CDCtx, F, OS);
238
270
writeNewLine (OS);
239
271
}
240
272
if (!I.ChildEnums .empty ()) {
241
273
writeHeader (" Enums" , 2 , OS);
242
274
for (const auto &E : I.ChildEnums )
243
- genMarkdown (E, OS);
275
+ genMarkdown (CDCtx, E, OS);
244
276
writeNewLine (OS);
245
277
}
246
278
}
247
279
280
+ static void serializeReference (llvm::raw_fd_ostream &OS, Index &I, int Level) {
281
+ // Write out the heading level starting at ##
282
+ OS << " ##" << std::string (Level, ' #' ) << " " ;
283
+ writeNameLink (" " , I, OS);
284
+ OS << " \n " ;
285
+ }
286
+
287
+ static llvm::Error serializeIndex (ClangDocContext &CDCtx) {
288
+ std::error_code FileErr;
289
+ llvm::SmallString<128 > FilePath;
290
+ llvm::sys::path::native (CDCtx.OutDirectory , FilePath);
291
+ llvm::sys::path::append (FilePath, " all_files.md" );
292
+ llvm::raw_fd_ostream OS (FilePath, FileErr, llvm::sys::fs::OF_None);
293
+ if (FileErr)
294
+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
295
+ " error creating index file: " +
296
+ FileErr.message ());
297
+
298
+ CDCtx.Idx .sort ();
299
+ OS << " # All Files" ;
300
+ if (!CDCtx.ProjectName .empty ())
301
+ OS << " for " << CDCtx.ProjectName ;
302
+ OS << " \n\n " ;
303
+
304
+ for (auto C : CDCtx.Idx .Children )
305
+ serializeReference (OS, C, 0 );
306
+
307
+ return llvm::Error::success ();
308
+ }
309
+
310
+ static llvm::Error genIndex (ClangDocContext &CDCtx) {
311
+ std::error_code FileErr;
312
+ llvm::SmallString<128 > FilePath;
313
+ llvm::sys::path::native (CDCtx.OutDirectory , FilePath);
314
+ llvm::sys::path::append (FilePath, " index.md" );
315
+ llvm::raw_fd_ostream OS (FilePath, FileErr, llvm::sys::fs::OF_None);
316
+ if (FileErr)
317
+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
318
+ " error creating index file: " +
319
+ FileErr.message ());
320
+ CDCtx.Idx .sort ();
321
+ OS << " # " << CDCtx.ProjectName << " C/C++ Reference\n\n " ;
322
+ for (auto C : CDCtx.Idx .Children ) {
323
+ if (!C.Children .empty ()) {
324
+ const char *Type;
325
+ switch (C.RefType ) {
326
+ case InfoType::IT_namespace:
327
+ Type = " Namespace" ;
328
+ break ;
329
+ case InfoType::IT_record:
330
+ Type = " Type" ;
331
+ break ;
332
+ case InfoType::IT_enum:
333
+ Type = " Enum" ;
334
+ break ;
335
+ case InfoType::IT_function:
336
+ Type = " Function" ;
337
+ break ;
338
+ case InfoType::IT_default:
339
+ Type = " Other" ;
340
+ }
341
+ OS << " * " << Type << " : [" << C.Name << " ](" ;
342
+ if (!C.Path .empty ())
343
+ OS << C.Path << " /" ;
344
+ OS << C.Name << " )\n " ;
345
+ }
346
+ }
347
+ return llvm::Error::success ();
348
+ }
248
349
// / Generator for Markdown documentation.
249
350
class MDGenerator : public Generator {
250
351
public:
251
352
static const char *Format;
252
353
253
354
llvm::Error generateDocForInfo (Info *I, llvm::raw_ostream &OS,
254
355
const ClangDocContext &CDCtx) override ;
356
+ llvm::Error createResources (ClangDocContext &CDCtx) override ;
255
357
};
256
358
257
359
const char *MDGenerator::Format = " md" ;
@@ -260,16 +362,16 @@ llvm::Error MDGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
260
362
const ClangDocContext &CDCtx) {
261
363
switch (I->IT ) {
262
364
case InfoType::IT_namespace:
263
- genMarkdown (*static_cast <clang::doc::NamespaceInfo *>(I), OS);
365
+ genMarkdown (CDCtx, *static_cast <clang::doc::NamespaceInfo *>(I), OS);
264
366
break ;
265
367
case InfoType::IT_record:
266
- genMarkdown (*static_cast <clang::doc::RecordInfo *>(I), OS);
368
+ genMarkdown (CDCtx, *static_cast <clang::doc::RecordInfo *>(I), OS);
267
369
break ;
268
370
case InfoType::IT_enum:
269
- genMarkdown (*static_cast <clang::doc::EnumInfo *>(I), OS);
371
+ genMarkdown (CDCtx, *static_cast <clang::doc::EnumInfo *>(I), OS);
270
372
break ;
271
373
case InfoType::IT_function:
272
- genMarkdown (*static_cast <clang::doc::FunctionInfo *>(I), OS);
374
+ genMarkdown (CDCtx, *static_cast <clang::doc::FunctionInfo *>(I), OS);
273
375
break ;
274
376
case InfoType::IT_default:
275
377
return createStringError (llvm::inconvertibleErrorCode (),
@@ -278,11 +380,25 @@ llvm::Error MDGenerator::generateDocForInfo(Info *I, llvm::raw_ostream &OS,
278
380
return llvm::Error::success ();
279
381
}
280
382
383
+ llvm::Error MDGenerator::createResources (ClangDocContext &CDCtx) {
384
+ // Write an all_files.md
385
+ auto Err = serializeIndex (CDCtx);
386
+ if (Err)
387
+ return Err;
388
+
389
+ // Generate the index page.
390
+ Err = genIndex (CDCtx);
391
+ if (Err)
392
+ return Err;
393
+
394
+ return llvm::Error::success ();
395
+ }
396
+
281
397
static GeneratorRegistry::Add<MDGenerator> MD (MDGenerator::Format,
282
398
" Generator for MD output." );
283
399
284
- // This anchor is used to force the linker to link in the generated object file
285
- // and thus register the generator.
400
+ // This anchor is used to force the linker to link in the generated object
401
+ // file and thus register the generator.
286
402
volatile int MDGeneratorAnchorSource = 0 ;
287
403
288
404
} // namespace doc
0 commit comments