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 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
369 | 369 |
370 if (type.name.endsWith('Exception')) { | 370 if (type.name.endsWith('Exception')) { |
371 exceptions.add(type); | 371 exceptions.add(type); |
372 } else { | 372 } else { |
373 types.add(type); | 373 types.add(type); |
374 } | 374 } |
375 } | 375 } |
376 | 376 |
377 if ((types.length == 0) && (exceptions.length == 0)) return; | 377 if ((types.length == 0) && (exceptions.length == 0)) return; |
378 | 378 |
379 writeType(String icon, Type type) { | 379 writeln('<ul class="icon">'); |
380 write('<li>'); | 380 types.forEach(docTypeNavigation); |
381 if (_currentType == type) { | 381 exceptions.forEach(docTypeNavigation); |
382 write( | |
383 '<div class="icon-$icon"></div><strong>${typeName(type)}</strong>'); | |
384 } else { | |
385 write(a(typeUrl(type), | |
386 '<div class="icon-$icon"></div>${typeName(type)}')); | |
387 } | |
388 writeln('</li>'); | |
389 } | |
390 | |
391 writeln('<ul>'); | |
392 types.forEach((type) => writeType(type.isClass ? 'class' : 'interface', | |
393 type)); | |
394 exceptions.forEach((type) => writeType('exception', type)); | |
395 writeln('</ul>'); | 382 writeln('</ul>'); |
396 } | 383 } |
397 | 384 |
385 /** Writes a linked navigation list item for the given type. */ | |
386 docTypeNavigation(Type type) { | |
387 var icon = 'interface'; | |
388 if (type.name.endsWith('Exception')) { | |
389 icon = 'exception'; | |
390 } else if (type.isClass) { | |
391 icon = 'class'; | |
392 } | |
393 | |
394 write('<li>'); | |
395 if (_currentType == type) { | |
396 write( | |
397 '<div class="icon-$icon"></div><strong>${typeName(type)}</strong>'); | |
398 } else { | |
399 write(a(typeUrl(type), | |
400 '<div class="icon-$icon"></div>${typeName(type)}')); | |
401 } | |
402 writeln('</li>'); | |
403 } | |
404 | |
398 docLibrary(Library library) { | 405 docLibrary(Library library) { |
399 _totalLibraries++; | 406 _totalLibraries++; |
400 _currentLibrary = library; | 407 _currentLibrary = library; |
401 _currentType = null; | 408 _currentType = null; |
402 | 409 |
403 startFile(libraryUrl(library)); | 410 startFile(libraryUrl(library)); |
404 writeHeader(library.name, [library.name, libraryUrl(library)]); | 411 writeHeader(library.name, [library.name, libraryUrl(library)]); |
405 writeln('<h2>Library <strong>${library.name}</strong></h2>'); | 412 writeln('<h2>Library <strong>${library.name}</strong></h2>'); |
406 | 413 |
407 // Look for a comment for the entire library. | 414 // Look for a comment for the entire library. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
471 '${type.isClass ? "Class" : "Interface"} ${typeName(type)}'; | 478 '${type.isClass ? "Class" : "Interface"} ${typeName(type)}'; |
472 writeHeader('Library ${type.library.name} / $typeTitle', | 479 writeHeader('Library ${type.library.name} / $typeTitle', |
473 [type.library.name, libraryUrl(type.library), | 480 [type.library.name, libraryUrl(type.library), |
474 typeName(type), typeUrl(type)]); | 481 typeName(type), typeUrl(type)]); |
475 writeln( | 482 writeln( |
476 ''' | 483 ''' |
477 <h2>${type.isClass ? "Class" : "Interface"} | 484 <h2>${type.isClass ? "Class" : "Interface"} |
478 <strong>${typeName(type, showBounds: true)}</strong></h2> | 485 <strong>${typeName(type, showBounds: true)}</strong></h2> |
479 '''); | 486 '''); |
480 | 487 |
488 docCode(type.span, getTypeComment(type)); | |
481 docInheritance(type); | 489 docInheritance(type); |
482 | |
483 docCode(type.span, getTypeComment(type)); | |
484 docConstructors(type); | 490 docConstructors(type); |
485 docMembers(type); | 491 docMembers(type); |
486 | 492 |
487 writeFooter(); | 493 writeFooter(); |
488 endFile(); | 494 endFile(); |
489 } | 495 } |
490 | 496 |
491 /** Document the superclass, superinterfaces and default class of [Type]. */ | 497 /** |
492 docInheritance(Type type) { | 498 * Writes an inline type span for the given type. This is a little box with |
493 final isSubclass = (type.parent != null) && !type.parent.isObject; | 499 * an icon and the type's name. It's similar to how types appear in the |
494 | 500 * navigation, but is suitable for inline (as opposed to in a `<ul>`) use. |
495 Type defaultType; | 501 */ |
496 if (type.definition is TypeDefinition) { | 502 typeSpan(Type type) { |
497 TypeDefinition definition = type.definition; | 503 var icon = 'interface'; |
498 if (definition.defaultType != null) { | 504 if (type.name.endsWith('Exception')) { |
499 defaultType = definition.defaultType.type; | 505 icon = 'exception'; |
500 } | 506 } else if (type.isClass) { |
507 icon = 'class'; | |
501 } | 508 } |
502 | 509 |
503 if (isSubclass || | 510 write('<span class="type-box"><span class="icon-$icon"></span>'); |
504 (type.interfaces != null && type.interfaces.length > 0) || | 511 if (_currentType == type) { |
505 (defaultType != null)) { | 512 write('<strong>${typeName(type)}</strong>'); |
513 } else { | |
514 write(a(typeUrl(type), typeName(type))); | |
515 } | |
516 write('</span>'); | |
517 } | |
518 | |
519 /** | |
520 * Document the other types that touch [Type] in the inheritance hierarchy: | |
521 * subclasses, superclasses, subinterfaces, superinferfaces, and default | |
522 * class. | |
523 */ | |
524 docInheritance(Type type) { | |
525 // Don't show the inheritance details for Object. It doesn't have any base | |
526 // class (obviously) and it has too many subclasses to be useful. | |
527 if (type.isObject) return; | |
528 | |
529 // Writes an unordered list of references to types with an optional header. | |
530 listTypes(types, header) { | |
531 if (types == null) return; | |
532 | |
533 // Skip private types. | |
534 final publicTypes = types.filter((type) => !type.name.startsWith('_')); | |
535 if (publicTypes.length == 0) return; | |
536 | |
537 writeln('<h3>$header</h3>'); | |
506 writeln('<p>'); | 538 writeln('<p>'); |
539 bool first = true; | |
540 for (final type in publicTypes) { | |
541 if (type.name.startsWith('_')) continue; | |
nweiz
2012/01/21 01:11:15
You already filtered for this.
Bob Nystrom
2012/02/01 21:41:56
Done.
| |
507 | 542 |
508 if (isSubclass) { | 543 if (!first) write(', '); |
509 write('Extends ${typeReference(type.parent)}. '); | 544 typeSpan(type); |
545 first = false; | |
546 } | |
547 writeln('</p>'); | |
548 } | |
549 | |
550 if (type.isClass) { | |
551 // Show the chain of superclasses. | |
552 if (!type.parent.isObject) { | |
553 final supertypes = []; | |
554 var thisType = type.parent; | |
555 // As a sanity check, only show up to five levels of nesting, otherwise | |
556 // the box starts to get hideous. | |
557 do { | |
558 supertypes.add(thisType); | |
559 thisType = thisType.parent; | |
560 } while (!thisType.isObject); | |
561 | |
562 writeln('<h3>Extends</h3>'); | |
563 writeln('<p>'); | |
564 for (var i = supertypes.length - 1; i >= 0; i--) { | |
565 typeSpan(supertypes[i]); | |
566 write(' > '); | |
567 } | |
568 | |
569 // Write this class. | |
570 typeSpan(type); | |
571 writeln('</p>'); | |
510 } | 572 } |
511 | 573 |
512 if (type.interfaces != null && type.interfaces.length > 0) { | 574 listTypes(type.subtypes, 'Subclasses'); |
Siggi Cherem (dart-lang)
2012/01/21 01:57:25
it would be nice to sort these by name
Bob Nystrom
2012/02/01 21:41:56
Done.
| |
513 var interfaceStr = joinWithCommas(map(type.interfaces, typeReference)); | 575 listTypes(type.interfaces, 'Implements'); |
514 write('Implements ${interfaceStr}. '); | 576 } else { |
577 // Show the default class. | |
578 if (type.genericType.defaultType != null) { | |
579 listTypes([type.genericType.defaultType], 'Default class'); | |
515 } | 580 } |
516 | 581 |
517 if (defaultType != null) { | 582 // List extended interfaces. |
518 write('Has default class ${typeReference(defaultType)}.'); | 583 listTypes(type.interfaces, 'Extends'); |
584 | |
585 // List subinterfaces and implementing classes. | |
586 final subinterfaces = []; | |
587 final implementing = []; | |
588 | |
589 for (final subtype in type.subtypes) { | |
590 if (subtype.isClass) { | |
591 implementing.add(subtype); | |
592 } else { | |
593 subinterfaces.add(subtype); | |
594 } | |
519 } | 595 } |
596 | |
597 listTypes(subinterfaces, 'Subinterfaces'); | |
598 listTypes(implementing, 'Implemented by'); | |
520 } | 599 } |
521 } | 600 } |
522 | 601 |
523 /** Document the constructors for [Type], if any. */ | 602 /** Document the constructors for [Type], if any. */ |
524 docConstructors(Type type) { | 603 docConstructors(Type type) { |
525 final names = type.constructors.getKeys().filter( | 604 final names = type.constructors.getKeys().filter( |
526 (name) => !name.startsWith('_')); | 605 (name) => !name.startsWith('_')); |
527 | 606 |
528 if (names.length > 0) { | 607 if (names.length > 0) { |
529 writeln('<h3>Constructors</h3>'); | 608 writeln('<h3>Constructors</h3>'); |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
964 | 1043 |
965 return new md.Element.text('code', name); | 1044 return new md.Element.text('code', name); |
966 } | 1045 } |
967 | 1046 |
968 // TODO(rnystrom): Move into SourceSpan? | 1047 // TODO(rnystrom): Move into SourceSpan? |
969 int getSpanColumn(SourceSpan span) { | 1048 int getSpanColumn(SourceSpan span) { |
970 final line = span.file.getLine(span.start); | 1049 final line = span.file.getLine(span.start); |
971 return span.file.getColumn(line, span.start); | 1050 return span.file.getColumn(line, span.start); |
972 } | 1051 } |
973 } | 1052 } |
OLD | NEW |