Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(329)

Side by Side Diff: pkg/dartdoc/dartdoc.dart

Issue 10829361: 'Find-as-you-type'-search in dartdoc/apidoc. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/dartdoc/client-static.dart ('k') | pkg/dartdoc/dropdown.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 12 matching lines...) Expand all
23 #import('mirrors/mirrors.dart'); 23 #import('mirrors/mirrors.dart');
24 #import('mirrors/mirrors_util.dart'); 24 #import('mirrors/mirrors_util.dart');
25 #import('mirrors/dart2js_mirror.dart', prefix: 'dart2js'); 25 #import('mirrors/dart2js_mirror.dart', prefix: 'dart2js');
26 #import('classify.dart'); 26 #import('classify.dart');
27 #import('markdown.dart', prefix: 'md'); 27 #import('markdown.dart', prefix: 'md');
28 #import('../../lib/compiler/implementation/scanner/scannerlib.dart', 28 #import('../../lib/compiler/implementation/scanner/scannerlib.dart',
29 prefix: 'dart2js'); 29 prefix: 'dart2js');
30 #import('../../lib/compiler/implementation/library_map.dart'); 30 #import('../../lib/compiler/implementation/library_map.dart');
31 31
32 #source('comment_map.dart'); 32 #source('comment_map.dart');
33 #source('nav.dart');
33 #source('utils.dart'); 34 #source('utils.dart');
34 35
35 // TODO(johnniwinther): Note that [IN_SDK] gets initialized to true when this 36 // TODO(johnniwinther): Note that [IN_SDK] gets initialized to true when this
36 // file is modified by the SDK deployment script. If you change, be sure to test 37 // file is modified by the SDK deployment script. If you change, be sure to test
37 // that dartdoc still works when run from the built SDK directory. 38 // that dartdoc still works when run from the built SDK directory.
38 final bool IN_SDK = false; 39 final bool IN_SDK = false;
39 40
40 /** 41 /**
41 * Generates completely static HTML containing everything you need to browse 42 * Generates completely static HTML containing everything you need to browse
42 * the docs. The only client side behavior is trivial stuff like syntax 43 * the docs. The only client side behavior is trivial stuff like syntax
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 // Compile the client-side code to JS. 154 // Compile the client-side code to JS.
154 final clientScript = (dartdoc.mode == MODE_STATIC) ? 'static' : 'live-nav'; 155 final clientScript = (dartdoc.mode == MODE_STATIC) ? 'static' : 'live-nav';
155 Future compiled = compileScript( 156 Future compiled = compileScript(
156 scriptDir.append('client-$clientScript.dart'), 157 scriptDir.append('client-$clientScript.dart'),
157 dartdoc.outputDir.append('client-$clientScript.js')); 158 dartdoc.outputDir.append('client-$clientScript.js'));
158 159
159 Future filesCopied = copyDirectory(scriptDir.append('static'), 160 Future filesCopied = copyDirectory(scriptDir.append('static'),
160 dartdoc.outputDir); 161 dartdoc.outputDir);
161 162
162 Futures.wait([compiled, filesCopied]).then((_) { 163 Futures.wait([compiled, filesCopied]).then((_) {
164 dartdoc.cleanup();
163 print('Documented ${dartdoc._totalLibraries} libraries, ' 165 print('Documented ${dartdoc._totalLibraries} libraries, '
164 '${dartdoc._totalTypes} types, and ' 166 '${dartdoc._totalTypes} types, and '
165 '${dartdoc._totalMembers} members.'); 167 '${dartdoc._totalMembers} members.');
166 }); 168 });
167 } 169 }
168 170
169 void printUsage() { 171 void printUsage() {
170 print(''' 172 print('''
171 Usage dartdoc [options] <entrypoint(s)> 173 Usage dartdoc [options] <entrypoint(s)>
172 [options] include 174 [options] include
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 * want the client-side behavior to be. The value for this should be one of 309 * want the client-side behavior to be. The value for this should be one of
308 * the `MODE_` constants. 310 * the `MODE_` constants.
309 */ 311 */
310 int mode = MODE_LIVE_NAV; 312 int mode = MODE_LIVE_NAV;
311 313
312 /** 314 /**
313 * Generates the App Cache manifest file, enabling offline doc viewing. 315 * Generates the App Cache manifest file, enabling offline doc viewing.
314 */ 316 */
315 bool generateAppCache = false; 317 bool generateAppCache = false;
316 318
319 /** Path to the dartdoc directory. */
320 Path dartdocPath;
321
317 /** Path to generate HTML files into. */ 322 /** Path to generate HTML files into. */
318 Path outputDir = const Path('docs'); 323 Path outputDir = const Path('docs');
319 324
320 /** 325 /**
321 * The title used for the overall generated output. Set this to change it. 326 * The title used for the overall generated output. Set this to change it.
322 */ 327 */
323 String mainTitle = 'Dart Documentation'; 328 String mainTitle = 'Dart Documentation';
324 329
325 /** 330 /**
326 * The URL that the Dart logo links to. Defaults "index.html", the main 331 * The URL that the Dart logo links to. Defaults "index.html", the main
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 Path _filePath; 386 Path _filePath;
382 387
383 /** The file currently being written to. */ 388 /** The file currently being written to. */
384 StringBuffer _file; 389 StringBuffer _file;
385 390
386 int _totalLibraries = 0; 391 int _totalLibraries = 0;
387 int _totalTypes = 0; 392 int _totalTypes = 0;
388 int _totalMembers = 0; 393 int _totalMembers = 0;
389 394
390 Dartdoc() 395 Dartdoc()
391 : _comments = new CommentMap() { 396 : _comments = new CommentMap(),
397 dartdocPath = scriptDir {
398
392 // Patch in support for [:...:]-style code to the markdown parser. 399 // Patch in support for [:...:]-style code to the markdown parser.
393 // TODO(rnystrom): Markdown already has syntax for this. Phase this out? 400 // TODO(rnystrom): Markdown already has syntax for this. Phase this out?
394 md.InlineParser.syntaxes.insertRange(0, 1, 401 md.InlineParser.syntaxes.insertRange(0, 1,
395 new md.CodeSyntax(@'\[\:((?:.|\n)*?)\:\]')); 402 new md.CodeSyntax(@'\[\:((?:.|\n)*?)\:\]'));
396 403
397 md.setImplicitLinkResolver((name) => resolveNameReference(name, 404 md.setImplicitLinkResolver((name) => resolveNameReference(name,
398 currentLibrary: _currentLibrary, currentType: _currentType, 405 currentLibrary: _currentLibrary, currentType: _currentType,
399 currentMember: _currentMember)); 406 currentMember: _currentMember));
400 } 407 }
401 408
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 // Sort the libraries by name (not key). 484 // Sort the libraries by name (not key).
478 _sortedLibraries = new List<LibraryMirror>.from( 485 _sortedLibraries = new List<LibraryMirror>.from(
479 compilation.mirrors.libraries.getValues().filter( 486 compilation.mirrors.libraries.getValues().filter(
480 shouldIncludeLibrary)); 487 shouldIncludeLibrary));
481 _sortedLibraries.sort((x, y) { 488 _sortedLibraries.sort((x, y) {
482 return x.simpleName.toUpperCase().compareTo( 489 return x.simpleName.toUpperCase().compareTo(
483 y.simpleName.toUpperCase()); 490 y.simpleName.toUpperCase());
484 }); 491 });
485 492
486 // Generate the docs. 493 // Generate the docs.
487 if (mode == MODE_LIVE_NAV) docNavigationJson(); 494 if (mode == MODE_LIVE_NAV) {
495 docNavigationJson();
496 } else {
497 docNavigationDart();
498 }
488 499
489 docIndex(); 500 docIndex();
490 for (final library in _sortedLibraries) { 501 for (final library in _sortedLibraries) {
491 docLibrary(library); 502 docLibrary(library);
492 } 503 }
493 504
494 if (generateAppCache) { 505 if (generateAppCache) {
495 generateAppCacheManifest(); 506 generateAppCacheManifest();
496 } 507 }
497 } 508 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 } 594 }
584 595
585 if (searchEngineId != null) { 596 if (searchEngineId != null) {
586 writeln( 597 writeln(
587 ''' 598 '''
588 <form action="$searchResultsUrl" id="search-box"> 599 <form action="$searchResultsUrl" id="search-box">
589 <input type="hidden" name="cx" value="$searchEngineId"> 600 <input type="hidden" name="cx" value="$searchEngineId">
590 <input type="hidden" name="ie" value="UTF-8"> 601 <input type="hidden" name="ie" value="UTF-8">
591 <input type="hidden" name="hl" value="en"> 602 <input type="hidden" name="hl" value="en">
592 <input type="search" name="q" id="q" autocomplete="off" 603 <input type="search" name="q" id="q" autocomplete="off"
593 placeholder="Search"> 604 class="search-input" placeholder="Search API">
594 </form> 605 </form>
595 '''); 606 ''');
607 } else {
608 writeln(
609 '''
610 <div id="search-box">
611 <input type="search" name="q" id="q" autocomplete="off"
612 class="search-input" placeholder="Search API">
613 </div>
614 ''');
596 } 615 }
597 616
598 writeln('</div>'); 617 writeln(
618 '''
619 </div>
620 <div class="drop-down" id="drop-down"></div>
621 ''');
599 622
600 docNavigation(); 623 docNavigation();
601 writeln('<div class="content">'); 624 writeln('<div class="content">');
602 } 625 }
603 626
604 String get clientScript() { 627 String get clientScript() {
605 switch (mode) { 628 switch (mode) {
606 case MODE_STATIC: return 'client-static'; 629 case MODE_STATIC: return 'client-static';
607 case MODE_LIVE_NAV: return 'client-live-nav'; 630 case MODE_LIVE_NAV: return 'client-live-nav';
608 default: throw 'Unknown mode $mode.'; 631 default: throw 'Unknown mode $mode.';
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 void docIndexLibrary(LibraryMirror library) { 678 void docIndexLibrary(LibraryMirror library) {
656 writeln('<h4>${a(libraryUrl(library), library.simpleName)}</h4>'); 679 writeln('<h4>${a(libraryUrl(library), library.simpleName)}</h4>');
657 } 680 }
658 681
659 /** 682 /**
660 * Walks the libraries and creates a JSON object containing the data needed 683 * Walks the libraries and creates a JSON object containing the data needed
661 * to generate navigation for them. 684 * to generate navigation for them.
662 */ 685 */
663 void docNavigationJson() { 686 void docNavigationJson() {
664 startFile('nav.json'); 687 startFile('nav.json');
665 688 writeln(JSON.stringify(createNavigationInfo()));
666 final libraryMap = {};
667
668 for (final library in _sortedLibraries) {
669 docLibraryNavigationJson(library, libraryMap);
670 }
671
672 writeln(JSON.stringify(libraryMap));
673 endFile(); 689 endFile();
674 } 690 }
675 691
676 void docLibraryNavigationJson(LibraryMirror library, Map libraryMap) { 692 void docNavigationDart() {
693 final dir = new Directory.fromPath(tmpPath);
694 if (!dir.existsSync()) {
695 // TODO(3914): Hack to avoid 'file already exists' exception
696 // thrown due to invalid result from dir.existsSync() (probably due to
697 // race conditions).
698 try {
699 dir.createSync();
700 } catch (DirectoryIOException e) {
701 // Ignore.
702 }
703 }
704 String jsonString = JSON.stringify(createNavigationInfo());
705 String dartString = jsonString.replaceAll(@"$", @"\$");
706 final filePath = tmpPath.append('nav.dart');
707 writeString(new File.fromPath(filePath),
708 'get json() => $dartString;');
709 }
710
711 Path get tmpPath() => dartdocPath.append('tmp');
712
713 void cleanup() {
714 final dir = new Directory.fromPath(tmpPath);
715 if (dir.existsSync()) {
716 dir.deleteRecursivelySync();
717 }
718 }
719
720 List createNavigationInfo() {
721 final libraryList = [];
722 for (final library in _sortedLibraries) {
723 docLibraryNavigationJson(library, libraryList);
724 }
725 return libraryList;
726 }
727
728 void docLibraryNavigationJson(LibraryMirror library, List libraryList) {
729 var libraryInfo = {};
730 libraryInfo[NAME] = library.simpleName;
731 final List members = docMembersJson(library.declaredMembers);
732 if (!members.isEmpty()) {
733 libraryInfo[MEMBERS] = members;
734 }
735
677 final types = []; 736 final types = [];
678
679 for (InterfaceMirror type in orderByName(library.types.getValues())) { 737 for (InterfaceMirror type in orderByName(library.types.getValues())) {
680 if (type.isPrivate) continue; 738 if (type.isPrivate) continue;
681 739
682 final kind = type.isClass ? 'class' : 'interface'; 740 var typeInfo = {};
683 final url = typeUrl(type); 741 typeInfo[NAME] = type.simpleName;
684 types.add({ 'name': typeName(type), 'kind': kind, 'url': url }); 742 if (type.isClass) {
743 typeInfo[KIND] = CLASS;
744 } else if (type.isInterface) {
745 typeInfo[KIND] = INTERFACE;
746 } else {
747 assert(type.isTypedef);
748 typeInfo[KIND] = TYPEDEF;
749 }
750 final List typeMembers = docMembersJson(type.declaredMembers);
751 if (!typeMembers.isEmpty()) {
752 typeInfo[MEMBERS] = typeMembers;
753 }
754
755 if (!type.declaration.typeVariables.isEmpty()) {
756 final typeVariables = [];
757 for (final typeVariable in type.declaration.typeVariables) {
758 typeVariables.add(typeVariable.simpleName);
759 }
760 typeInfo[ARGS] = Strings.join(typeVariables, ', ');
761 }
762 types.add(typeInfo);
763 }
764 if (!types.isEmpty()) {
765 libraryInfo[TYPES] = types;
685 } 766 }
686 767
687 libraryMap[library.simpleName] = types; 768 libraryList.add(libraryInfo);
769 }
770
771 List docMembersJson(Map<Object,MemberMirror> memberMap) {
772 final members = [];
773 for (MemberMirror member in orderByName(memberMap.getValues())) {
774 if (member.isPrivate) continue;
775
776 var memberInfo = {};
777 if (member.isField) {
778 memberInfo[NAME] = member.simpleName;
779 memberInfo[KIND] = FIELD;
780 } else {
781 MethodMirror method = member;
782 if (method.isConstructor) {
783 if (method.constructorName != '') {
784 memberInfo[NAME] = '${method.simpleName}.${method.constructorName}';
785 memberInfo[KIND] = CONSTRUCTOR;
786 } else {
787 memberInfo[NAME] = member.simpleName;
788 memberInfo[KIND] = CONSTRUCTOR;
789 }
790 } else if (method.isOperator) {
791 memberInfo[NAME] = '${method.simpleName} ${method.operatorName}';
792 memberInfo[KIND] = METHOD;
793 } else if (method.isSetter) {
794 memberInfo[NAME] = member.simpleName;
795 memberInfo[KIND] = SETTER;
796 } else if (method.isGetter) {
797 memberInfo[NAME] = member.simpleName;
798 memberInfo[KIND] = GETTER;
799 } else {
800 memberInfo[NAME] = member.simpleName;
801 memberInfo[KIND] = METHOD;
802 }
803 }
804 var anchor = memberAnchor(member);
805 if (anchor != memberInfo[NAME]) {
806 memberInfo[LINK_NAME] = anchor;
807 }
808 members.add(memberInfo);
809 }
810 return members;
688 } 811 }
689 812
690 void docNavigation() { 813 void docNavigation() {
691 writeln( 814 writeln(
692 ''' 815 '''
693 <div class="nav"> 816 <div class="nav">
694 '''); 817 ''');
695 818
696 if (mode == MODE_STATIC) { 819 if (mode == MODE_STATIC) {
697 for (final library in _sortedLibraries) { 820 for (final library in _sortedLibraries) {
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
1286 // Always get the generic type to strip off any type parameters or 1409 // Always get the generic type to strip off any type parameters or
1287 // arguments. If the type isn't generic, genericType returns `this`, so it 1410 // arguments. If the type isn't generic, genericType returns `this`, so it
1288 // works for non-generic types too. 1411 // works for non-generic types too.
1289 return '${sanitize(type.library.simpleName)}/' 1412 return '${sanitize(type.library.simpleName)}/'
1290 '${type.declaration.simpleName}.html'; 1413 '${type.declaration.simpleName}.html';
1291 } 1414 }
1292 1415
1293 /** Gets the URL for the documentation for [member]. */ 1416 /** Gets the URL for the documentation for [member]. */
1294 String memberUrl(MemberMirror member) { 1417 String memberUrl(MemberMirror member) {
1295 String url = typeUrl(member.surroundingDeclaration); 1418 String url = typeUrl(member.surroundingDeclaration);
1296 if (!member.isConstructor) { 1419 return '$url#${memberAnchor(member)}';
1297 return '$url#${member.simpleName}';
1298 }
1299 assert (member is MethodMirror);
1300 if (member.constructorName == '') {
1301 return '$url#new:${member.simpleName}';
1302 }
1303 return '$url#new:${member.simpleName}.${member.constructorName}';
1304 } 1420 }
1305 1421
1306 /** Gets the anchor id for the document for [member]. */ 1422 /** Gets the anchor id for the document for [member]. */
1307 String memberAnchor(MemberMirror member) { 1423 String memberAnchor(MemberMirror member) {
1308 return '${member.simpleName}'; 1424 if (member.isField) {
1425 return member.simpleName;
1426 }
1427 MethodMirror method = member;
1428 if (method.isConstructor) {
1429 if (method.constructorName == '') {
1430 return method.simpleName;
1431 } else {
1432 return '${method.simpleName}.${method.constructorName}';
1433 }
1434 } else if (method.isOperator) {
1435 return '${method.simpleName} ${method.operatorName}';
1436 } else if (method.isSetter) {
1437 return '${method.simpleName}=';
1438 } else {
1439 return method.simpleName;
1440 }
1309 } 1441 }
1310 1442
1311 /** 1443 /**
1312 * Creates a hyperlink. Handles turning the [href] into an appropriate 1444 * Creates a hyperlink. Handles turning the [href] into an appropriate
1313 * relative path from the current file. 1445 * relative path from the current file.
1314 */ 1446 */
1315 String a(String href, String contents, [String css]) { 1447 String a(String href, String contents, [String css]) {
1316 // Mark outgoing external links, mainly so we can style them. 1448 // Mark outgoing external links, mainly so we can style them.
1317 final rel = isAbsolute(href) ? ' ref="external"' : ''; 1449 final rel = isAbsolute(href) ? ' ref="external"' : '';
1318 final cssClass = css == null ? '' : ' class="$css"'; 1450 final cssClass = css == null ? '' : ' class="$css"';
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1405 } 1537 }
1406 1538
1407 /** Generates a human-friendly string representation for a type. */ 1539 /** Generates a human-friendly string representation for a type. */
1408 typeName(TypeMirror type, [bool showBounds = false]) { 1540 typeName(TypeMirror type, [bool showBounds = false]) {
1409 if (type.isVoid) { 1541 if (type.isVoid) {
1410 return 'void'; 1542 return 'void';
1411 } 1543 }
1412 if (type is TypeVariableMirror) { 1544 if (type is TypeVariableMirror) {
1413 return type.simpleName; 1545 return type.simpleName;
1414 } 1546 }
1415 assert (type is InterfaceMirror); 1547 assert(type is InterfaceMirror);
1416 1548
1417 // See if it's a generic type. 1549 // See if it's a generic type.
1418 if (type.isDeclaration) { 1550 if (type.isDeclaration) {
1419 final typeParams = []; 1551 final typeParams = [];
1420 for (final typeParam in type.declaration.typeVariables) { 1552 for (final typeParam in type.declaration.typeVariables) {
1421 if (showBounds && 1553 if (showBounds &&
1422 (typeParam.bound != null) && 1554 (typeParam.bound != null) &&
1423 !typeParam.bound.isObject) { 1555 !typeParam.bound.isObject) {
1424 final bound = typeName(typeParam.bound, showBounds: true); 1556 final bound = typeName(typeParam.bound, showBounds: true);
1425 typeParams.add('${typeParam.simpleName} extends $bound'); 1557 typeParams.add('${typeParam.simpleName} extends $bound');
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1589 } 1721 }
1590 1722
1591 /** 1723 /**
1592 * Returns [:true:] if [type] should be regarded as an exception. 1724 * Returns [:true:] if [type] should be regarded as an exception.
1593 */ 1725 */
1594 bool isException(TypeMirror type) { 1726 bool isException(TypeMirror type) {
1595 return type.simpleName.endsWith('Exception'); 1727 return type.simpleName.endsWith('Exception');
1596 } 1728 }
1597 } 1729 }
1598 1730
OLDNEW
« no previous file with comments | « pkg/dartdoc/client-static.dart ('k') | pkg/dartdoc/dropdown.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698