Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 generate docs for a library, run this script with the path to an | 6 * To generate docs for a library, run this script with the path to an |
| 7 * entrypoint .dart file, like: | 7 * entrypoint .dart file, like: |
| 8 * | 8 * |
| 9 * $ dart dartdoc.dart foo.dart | 9 * $ dart dartdoc.dart foo.dart |
| 10 * | 10 * |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 try { | 82 try { |
| 83 // TODO(3914): Hack to avoid 'file already exists' exception thrown | 83 // TODO(3914): Hack to avoid 'file already exists' exception thrown |
| 84 // due to invalid result from dir.existsSync() (probably due to race | 84 // due to invalid result from dir.existsSync() (probably due to race |
| 85 // conditions). | 85 // conditions). |
| 86 outputDir.createSync(); | 86 outputDir.createSync(); |
| 87 } on DirectoryIOException catch (e) { | 87 } on DirectoryIOException catch (e) { |
| 88 // Ignore. | 88 // Ignore. |
| 89 } | 89 } |
| 90 } | 90 } |
| 91 | 91 |
| 92 /** Returns the printed name of the library. */ | |
| 93 String printedName(LibraryMirror library) { | |
|
Bob Nystrom
2012/10/24 20:52:15
"printed" might be a bit too specific. Maybe "disp
Andrei Mouravski
2012/10/24 21:19:36
Done.
| |
| 94 var uri = library.uri.toString(); | |
| 95 return uri.startsWith('dart:') ? uri.toString() : library.simpleName; | |
| 96 } | |
| 97 | |
| 92 /** | 98 /** |
| 93 * Copies all of the files in the directory [from] to [to]. Does *not* | 99 * Copies all of the files in the directory [from] to [to]. Does *not* |
| 94 * recursively copy subdirectories. | 100 * recursively copy subdirectories. |
| 95 * | 101 * |
| 96 * Note: runs asynchronously, so you won't see any files copied until after the | 102 * Note: runs asynchronously, so you won't see any files copied until after the |
| 97 * event loop has had a chance to pump (i.e. after `main()` has returned). | 103 * event loop has had a chance to pump (i.e. after `main()` has returned). |
| 98 */ | 104 */ |
| 99 Future copyDirectory(Path from, Path to) { | 105 Future copyDirectory(Path from, Path to) { |
| 100 final completer = new Completer(); | 106 final completer = new Completer(); |
| 101 final fromDir = new Directory.fromPath(from); | 107 final fromDir = new Directory.fromPath(from); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 } | 256 } |
| 251 | 257 |
| 252 /** | 258 /** |
| 253 * Returns `true` if [library] is included in the generated documentation. | 259 * Returns `true` if [library] is included in the generated documentation. |
| 254 */ | 260 */ |
| 255 bool shouldIncludeLibrary(LibraryMirror library) { | 261 bool shouldIncludeLibrary(LibraryMirror library) { |
| 256 if (shouldLinkToPublicApi(library)) { | 262 if (shouldLinkToPublicApi(library)) { |
| 257 return false; | 263 return false; |
| 258 } | 264 } |
| 259 var includeByDefault = true; | 265 var includeByDefault = true; |
| 260 String libraryName = library.simpleName; | 266 String libraryName = printedName(library); |
| 261 if (!includedLibraries.isEmpty) { | 267 if (!includedLibraries.isEmpty) { |
| 262 includeByDefault = false; | 268 includeByDefault = false; |
| 263 if (includedLibraries.indexOf(libraryName) != -1) { | 269 if (includedLibraries.indexOf(libraryName) != -1) { |
| 264 return true; | 270 return true; |
| 265 } | 271 } |
| 266 } | 272 } |
| 267 if (excludedLibraries.indexOf(libraryName) != -1) { | 273 if (excludedLibraries.indexOf(libraryName) != -1) { |
| 268 return false; | 274 return false; |
| 269 } | 275 } |
| 270 if (libraryName.startsWith('dart:')) { | 276 if (libraryName.startsWith('dart:')) { |
| 271 String suffix = libraryName.substring('dart:'.length); | 277 String suffix = libraryName.substring('dart:'.length); |
| 272 LibraryInfo info = LIBRARIES[suffix]; | 278 LibraryInfo info = LIBRARIES[suffix]; |
| 273 if (info != null) { | 279 if (info != null) { |
| 274 return info.documented && includeApi; | 280 return info.documented && includeApi; |
| 275 } | 281 } |
| 276 } | 282 } |
| 277 return includeByDefault; | 283 return includeByDefault; |
| 278 } | 284 } |
| 279 | 285 |
| 280 /** | 286 /** |
| 281 * Returns `true` if links to the public API should be generated for | 287 * Returns `true` if links to the public API should be generated for |
| 282 * [library]. | 288 * [library]. |
| 283 */ | 289 */ |
| 284 bool shouldLinkToPublicApi(LibraryMirror library) { | 290 bool shouldLinkToPublicApi(LibraryMirror library) { |
| 285 if (linkToApi) { | 291 if (linkToApi) { |
| 286 String libraryName = library.simpleName; | 292 String libraryName = printedName(library); |
| 287 if (libraryName.startsWith('dart:')) { | 293 if (libraryName.startsWith('dart:')) { |
| 288 String suffix = libraryName.substring('dart:'.length); | 294 String suffix = libraryName.substring('dart:'.length); |
| 289 LibraryInfo info = LIBRARIES[suffix]; | 295 LibraryInfo info = LIBRARIES[suffix]; |
| 290 if (info != null) { | 296 if (info != null) { |
| 291 return info.documented; | 297 return info.documented; |
| 292 } | 298 } |
| 293 } | 299 } |
| 294 } | 300 } |
| 295 return false; | 301 return false; |
| 296 } | 302 } |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 322 final compilation = new Compilation.library(libraryList, libPath, pkgPath); | 328 final compilation = new Compilation.library(libraryList, libPath, pkgPath); |
| 323 _document(compilation); | 329 _document(compilation); |
| 324 } | 330 } |
| 325 | 331 |
| 326 void _document(Compilation compilation) { | 332 void _document(Compilation compilation) { |
| 327 // Sort the libraries by name (not key). | 333 // Sort the libraries by name (not key). |
| 328 _sortedLibraries = new List<LibraryMirror>.from( | 334 _sortedLibraries = new List<LibraryMirror>.from( |
| 329 compilation.mirrors.libraries.getValues().filter( | 335 compilation.mirrors.libraries.getValues().filter( |
| 330 shouldIncludeLibrary)); | 336 shouldIncludeLibrary)); |
| 331 _sortedLibraries.sort((x, y) { | 337 _sortedLibraries.sort((x, y) { |
| 332 return x.simpleName.toUpperCase().compareTo( | 338 return printedName(x).toUpperCase().compareTo( |
| 333 y.simpleName.toUpperCase()); | 339 printedName(y).toUpperCase()); |
| 334 }); | 340 }); |
| 335 | 341 |
| 336 // Generate the docs. | 342 // Generate the docs. |
| 337 if (mode == MODE_LIVE_NAV) { | 343 if (mode == MODE_LIVE_NAV) { |
| 338 docNavigationJson(); | 344 docNavigationJson(); |
| 339 } else { | 345 } else { |
| 340 docNavigationDart(); | 346 docNavigationDart(); |
| 341 } | 347 } |
| 342 | 348 |
| 343 docIndex(); | 349 docIndex(); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 <!DOCTYPE html> | 409 <!DOCTYPE html> |
| 404 <html${htmlAttributes == '' ? '' : ' $htmlAttributes'}> | 410 <html${htmlAttributes == '' ? '' : ' $htmlAttributes'}> |
| 405 <head> | 411 <head> |
| 406 '''); | 412 '''); |
| 407 writeHeadContents(title); | 413 writeHeadContents(title); |
| 408 | 414 |
| 409 // Add data attributes describing what the page documents. | 415 // Add data attributes describing what the page documents. |
| 410 var data = ''; | 416 var data = ''; |
| 411 if (_currentLibrary != null) { | 417 if (_currentLibrary != null) { |
| 412 data = '$data data-library=' | 418 data = '$data data-library=' |
| 413 '"${md.escapeHtml(_currentLibrary.simpleName)}"'; | 419 '"${md.escapeHtml(printedName(_currentLibrary))}"'; |
| 414 } | 420 } |
| 415 | 421 |
| 416 if (_currentType != null) { | 422 if (_currentType != null) { |
| 417 data = '$data data-type="${md.escapeHtml(typeName(_currentType))}"'; | 423 data = '$data data-type="${md.escapeHtml(typeName(_currentType))}"'; |
| 418 } | 424 } |
| 419 | 425 |
| 420 write( | 426 write( |
| 421 ''' | 427 ''' |
| 422 </head> | 428 </head> |
| 423 <body$data> | 429 <body$data> |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 512 | 518 |
| 513 for (final library in _sortedLibraries) { | 519 for (final library in _sortedLibraries) { |
| 514 docIndexLibrary(library); | 520 docIndexLibrary(library); |
| 515 } | 521 } |
| 516 | 522 |
| 517 writeFooter(); | 523 writeFooter(); |
| 518 endFile(); | 524 endFile(); |
| 519 } | 525 } |
| 520 | 526 |
| 521 void docIndexLibrary(LibraryMirror library) { | 527 void docIndexLibrary(LibraryMirror library) { |
| 522 writeln('<h4>${a(libraryUrl(library), library.simpleName)}</h4>'); | 528 writeln('<h4>${a(libraryUrl(library), printedName(library))}</h4>'); |
| 523 } | 529 } |
| 524 | 530 |
| 525 /** | 531 /** |
| 526 * Walks the libraries and creates a JSON object containing the data needed | 532 * Walks the libraries and creates a JSON object containing the data needed |
| 527 * to generate navigation for them. | 533 * to generate navigation for them. |
| 528 */ | 534 */ |
| 529 void docNavigationJson() { | 535 void docNavigationJson() { |
| 530 startFile('nav.json'); | 536 startFile('nav.json'); |
| 531 writeln(JSON.stringify(createNavigationInfo())); | 537 writeln(JSON.stringify(createNavigationInfo())); |
| 532 endFile(); | 538 endFile(); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 563 List createNavigationInfo() { | 569 List createNavigationInfo() { |
| 564 final libraryList = []; | 570 final libraryList = []; |
| 565 for (final library in _sortedLibraries) { | 571 for (final library in _sortedLibraries) { |
| 566 docLibraryNavigationJson(library, libraryList); | 572 docLibraryNavigationJson(library, libraryList); |
| 567 } | 573 } |
| 568 return libraryList; | 574 return libraryList; |
| 569 } | 575 } |
| 570 | 576 |
| 571 void docLibraryNavigationJson(LibraryMirror library, List libraryList) { | 577 void docLibraryNavigationJson(LibraryMirror library, List libraryList) { |
| 572 var libraryInfo = {}; | 578 var libraryInfo = {}; |
| 573 libraryInfo[NAME] = library.simpleName; | 579 libraryInfo[NAME] = printedName(library); |
| 574 final List members = docMembersJson(library.declaredMembers); | 580 final List members = docMembersJson(library.declaredMembers); |
| 575 if (!members.isEmpty) { | 581 if (!members.isEmpty) { |
| 576 libraryInfo[MEMBERS] = members; | 582 libraryInfo[MEMBERS] = members; |
| 577 } | 583 } |
| 578 | 584 |
| 579 final types = []; | 585 final types = []; |
| 580 for (InterfaceMirror type in orderByName(library.types.getValues())) { | 586 for (InterfaceMirror type in orderByName(library.types.getValues())) { |
| 581 if (!showPrivate && type.isPrivate) continue; | 587 if (!showPrivate && type.isPrivate) continue; |
| 582 | 588 |
| 583 var typeInfo = {}; | 589 var typeInfo = {}; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 648 writeln( | 654 writeln( |
| 649 ''' | 655 ''' |
| 650 <div class="nav"> | 656 <div class="nav"> |
| 651 '''); | 657 '''); |
| 652 | 658 |
| 653 if (mode == MODE_STATIC) { | 659 if (mode == MODE_STATIC) { |
| 654 for (final library in _sortedLibraries) { | 660 for (final library in _sortedLibraries) { |
| 655 write('<h2><div class="icon-library"></div>'); | 661 write('<h2><div class="icon-library"></div>'); |
| 656 | 662 |
| 657 if ((_currentLibrary == library) && (_currentType == null)) { | 663 if ((_currentLibrary == library) && (_currentType == null)) { |
| 658 write('<strong>${library.simpleName}</strong>'); | 664 write('<strong>${printedName(library)}</strong>'); |
| 659 } else { | 665 } else { |
| 660 write('${a(libraryUrl(library), library.simpleName)}'); | 666 write('${a(libraryUrl(library), printedName(library))}'); |
| 661 } | 667 } |
| 662 write('</h2>'); | 668 write('</h2>'); |
| 663 | 669 |
| 664 // Only expand classes in navigation for current library. | 670 // Only expand classes in navigation for current library. |
| 665 if (_currentLibrary == library) docLibraryNavigation(library); | 671 if (_currentLibrary == library) docLibraryNavigation(library); |
| 666 } | 672 } |
| 667 } | 673 } |
| 668 | 674 |
| 669 writeln('</div>'); | 675 writeln('</div>'); |
| 670 } | 676 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 708 '<div class="icon-$icon"></div><strong>${typeName(type)}</strong>'); | 714 '<div class="icon-$icon"></div><strong>${typeName(type)}</strong>'); |
| 709 } else { | 715 } else { |
| 710 write(a(typeUrl(type), | 716 write(a(typeUrl(type), |
| 711 '<div class="icon-$icon"></div>${typeName(type)}')); | 717 '<div class="icon-$icon"></div>${typeName(type)}')); |
| 712 } | 718 } |
| 713 writeln('</li>'); | 719 writeln('</li>'); |
| 714 } | 720 } |
| 715 | 721 |
| 716 void docLibrary(LibraryMirror library) { | 722 void docLibrary(LibraryMirror library) { |
| 717 if (verbose) { | 723 if (verbose) { |
| 718 print('Library \'${library.simpleName}\':'); | 724 print('Library \'${printedName(library)}\':'); |
| 719 } | 725 } |
| 720 _totalLibraries++; | 726 _totalLibraries++; |
| 721 _currentLibrary = library; | 727 _currentLibrary = library; |
| 722 _currentType = null; | 728 _currentType = null; |
| 723 | 729 |
| 724 startFile(libraryUrl(library)); | 730 startFile(libraryUrl(library)); |
| 725 writeHeader('${library.simpleName} Library', | 731 writeHeader('${printedName(library)} Library', |
| 726 [library.simpleName, libraryUrl(library)]); | 732 [printedName(library), libraryUrl(library)]); |
| 727 writeln('<h2><strong>${library.simpleName}</strong> library</h2>'); | 733 writeln('<h2><strong>${printedName(library)}</strong> library</h2>'); |
| 728 | 734 |
| 729 // Look for a comment for the entire library. | 735 // Look for a comment for the entire library. |
| 730 final comment = getLibraryComment(library); | 736 final comment = getLibraryComment(library); |
| 731 if (comment != null) { | 737 if (comment != null) { |
| 732 writeln('<div class="doc">${comment.html}</div>'); | 738 writeln('<div class="doc">${comment.html}</div>'); |
| 733 } | 739 } |
| 734 | 740 |
| 735 // Document the top-level members. | 741 // Document the top-level members. |
| 736 docMembers(library); | 742 docMembers(library); |
| 737 | 743 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 806 } else if (type.isClass) { | 812 } else if (type.isClass) { |
| 807 if (type.isAbstract) { | 813 if (type.isAbstract) { |
| 808 kind = 'abstract class'; | 814 kind = 'abstract class'; |
| 809 } else { | 815 } else { |
| 810 kind = 'class'; | 816 kind = 'class'; |
| 811 } | 817 } |
| 812 } | 818 } |
| 813 | 819 |
| 814 final typeTitle = | 820 final typeTitle = |
| 815 '${typeName(type)} ${kind}'; | 821 '${typeName(type)} ${kind}'; |
| 816 writeHeader('$typeTitle / ${type.library.simpleName} Library', | 822 writeHeader('$typeTitle / ${printedName(type.library)} Library', |
| 817 [type.library.simpleName, libraryUrl(type.library), | 823 [printedName(type.library), libraryUrl(type.library), |
| 818 typeName(type), typeUrl(type)]); | 824 typeName(type), typeUrl(type)]); |
| 819 writeln( | 825 writeln( |
| 820 ''' | 826 ''' |
| 821 <h2><strong>${typeName(type, showBounds: true)}</strong> | 827 <h2><strong>${typeName(type, showBounds: true)}</strong> |
| 822 $kind | 828 $kind |
| 823 </h2> | 829 </h2> |
| 824 '''); | 830 '''); |
| 825 writeln('<button id="show-inherited" class="show-inherited">' | 831 writeln('<button id="show-inherited" class="show-inherited">' |
| 826 'Hide inherited</button>'); | 832 'Hide inherited</button>'); |
| 827 | 833 |
| (...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1505 /** Gets whether or not the given URL is absolute or relative. */ | 1511 /** Gets whether or not the given URL is absolute or relative. */ |
| 1506 bool isAbsolute(String url) { | 1512 bool isAbsolute(String url) { |
| 1507 // TODO(rnystrom): Why don't we have a nice type in the platform for this? | 1513 // TODO(rnystrom): Why don't we have a nice type in the platform for this? |
| 1508 // TODO(rnystrom): This is a bit hackish. We consider any URL that lacks | 1514 // TODO(rnystrom): This is a bit hackish. We consider any URL that lacks |
| 1509 // a scheme to be relative. | 1515 // a scheme to be relative. |
| 1510 return const RegExp(r'^\w+:').hasMatch(url); | 1516 return const RegExp(r'^\w+:').hasMatch(url); |
| 1511 } | 1517 } |
| 1512 | 1518 |
| 1513 /** Gets the URL to the documentation for [library]. */ | 1519 /** Gets the URL to the documentation for [library]. */ |
| 1514 String libraryUrl(LibraryMirror library) { | 1520 String libraryUrl(LibraryMirror library) { |
| 1515 return '${sanitize(library.simpleName)}.html'; | 1521 return '${sanitize(printedName(library))}.html'; |
| 1516 } | 1522 } |
| 1517 | 1523 |
| 1518 /** Gets the URL for the documentation for [type]. */ | 1524 /** Gets the URL for the documentation for [type]. */ |
| 1519 String typeUrl(ObjectMirror type) { | 1525 String typeUrl(ObjectMirror type) { |
| 1520 if (type is LibraryMirror) { | 1526 if (type is LibraryMirror) { |
| 1521 return '${sanitize(type.simpleName)}.html'; | 1527 return '${sanitize(type.simpleName)}.html'; |
| 1522 } | 1528 } |
| 1523 assert (type is TypeMirror); | 1529 assert (type is TypeMirror); |
| 1524 // Always get the generic type to strip off any type parameters or | 1530 // Always get the generic type to strip off any type parameters or |
| 1525 // arguments. If the type isn't generic, genericType returns `this`, so it | 1531 // arguments. If the type isn't generic, genericType returns `this`, so it |
| 1526 // works for non-generic types too. | 1532 // works for non-generic types too. |
| 1527 return '${sanitize(type.library.simpleName)}/' | 1533 return '${sanitize(printedName(type.library))}/' |
| 1528 '${type.declaration.simpleName}.html'; | 1534 '${type.declaration.simpleName}.html'; |
| 1529 } | 1535 } |
| 1530 | 1536 |
| 1531 /** Gets the URL for the documentation for [member]. */ | 1537 /** Gets the URL for the documentation for [member]. */ |
| 1532 String memberUrl(MemberMirror member) { | 1538 String memberUrl(MemberMirror member) { |
| 1533 String url = typeUrl(member.surroundingDeclaration); | 1539 String url = typeUrl(member.surroundingDeclaration); |
| 1534 return '$url#${memberAnchor(member)}'; | 1540 return '$url#${memberAnchor(member)}'; |
| 1535 } | 1541 } |
| 1536 | 1542 |
| 1537 /** Gets the anchor id for the document for [member]. */ | 1543 /** Gets the anchor id for the document for [member]. */ |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1848 final InterfaceMirror inheritedFrom; | 1854 final InterfaceMirror inheritedFrom; |
| 1849 | 1855 |
| 1850 DocComment(this.text, [this.inheritedFrom = null]) { | 1856 DocComment(this.text, [this.inheritedFrom = null]) { |
| 1851 assert(text != null && !text.trim().isEmpty); | 1857 assert(text != null && !text.trim().isEmpty); |
| 1852 } | 1858 } |
| 1853 | 1859 |
| 1854 String get html => md.markdownToHtml(text); | 1860 String get html => md.markdownToHtml(text); |
| 1855 | 1861 |
| 1856 String toString() => text; | 1862 String toString() => text; |
| 1857 } | 1863 } |
| OLD | NEW |