OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * To use it, from this directory, run: | 6 * To use it, from this directory, run: |
7 * | 7 * |
8 * $ ./dartdoc <path to .dart file> | 8 * $ ./dartdoc <path to .dart file> |
9 * | 9 * |
10 * This will create a "docs" directory with the docs for your libraries. To | 10 * This will create a "docs" directory with the docs for your libraries. To |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 * The title used for the overall generated output. Set this to change it. | 114 * The title used for the overall generated output. Set this to change it. |
115 */ | 115 */ |
116 String mainTitle = 'Dart Documentation'; | 116 String mainTitle = 'Dart Documentation'; |
117 | 117 |
118 /** | 118 /** |
119 * The URL that the Dart logo links to. Defaults "index.html", the main | 119 * The URL that the Dart logo links to. Defaults "index.html", the main |
120 * page for the generated docs, but can be anything. | 120 * page for the generated docs, but can be anything. |
121 */ | 121 */ |
122 String mainUrl = 'index.html'; | 122 String mainUrl = 'index.html'; |
123 | 123 |
| 124 /** |
| 125 * The Google Custom Search ID that should be used for the search box. If |
| 126 * this is `null` then no search box will be shown. |
| 127 */ |
| 128 String searchEngineId = null; |
| 129 |
| 130 /* The URL that the embedded search results should be displayed on. */ |
| 131 String searchResultsUrl = 'results.html'; |
| 132 |
124 /** Set this to add footer text to each generated page. */ | 133 /** Set this to add footer text to each generated page. */ |
125 String footerText = ''; | 134 String footerText = ''; |
126 | 135 |
127 CommentMap _comments; | 136 CommentMap _comments; |
128 | 137 |
129 /** The library that we're currently generating docs for. */ | 138 /** The library that we're currently generating docs for. */ |
130 Library _currentLibrary; | 139 Library _currentLibrary; |
131 | 140 |
132 /** The type that we're currently generating docs for. */ | 141 /** The type that we're currently generating docs for. */ |
133 Type _currentType; | 142 Type _currentType; |
(...skipping 16 matching lines...) Expand all Loading... |
150 // Patch in support for [:...:]-style code to the markdown parser. | 159 // Patch in support for [:...:]-style code to the markdown parser. |
151 // TODO(rnystrom): Markdown already has syntax for this. Phase this out? | 160 // TODO(rnystrom): Markdown already has syntax for this. Phase this out? |
152 md.InlineParser.syntaxes.insertRange(0, 1, | 161 md.InlineParser.syntaxes.insertRange(0, 1, |
153 new md.CodeSyntax(@'\[\:((?:.|\n)*?)\:\]')); | 162 new md.CodeSyntax(@'\[\:((?:.|\n)*?)\:\]')); |
154 | 163 |
155 md.setImplicitLinkResolver((name) => resolveNameReference(name, | 164 md.setImplicitLinkResolver((name) => resolveNameReference(name, |
156 library: _currentLibrary, type: _currentType, | 165 library: _currentLibrary, type: _currentType, |
157 member: _currentMember)); | 166 member: _currentMember)); |
158 } | 167 } |
159 | 168 |
160 document(String entrypoint) { | 169 void document(String entrypoint) { |
161 var oldDietParse = options.dietParse; | 170 var oldDietParse = options.dietParse; |
162 try { | 171 try { |
163 options.dietParse = true; | 172 options.dietParse = true; |
164 | 173 |
165 // Handle the built-in entrypoints. | 174 // Handle the built-in entrypoints. |
166 switch (entrypoint) { | 175 switch (entrypoint) { |
167 case 'corelib': | 176 case 'corelib': |
168 world.getOrAddLibrary('dart:core'); | 177 world.getOrAddLibrary('dart:core'); |
169 world.getOrAddLibrary('dart:coreimpl'); | 178 world.getOrAddLibrary('dart:coreimpl'); |
170 world.getOrAddLibrary('dart:json'); | 179 world.getOrAddLibrary('dart:json'); |
(...skipping 29 matching lines...) Expand all Loading... |
200 | 209 |
201 docIndex(); | 210 docIndex(); |
202 for (final library in world.libraries.getValues()) { | 211 for (final library in world.libraries.getValues()) { |
203 docLibrary(library); | 212 docLibrary(library); |
204 } | 213 } |
205 } finally { | 214 } finally { |
206 options.dietParse = oldDietParse; | 215 options.dietParse = oldDietParse; |
207 } | 216 } |
208 } | 217 } |
209 | 218 |
210 startFile(String path) { | 219 void startFile(String path) { |
211 _filePath = path; | 220 _filePath = path; |
212 _file = new StringBuffer(); | 221 _file = new StringBuffer(); |
213 } | 222 } |
214 | 223 |
215 endFile() { | 224 void endFile() { |
216 String outPath = '$_outdir/$_filePath'; | 225 String outPath = '$_outdir/$_filePath'; |
217 world.files.createDirectory(dirname(outPath), recursive: true); | 226 world.files.createDirectory(dirname(outPath), recursive: true); |
218 | 227 |
219 world.files.writeString(outPath, _file.toString()); | 228 world.files.writeString(outPath, _file.toString()); |
220 _filePath = null; | 229 _filePath = null; |
221 _file = null; | 230 _file = null; |
222 } | 231 } |
223 | 232 |
224 write(String s) { | 233 void write(String s) { |
225 _file.add(s); | 234 _file.add(s); |
226 } | 235 } |
227 | 236 |
228 writeln(String s) { | 237 void writeln(String s) { |
229 write(s); | 238 write(s); |
230 write('\n'); | 239 write('\n'); |
231 } | 240 } |
232 | 241 |
233 /** | 242 /** |
234 * Writes the page header with the given [title] and [breadcrumbs]. The | 243 * Writes the page header with the given [title] and [breadcrumbs]. The |
235 * breadcrumbs are an interleaved list of links and titles. If a link is null, | 244 * breadcrumbs are an interleaved list of links and titles. If a link is null, |
236 * then no link will be generated. For example, given: | 245 * then no link will be generated. For example, given: |
237 * | 246 * |
238 * ['foo', 'foo.html', 'bar', null] | 247 * ['foo', 'foo.html', 'bar', null] |
239 * | 248 * |
240 * It will output: | 249 * It will output: |
241 * | 250 * |
242 * <a href="foo.html">foo</a> › bar | 251 * <a href="foo.html">foo</a> › bar |
243 */ | 252 */ |
244 writeHeader(String title, List<String> breadcrumbs) { | 253 void writeHeader(String title, List<String> breadcrumbs) { |
245 write( | 254 write( |
246 ''' | 255 ''' |
247 <!DOCTYPE html> | 256 <!DOCTYPE html> |
248 <html> | 257 <html> |
249 <head> | 258 <head> |
250 '''); | 259 '''); |
251 writeHeadContents(title); | 260 writeHeadContents(title); |
252 | 261 |
253 // Add data attributes describing what the page documents. | 262 // Add data attributes describing what the page documents. |
254 var data = ''; | 263 var data = ''; |
(...skipping 16 matching lines...) Expand all Loading... |
271 '''); | 280 '''); |
272 | 281 |
273 // Write the breadcrumb trail. | 282 // Write the breadcrumb trail. |
274 for (int i = 0; i < breadcrumbs.length; i += 2) { | 283 for (int i = 0; i < breadcrumbs.length; i += 2) { |
275 if (breadcrumbs[i + 1] == null) { | 284 if (breadcrumbs[i + 1] == null) { |
276 write(' › ${breadcrumbs[i]}'); | 285 write(' › ${breadcrumbs[i]}'); |
277 } else { | 286 } else { |
278 write(' › ${a(breadcrumbs[i + 1], breadcrumbs[i])}'); | 287 write(' › ${a(breadcrumbs[i + 1], breadcrumbs[i])}'); |
279 } | 288 } |
280 } | 289 } |
| 290 |
| 291 if (searchEngineId != null) { |
| 292 writeln( |
| 293 ''' |
| 294 <form action="$searchResultsUrl" id="search-box"> |
| 295 <input type="hidden" name="cx" value="$searchEngineId"> |
| 296 <input type="hidden" name="ie" value="UTF-8"> |
| 297 <input type="hidden" name="hl" value="en"> |
| 298 <input type="search" name="q" id="q" autocomplete="off" |
| 299 placeholder="Search"> |
| 300 </form> |
| 301 '''); |
| 302 } |
| 303 |
281 writeln('</div>'); | 304 writeln('</div>'); |
282 | 305 |
283 docNavigation(); | 306 docNavigation(); |
284 writeln('<div class="content">'); | 307 writeln('<div class="content">'); |
285 } | 308 } |
286 | 309 |
287 String get clientScript() { | 310 String get clientScript() { |
288 switch (mode) { | 311 switch (mode) { |
289 case MODE_STATIC: return 'client-static'; | 312 case MODE_STATIC: return 'client-static'; |
290 case MODE_LIVE_NAV: return 'client-live-nav'; | 313 case MODE_LIVE_NAV: return 'client-live-nav'; |
291 default: throw 'Unknown mode $mode.'; | 314 default: throw 'Unknown mode $mode.'; |
292 } | 315 } |
293 } | 316 } |
294 | 317 |
295 writeHeadContents(String title) { | 318 void writeHeadContents(String title) { |
296 writeln( | 319 writeln( |
297 ''' | 320 ''' |
298 <meta charset="utf-8"> | 321 <meta charset="utf-8"> |
299 <title>$title</title> | 322 <title>$title</title> |
300 <link rel="stylesheet" type="text/css" | 323 <link rel="stylesheet" type="text/css" |
301 href="${relativePath('styles.css')}" /> | 324 href="${relativePath('styles.css')}" /> |
302 <link href="http://fonts.googleapis.com/css?family=Open+Sans:400,600,700
,800" rel="stylesheet" type="text/css"> | 325 <link href="http://fonts.googleapis.com/css?family=Open+Sans:400,600,700
,800" rel="stylesheet" type="text/css"> |
303 <link rel="shortcut icon" href="${relativePath('favicon.ico')}" /> | 326 <link rel="shortcut icon" href="${relativePath('favicon.ico')}" /> |
304 <script src="${relativePath('$clientScript.js')}"></script> | 327 <script src="${relativePath('$clientScript.js')}"></script> |
305 '''); | 328 '''); |
306 } | 329 } |
307 | 330 |
308 writeFooter() { | 331 void writeFooter() { |
309 writeln( | 332 writeln( |
310 ''' | 333 ''' |
311 </div> | 334 </div> |
312 <div class="clear"></div> | 335 <div class="clear"></div> |
313 </div> | 336 </div> |
314 <div class="footer">$footerText</div> | 337 <div class="footer">$footerText</div> |
315 </body></html> | 338 </body></html> |
316 '''); | 339 '''); |
317 } | 340 } |
318 | 341 |
319 docIndex() { | 342 void docIndex() { |
320 startFile('index.html'); | 343 startFile('index.html'); |
321 | 344 |
322 writeHeader(mainTitle, []); | 345 writeHeader(mainTitle, []); |
323 | 346 |
324 writeln('<h2>$mainTitle</h2>'); | 347 writeln('<h2>$mainTitle</h2>'); |
325 writeln('<h3>Libraries</h3>'); | 348 writeln('<h3>Libraries</h3>'); |
326 | 349 |
327 for (final library in orderByName(world.libraries)) { | 350 for (final library in orderByName(world.libraries)) { |
328 writeln( | 351 docIndexLibrary(library); |
329 ''' | |
330 <h4>${a(libraryUrl(library), library.name)}</h4> | |
331 '''); | |
332 } | 352 } |
333 | 353 |
334 writeFooter(); | 354 writeFooter(); |
335 endFile(); | 355 endFile(); |
336 } | 356 } |
337 | 357 |
| 358 void docIndexLibrary(Library library) { |
| 359 writeln('<h4>${a(libraryUrl(library), library.name)}</h4>'); |
| 360 } |
| 361 |
338 /** | 362 /** |
339 * Walks the libraries and creates a JSON object containing the data needed | 363 * Walks the libraries and creates a JSON object containing the data needed |
340 * to generate navigation for them. | 364 * to generate navigation for them. |
341 */ | 365 */ |
342 docNavigationJson() { | 366 void docNavigationJson() { |
343 startFile('nav.json'); | 367 startFile('nav.json'); |
344 | 368 |
345 final libraries = {}; | 369 final libraries = {}; |
346 | 370 |
347 for (final library in orderByName(world.libraries)) { | 371 for (final library in orderByName(world.libraries)) { |
348 final types = []; | 372 docLibraryNavigationJson(library, libraries); |
349 | |
350 for (final type in orderByName(library.types)) { | |
351 if (type.isTop) continue; | |
352 if (type.name.startsWith('_')) continue; | |
353 | |
354 final kind = type.isClass ? 'class' : 'interface'; | |
355 final url = typeUrl(type); | |
356 types.add({ 'name': typeName(type), 'kind': kind, 'url': url }); | |
357 } | |
358 | |
359 libraries[library.name] = types; | |
360 } | 373 } |
361 | 374 |
362 writeln(JSON.stringify(libraries)); | 375 writeln(JSON.stringify(libraries)); |
363 endFile(); | 376 endFile(); |
364 } | 377 } |
365 | 378 |
366 docNavigation() { | 379 void docLibraryNavigationJson(Library library, Map libraries) { |
| 380 final types = []; |
| 381 |
| 382 for (final type in orderByName(library.types)) { |
| 383 if (type.isTop) continue; |
| 384 if (type.name.startsWith('_')) continue; |
| 385 |
| 386 final kind = type.isClass ? 'class' : 'interface'; |
| 387 final url = typeUrl(type); |
| 388 types.add({ 'name': typeName(type), 'kind': kind, 'url': url }); |
| 389 } |
| 390 |
| 391 libraries[library.name] = types; |
| 392 } |
| 393 |
| 394 void docNavigation() { |
367 writeln( | 395 writeln( |
368 ''' | 396 ''' |
369 <div class="nav"> | 397 <div class="nav"> |
370 '''); | 398 '''); |
371 | 399 |
372 if (mode == MODE_STATIC) { | 400 if (mode == MODE_STATIC) { |
373 for (final library in orderByName(world.libraries)) { | 401 for (final library in orderByName(world.libraries)) { |
374 write('<h2><div class="icon-library"></div>'); | 402 write('<h2><div class="icon-library"></div>'); |
375 | 403 |
376 if ((_currentLibrary == library) && (_currentType == null)) { | 404 if ((_currentLibrary == library) && (_currentType == null)) { |
377 write('<strong>${library.name}</strong>'); | 405 write('<strong>${library.name}</strong>'); |
378 } else { | 406 } else { |
379 write('${a(libraryUrl(library), library.name)}'); | 407 write('${a(libraryUrl(library), library.name)}'); |
380 } | 408 } |
381 write('</h2>'); | 409 write('</h2>'); |
382 | 410 |
383 // Only expand classes in navigation for current library. | 411 // Only expand classes in navigation for current library. |
384 if (_currentLibrary == library) docLibraryNavigation(library); | 412 if (_currentLibrary == library) docLibraryNavigation(library); |
385 } | 413 } |
386 } | 414 } |
387 | 415 |
388 writeln('</div>'); | 416 writeln('</div>'); |
389 } | 417 } |
390 | 418 |
391 /** Writes the navigation for the types contained by the given library. */ | 419 /** Writes the navigation for the types contained by the given library. */ |
392 docLibraryNavigation(Library library) { | 420 void docLibraryNavigation(Library library) { |
393 // Show the exception types separately. | 421 // Show the exception types separately. |
394 final types = <Type>[]; | 422 final types = <Type>[]; |
395 final exceptions = <Type>[]; | 423 final exceptions = <Type>[]; |
396 | 424 |
397 for (final type in orderByName(library.types)) { | 425 for (final type in orderByName(library.types)) { |
398 if (type.isTop) continue; | 426 if (type.isTop) continue; |
399 if (type.name.startsWith('_')) continue; | 427 if (type.name.startsWith('_')) continue; |
400 | 428 |
401 if (type.name.endsWith('Exception')) { | 429 if (type.name.endsWith('Exception')) { |
402 exceptions.add(type); | 430 exceptions.add(type); |
403 } else { | 431 } else { |
404 types.add(type); | 432 types.add(type); |
405 } | 433 } |
406 } | 434 } |
407 | 435 |
408 if ((types.length == 0) && (exceptions.length == 0)) return; | 436 if ((types.length == 0) && (exceptions.length == 0)) return; |
409 | 437 |
410 writeln('<ul class="icon">'); | 438 writeln('<ul class="icon">'); |
411 types.forEach(docTypeNavigation); | 439 types.forEach(docTypeNavigation); |
412 exceptions.forEach(docTypeNavigation); | 440 exceptions.forEach(docTypeNavigation); |
413 writeln('</ul>'); | 441 writeln('</ul>'); |
414 } | 442 } |
415 | 443 |
416 /** Writes a linked navigation list item for the given type. */ | 444 /** Writes a linked navigation list item for the given type. */ |
417 docTypeNavigation(Type type) { | 445 void docTypeNavigation(Type type) { |
418 var icon = 'interface'; | 446 var icon = 'interface'; |
419 if (type.name.endsWith('Exception')) { | 447 if (type.name.endsWith('Exception')) { |
420 icon = 'exception'; | 448 icon = 'exception'; |
421 } else if (type.isClass) { | 449 } else if (type.isClass) { |
422 icon = 'class'; | 450 icon = 'class'; |
423 } | 451 } |
424 | 452 |
425 write('<li>'); | 453 write('<li>'); |
426 if (_currentType == type) { | 454 if (_currentType == type) { |
427 write( | 455 write( |
428 '<div class="icon-$icon"></div><strong>${typeName(type)}</strong>'); | 456 '<div class="icon-$icon"></div><strong>${typeName(type)}</strong>'); |
429 } else { | 457 } else { |
430 write(a(typeUrl(type), | 458 write(a(typeUrl(type), |
431 '<div class="icon-$icon"></div>${typeName(type)}')); | 459 '<div class="icon-$icon"></div>${typeName(type)}')); |
432 } | 460 } |
433 writeln('</li>'); | 461 writeln('</li>'); |
434 } | 462 } |
435 | 463 |
436 docLibrary(Library library) { | 464 void docLibrary(Library library) { |
437 _totalLibraries++; | 465 _totalLibraries++; |
438 _currentLibrary = library; | 466 _currentLibrary = library; |
439 _currentType = null; | 467 _currentType = null; |
440 | 468 |
441 startFile(libraryUrl(library)); | 469 startFile(libraryUrl(library)); |
442 writeHeader(library.name, [library.name, libraryUrl(library)]); | 470 writeHeader(library.name, [library.name, libraryUrl(library)]); |
443 writeln('<h2>Library <strong>${library.name}</strong></h2>'); | 471 writeln('<h2>Library <strong>${library.name}</strong></h2>'); |
444 | 472 |
445 // Look for a comment for the entire library. | 473 // Look for a comment for the entire library. |
446 final comment = _comments.findLibrary(library.baseSource); | 474 final comment = _comments.findLibrary(library.baseSource); |
(...skipping 28 matching lines...) Expand all Loading... |
475 docTypes(exceptions, 'Exceptions'); | 503 docTypes(exceptions, 'Exceptions'); |
476 | 504 |
477 writeFooter(); | 505 writeFooter(); |
478 endFile(); | 506 endFile(); |
479 | 507 |
480 for (final type in library.types.getValues()) { | 508 for (final type in library.types.getValues()) { |
481 if (!type.isTop) docType(type); | 509 if (!type.isTop) docType(type); |
482 } | 510 } |
483 } | 511 } |
484 | 512 |
485 docTypes(List<Type> types, String header) { | 513 void docTypes(List<Type> types, String header) { |
486 if (types.length == 0) return; | 514 if (types.length == 0) return; |
487 | 515 |
488 writeln('<h3>$header</h3>'); | 516 writeln('<h3>$header</h3>'); |
489 | 517 |
490 for (final type in types) { | 518 for (final type in types) { |
491 writeln( | 519 writeln( |
492 ''' | 520 ''' |
493 <div class="type"> | 521 <div class="type"> |
494 <h4> | 522 <h4> |
495 ${a(typeUrl(type), "<strong>${typeName(type)}</strong>")} | 523 ${a(typeUrl(type), "<strong>${typeName(type)}</strong>")} |
496 </h4> | 524 </h4> |
497 </div> | 525 </div> |
498 '''); | 526 '''); |
499 } | 527 } |
500 } | 528 } |
501 | 529 |
502 docType(Type type) { | 530 void docType(Type type) { |
503 _totalTypes++; | 531 _totalTypes++; |
504 _currentType = type; | 532 _currentType = type; |
505 | 533 |
506 startFile(typeUrl(type)); | 534 startFile(typeUrl(type)); |
507 | 535 |
508 final typeTitle = | 536 final typeTitle = |
509 '${type.isClass ? "Class" : "Interface"} ${typeName(type)}'; | 537 '${type.isClass ? "Class" : "Interface"} ${typeName(type)}'; |
510 writeHeader('Library ${type.library.name} / $typeTitle', | 538 writeHeader('Library ${type.library.name} / $typeTitle', |
511 [type.library.name, libraryUrl(type.library), | 539 [type.library.name, libraryUrl(type.library), |
512 typeName(type), typeUrl(type)]); | 540 typeName(type), typeUrl(type)]); |
(...skipping 16 matching lines...) Expand all Loading... |
529 /** Override this to write additional content at the end of a type's page. */ | 557 /** Override this to write additional content at the end of a type's page. */ |
530 void writeTypeFooter() { | 558 void writeTypeFooter() { |
531 // Do nothing. | 559 // Do nothing. |
532 } | 560 } |
533 | 561 |
534 /** | 562 /** |
535 * Writes an inline type span for the given type. This is a little box with | 563 * Writes an inline type span for the given type. This is a little box with |
536 * an icon and the type's name. It's similar to how types appear in the | 564 * an icon and the type's name. It's similar to how types appear in the |
537 * navigation, but is suitable for inline (as opposed to in a `<ul>`) use. | 565 * navigation, but is suitable for inline (as opposed to in a `<ul>`) use. |
538 */ | 566 */ |
539 typeSpan(Type type) { | 567 void typeSpan(Type type) { |
540 var icon = 'interface'; | 568 var icon = 'interface'; |
541 if (type.name.endsWith('Exception')) { | 569 if (type.name.endsWith('Exception')) { |
542 icon = 'exception'; | 570 icon = 'exception'; |
543 } else if (type.isClass) { | 571 } else if (type.isClass) { |
544 icon = 'class'; | 572 icon = 'class'; |
545 } | 573 } |
546 | 574 |
547 write('<span class="type-box"><span class="icon-$icon"></span>'); | 575 write('<span class="type-box"><span class="icon-$icon"></span>'); |
548 if (_currentType == type) { | 576 if (_currentType == type) { |
549 write('<strong>${typeName(type)}</strong>'); | 577 write('<strong>${typeName(type)}</strong>'); |
550 } else { | 578 } else { |
551 write(a(typeUrl(type), typeName(type))); | 579 write(a(typeUrl(type), typeName(type))); |
552 } | 580 } |
553 write('</span>'); | 581 write('</span>'); |
554 } | 582 } |
555 | 583 |
556 /** | 584 /** |
557 * Document the other types that touch [Type] in the inheritance hierarchy: | 585 * Document the other types that touch [Type] in the inheritance hierarchy: |
558 * subclasses, superclasses, subinterfaces, superinferfaces, and default | 586 * subclasses, superclasses, subinterfaces, superinferfaces, and default |
559 * class. | 587 * class. |
560 */ | 588 */ |
561 docInheritance(Type type) { | 589 void docInheritance(Type type) { |
562 // Don't show the inheritance details for Object. It doesn't have any base | 590 // Don't show the inheritance details for Object. It doesn't have any base |
563 // class (obviously) and it has too many subclasses to be useful. | 591 // class (obviously) and it has too many subclasses to be useful. |
564 if (type.isObject) return; | 592 if (type.isObject) return; |
565 | 593 |
566 // Writes an unordered list of references to types with an optional header. | 594 // Writes an unordered list of references to types with an optional header. |
567 listTypes(types, header) { | 595 listTypes(types, header) { |
568 if (types == null) return; | 596 if (types == null) return; |
569 | 597 |
570 // Skip private types. | 598 // Skip private types. |
571 final publicTypes = types.filter((type) => !type.name.startsWith('_')); | 599 final publicTypes = types.filter((type) => !type.name.startsWith('_')); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 } | 671 } |
644 } | 672 } |
645 } | 673 } |
646 | 674 |
647 listTypes(subinterfaces, 'Subinterfaces'); | 675 listTypes(subinterfaces, 'Subinterfaces'); |
648 listTypes(implementing, 'Implemented by'); | 676 listTypes(implementing, 'Implemented by'); |
649 } | 677 } |
650 } | 678 } |
651 | 679 |
652 /** Document the constructors for [Type], if any. */ | 680 /** Document the constructors for [Type], if any. */ |
653 docConstructors(Type type) { | 681 void docConstructors(Type type) { |
654 final names = type.constructors.getKeys().filter( | 682 final names = type.constructors.getKeys().filter( |
655 (name) => !name.startsWith('_')); | 683 (name) => !name.startsWith('_')); |
656 | 684 |
657 if (names.length > 0) { | 685 if (names.length > 0) { |
658 writeln('<h3>Constructors</h3>'); | 686 writeln('<h3>Constructors</h3>'); |
659 names.sort((x, y) => x.toUpperCase().compareTo(y.toUpperCase())); | 687 names.sort((x, y) => x.toUpperCase().compareTo(y.toUpperCase())); |
660 | 688 |
661 for (final name in names) { | 689 for (final name in names) { |
662 docMethod(type, type.constructors[name], constructorName: name); | 690 docMethod(type, type.constructors[name], constructorName: name); |
663 } | 691 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 if (instanceFields.length > 0) { | 735 if (instanceFields.length > 0) { |
708 writeln('<h3>Fields</h3>'); | 736 writeln('<h3>Fields</h3>'); |
709 for (final field in instanceFields) docField(type, field); | 737 for (final field in instanceFields) docField(type, field); |
710 } | 738 } |
711 } | 739 } |
712 | 740 |
713 /** | 741 /** |
714 * Documents the [method] in type [type]. Handles all kinds of methods | 742 * Documents the [method] in type [type]. Handles all kinds of methods |
715 * including getters, setters, and constructors. | 743 * including getters, setters, and constructors. |
716 */ | 744 */ |
717 docMethod(Type type, MethodMember method, [String constructorName = null]) { | 745 void docMethod(Type type, MethodMember method, |
| 746 [String constructorName = null]) { |
718 _totalMembers++; | 747 _totalMembers++; |
719 _currentMember = method; | 748 _currentMember = method; |
720 | 749 |
721 writeln('<div class="method"><h4 id="${memberAnchor(method)}">'); | 750 writeln('<div class="method"><h4 id="${memberAnchor(method)}">'); |
722 | 751 |
723 if (includeSource) { | 752 if (includeSource) { |
724 writeln('<span class="show-code">Code</span>'); | 753 writeln('<span class="show-code">Code</span>'); |
725 } | 754 } |
726 | 755 |
727 if (method.isConstructor) { | 756 if (method.isConstructor) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 write(''' <a class="anchor-link" href="#${memberAnchor(method)}" | 797 write(''' <a class="anchor-link" href="#${memberAnchor(method)}" |
769 title="Permalink to ${typeName(type)}.$name">#</a>'''); | 798 title="Permalink to ${typeName(type)}.$name">#</a>'''); |
770 writeln('</h4>'); | 799 writeln('</h4>'); |
771 | 800 |
772 docCode(method.span, getMethodComment(method), showCode: true); | 801 docCode(method.span, getMethodComment(method), showCode: true); |
773 | 802 |
774 writeln('</div>'); | 803 writeln('</div>'); |
775 } | 804 } |
776 | 805 |
777 /** Documents the field [field] of type [type]. */ | 806 /** Documents the field [field] of type [type]. */ |
778 docField(Type type, FieldMember field) { | 807 void docField(Type type, FieldMember field) { |
779 _totalMembers++; | 808 _totalMembers++; |
780 _currentMember = field; | 809 _currentMember = field; |
781 | 810 |
782 writeln('<div class="field"><h4 id="${memberAnchor(field)}">'); | 811 writeln('<div class="field"><h4 id="${memberAnchor(field)}">'); |
783 | 812 |
784 if (includeSource) { | 813 if (includeSource) { |
785 writeln('<span class="show-code">Code</span>'); | 814 writeln('<span class="show-code">Code</span>'); |
786 } | 815 } |
787 | 816 |
788 if (field.isFinal) { | 817 if (field.isFinal) { |
789 write('final '); | 818 write('final '); |
790 } else if (field.type.name == 'Dynamic') { | 819 } else if (field.type.name == 'Dynamic') { |
791 write('var '); | 820 write('var '); |
792 } | 821 } |
793 | 822 |
794 annotateType(type, field.type); | 823 annotateType(type, field.type); |
795 write( | 824 write( |
796 ''' | 825 ''' |
797 <strong>${field.name}</strong> <a class="anchor-link" | 826 <strong>${field.name}</strong> <a class="anchor-link" |
798 href="#${memberAnchor(field)}" | 827 href="#${memberAnchor(field)}" |
799 title="Permalink to ${typeName(type)}.${field.name}">#</a> | 828 title="Permalink to ${typeName(type)}.${field.name}">#</a> |
800 </h4> | 829 </h4> |
801 '''); | 830 '''); |
802 | 831 |
803 docCode(field.span, getFieldComment(field), showCode: true); | 832 docCode(field.span, getFieldComment(field), showCode: true); |
804 writeln('</div>'); | 833 writeln('</div>'); |
805 } | 834 } |
806 | 835 |
807 docParamList(Type enclosingType, MethodMember member) { | 836 void docParamList(Type enclosingType, MethodMember member) { |
808 write('('); | 837 write('('); |
809 bool first = true; | 838 bool first = true; |
810 bool inOptionals = false; | 839 bool inOptionals = false; |
811 for (final parameter in member.parameters) { | 840 for (final parameter in member.parameters) { |
812 if (!first) write(', '); | 841 if (!first) write(', '); |
813 | 842 |
814 if (!inOptionals && parameter.isOptional) { | 843 if (!inOptionals && parameter.isOptional) { |
815 write('['); | 844 write('['); |
816 inOptionals = true; | 845 inOptionals = true; |
817 } | 846 } |
(...skipping 16 matching lines...) Expand all Loading... |
834 } | 863 } |
835 | 864 |
836 if (inOptionals) write(']'); | 865 if (inOptionals) write(']'); |
837 write(')'); | 866 write(')'); |
838 } | 867 } |
839 | 868 |
840 /** | 869 /** |
841 * Documents the code contained within [span] with [comment]. If [showCode] | 870 * Documents the code contained within [span] with [comment]. If [showCode] |
842 * is `true` (and [includeSource] is set), also includes the source code. | 871 * is `true` (and [includeSource] is set), also includes the source code. |
843 */ | 872 */ |
844 docCode(SourceSpan span, String comment, [bool showCode = false]) { | 873 void docCode(SourceSpan span, String comment, [bool showCode = false]) { |
845 writeln('<div class="doc">'); | 874 writeln('<div class="doc">'); |
846 if (comment != null) { | 875 if (comment != null) { |
847 writeln(comment); | 876 writeln(comment); |
848 } | 877 } |
849 | 878 |
850 if (includeSource && showCode) { | 879 if (includeSource && showCode) { |
851 writeln('<pre class="source">'); | 880 writeln('<pre class="source">'); |
852 writeln(md.escapeHtml(unindentCode(span))); | 881 writeln(md.escapeHtml(unindentCode(span))); |
853 writeln('</pre>'); | 882 writeln('</pre>'); |
854 } | 883 } |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1157 | 1186 |
1158 return new md.Element.text('code', name); | 1187 return new md.Element.text('code', name); |
1159 } | 1188 } |
1160 | 1189 |
1161 // TODO(rnystrom): Move into SourceSpan? | 1190 // TODO(rnystrom): Move into SourceSpan? |
1162 int getSpanColumn(SourceSpan span) { | 1191 int getSpanColumn(SourceSpan span) { |
1163 final line = span.file.getLine(span.start); | 1192 final line = span.file.getLine(span.start); |
1164 return span.file.getColumn(line, span.start); | 1193 return span.file.getColumn(line, span.start); |
1165 } | 1194 } |
1166 } | 1195 } |
OLD | NEW |