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