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

Side by Side Diff: sdk/lib/_internal/dartdoc/lib/dartdoc.dart

Issue 13861024: Have dartdoc document exports. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Code review changes Created 7 years, 8 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 *
11 * This will create a "docs" directory with the docs for your libraries. To 11 * This will create a "docs" directory with the docs for your libraries. To
12 * create these beautiful docs, dartdoc parses your library and every library 12 * create these beautiful docs, dartdoc parses your library and every library
13 * it imports (recursively). From each library, it parses all classes and 13 * it imports (recursively). From each library, it parses all classes and
14 * members, finds the associated doc comments and builds crosslinked docs from 14 * members, finds the associated doc comments and builds crosslinked docs from
15 * them. 15 * them.
16 */ 16 */
17 library dartdoc; 17 library dartdoc;
18 18
19 import 'dart:async'; 19 import 'dart:async';
20 import 'dart:io'; 20 import 'dart:io';
21 import 'dart:json' as json; 21 import 'dart:json' as json;
22 import 'dart:math'; 22 import 'dart:math';
23 import 'dart:uri'; 23 import 'dart:uri';
24 24
25 import 'package:pathos/path.dart' as pathos;
26
25 import 'classify.dart'; 27 import 'classify.dart';
26 import 'markdown.dart' as md; 28 import 'markdown.dart' as md;
27 import 'universe_serializer.dart'; 29 import 'universe_serializer.dart';
28 30
29 import 'src/dartdoc/nav.dart'; 31 import 'src/dartdoc/nav.dart';
32 import 'src/dartdoc/utils.dart';
33 import 'src/export_map.dart';
30 import 'src/json_serializer.dart' as json_serializer; 34 import 'src/json_serializer.dart' as json_serializer;
31 35
32 // TODO(rnystrom): Use "package:" URL (#4968). 36 // TODO(rnystrom): Use "package:" URL (#4968).
33 import '../../compiler/implementation/mirrors/dart2js_mirror.dart' as dart2js; 37 import '../../compiler/implementation/mirrors/dart2js_mirror.dart' as dart2js;
34 import '../../compiler/implementation/mirrors/mirrors.dart'; 38 import '../../compiler/implementation/mirrors/mirrors.dart';
35 import '../../compiler/implementation/mirrors/mirrors_util.dart'; 39 import '../../compiler/implementation/mirrors/mirrors_util.dart';
36 import '../../libraries.dart'; 40 import '../../libraries.dart';
37 41
38 part 'src/dartdoc/utils.dart';
39
40 /** 42 /**
41 * Generates completely static HTML containing everything you need to browse 43 * Generates completely static HTML containing everything you need to browse
42 * the docs. The only client side behavior is trivial stuff like syntax 44 * the docs. The only client side behavior is trivial stuff like syntax
43 * highlighting code. 45 * highlighting code.
44 */ 46 */
45 const MODE_STATIC = 0; 47 const MODE_STATIC = 0;
46 48
47 /** 49 /**
48 * Generated docs do not include baked HTML navigation. Instead, a single 50 * Generated docs do not include baked HTML navigation. Instead, a single
49 * `nav.json` file is created and the appropriate navigation is generated 51 * `nav.json` file is created and the appropriate navigation is generated
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 256
255 /** Version of the sdk or package docs are being generated for. */ 257 /** Version of the sdk or package docs are being generated for. */
256 String version; 258 String version;
257 259
258 /** Set this to select the libraries to include in the documentation. */ 260 /** Set this to select the libraries to include in the documentation. */
259 List<String> includedLibraries = const <String>[]; 261 List<String> includedLibraries = const <String>[];
260 262
261 /** Set this to select the libraries to exclude from the documentation. */ 263 /** Set this to select the libraries to exclude from the documentation. */
262 List<String> excludedLibraries = const <String>[]; 264 List<String> excludedLibraries = const <String>[];
263 265
266 /** The package root for `package:` imports. */
267 String _packageRoot;
268
269 /** The map containing all the exports for each library. */
270 ExportMap _exports;
271
264 /** 272 /**
265 * This list contains the libraries sorted in by the library name. 273 * This list contains the libraries sorted in by the library name.
266 */ 274 */
267 List<LibraryMirror> _sortedLibraries; 275 List<LibraryMirror> _sortedLibraries;
268 276
277 /** A map from absolute paths of libraries to the libraries at those paths. */
278 Map<String, LibraryMirror> _librariesByPath;
279
280 /**
281 * A map from absolute paths of hidden libraries to lists of [Export]s that
282 * export those libraries from visible libraries. This is used to determine
283 * what public library any given entity belongs to.
284 *
285 * The lists of exports are sorted so that exports that hide the fewest number
286 * of members come first.
287 */
288 Map<String, List<Export>> _hiddenLibraryExports;
289
269 /** The library that we're currently generating docs for. */ 290 /** The library that we're currently generating docs for. */
270 LibraryMirror _currentLibrary; 291 LibraryMirror _currentLibrary;
271 292
272 /** The type that we're currently generating docs for. */ 293 /** The type that we're currently generating docs for. */
273 ClassMirror _currentType; 294 ClassMirror _currentType;
274 295
275 /** The member that we're currently generating docs for. */ 296 /** The member that we're currently generating docs for. */
276 MemberMirror _currentMember; 297 MemberMirror _currentMember;
277 298
278 /** The path to the file currently being written to, relative to [outdir]. */ 299 /** The path to the file currently being written to, relative to [outdir]. */
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 var content = ''; 417 var content = '';
397 for (int i = 0; i < footerItems.length; i++) { 418 for (int i = 0; i < footerItems.length; i++) {
398 if (i > 0) { 419 if (i > 0) {
399 content += '\n'; 420 content += '\n';
400 } 421 }
401 content += '<div>${footerItems[i]}</div>'; 422 content += '<div>${footerItems[i]}</div>';
402 } 423 }
403 return content; 424 return content;
404 } 425 }
405 426
406 Future documentEntryPoint(Path entrypoint, Path libPath, Path packageRoot) { 427 Future documentLibraries(List<Uri> libraryList, Path libPath,
407 return documentLibraries(<Path>[entrypoint], libPath, packageRoot); 428 String packageRoot) {
408 } 429 _packageRoot = packageRoot;
430 _exports = new ExportMap.parse(libraryList, packageRoot);
431 var librariesToAnalyze = _exports.allExportedFiles.toList();
432 librariesToAnalyze.addAll(libraryList.map((uri) {
433 if (uri.scheme == 'file') return fileUriToPath(uri);
434 // dart2js takes "dart:*" URIs as Path objects for some reason.
435 return uri.toString();
436 }));
409 437
410 Future documentLibraries(List<Path> libraryList, Path libPath, Path packageRoo t) {
411 // TODO(amouravski): make all of these print statements into logging 438 // TODO(amouravski): make all of these print statements into logging
412 // statements. 439 // statements.
413 print('Analyzing libraries...'); 440 print('Analyzing libraries...');
414 return dart2js.analyze(libraryList, libPath, packageRoot: packageRoot, 441 return dart2js.analyze(
415 options: COMPILER_OPTIONS) 442 librariesToAnalyze.map((path) => new Path(path)).toList(), libPath,
443 packageRoot: new Path(packageRoot), options: COMPILER_OPTIONS)
416 .then((MirrorSystem mirrors) { 444 .then((MirrorSystem mirrors) {
417 print('Generating documentation...'); 445 print('Generating documentation...');
418 _document(mirrors); 446 _document(mirrors);
419 }); 447 });
420 } 448 }
421 449
422 void _document(MirrorSystem mirrors) { 450 void _document(MirrorSystem mirrors) {
423 _started = true; 451 _started = true;
424 452
425 // Sort the libraries by name (not key). 453 // Sort the libraries by name (not key).
426 _sortedLibraries = new List<LibraryMirror>.from( 454 _sortedLibraries = new List<LibraryMirror>.from(
427 mirrors.libraries.values.where(shouldIncludeLibrary)); 455 mirrors.libraries.values.where(shouldIncludeLibrary));
428 _sortedLibraries.sort((x, y) { 456 _sortedLibraries.sort((x, y) {
429 return displayName(x).toUpperCase().compareTo( 457 return displayName(x).toUpperCase().compareTo(
430 displayName(y).toUpperCase()); 458 displayName(y).toUpperCase());
431 }); 459 });
432 460
461 _librariesByPath = <String, LibraryMirror>{};
462 for (var library in mirrors.libraries.values) {
463 var path = _libraryPath(library);
464 if (path == null) continue;
465 path = pathos.normalize(pathos.absolute(path));
466 _librariesByPath[path] = library;
467 }
468
469 _hiddenLibraryExports = _generateHiddenLibraryExports();
470
433 // Generate the docs. 471 // Generate the docs.
434 if (mode == MODE_LIVE_NAV) { 472 if (mode == MODE_LIVE_NAV) {
435 docNavigationJson(); 473 docNavigationJson();
436 } else { 474 } else {
437 docNavigationDart(); 475 docNavigationDart();
438 } 476 }
439 477
440 docIndex(); 478 docIndex();
441 for (final library in _sortedLibraries) { 479 for (final library in _sortedLibraries) {
442 docLibrary(library); 480 docLibrary(library);
443 } 481 }
444 482
445 if (generateAppCache) { 483 if (generateAppCache) {
446 generateAppCacheManifest(); 484 generateAppCacheManifest();
447 } 485 }
448 486
487 // TODO(nweiz): properly handle exports when generating JSON.
449 // TODO(jacobr): handle arbitrary pub packages rather than just the system 488 // TODO(jacobr): handle arbitrary pub packages rather than just the system
450 // libraries. 489 // libraries.
451 var revision = '0'; 490 var revision = '0';
452 if (version != null) { 491 if (version != null) {
453 var match = new RegExp(r"_r(\d+)").firstMatch(version); 492 var match = new RegExp(r"_r(\d+)").firstMatch(version);
454 if (match != null) { 493 if (match != null) {
455 revision = match.group(1); 494 revision = match.group(1);
456 } else { 495 } else {
457 print("Warning: could not parse version: $version"); 496 print("Warning: could not parse version: $version");
458 } 497 }
(...skipping 18 matching lines...) Expand all
477 // Write out top level json file with a relative path to the library json 516 // Write out top level json file with a relative path to the library json
478 // files. 517 // files.
479 startFile("apidoc.json"); 518 startFile("apidoc.json");
480 packageManifest.location = revision; 519 packageManifest.location = revision;
481 write(json_serializer.serialize(packageManifest)); 520 write(json_serializer.serialize(packageManifest));
482 endFile(); 521 endFile();
483 522
484 _finished = true; 523 _finished = true;
485 } 524 }
486 525
526 /**
527 * Generate [_hiddenLibraryExports] from [_exports] and [_librariesByPath].
528 */
529 Map<String, List<Export>> _generateHiddenLibraryExports() {
530 // First generate a map `exported path => exporter path => Export`. The
531 // inner map makes it easier to merge multiple exports of the same library
532 // by the same exporter.
533 var hiddenLibraryExportMaps = <String, Map<String, Export>>{};
534 _exports.exports.forEach((exporter, exports) {
535 var library = _librariesByPath[exporter];
536 // TODO(nweiz): remove this check when issue 9645 is fixed.
537 if (library == null) return;
538 if (!shouldIncludeLibrary(library)) return;
539 for (var export in exports) {
540 var library = _librariesByPath[export.path];
541 // TODO(nweiz): remove this check when issue 9645 is fixed.
542 if (library == null) continue;
543 if (shouldIncludeLibrary(library)) continue;
544
545 var hiddenExports = _exports.transitiveExports(export.path)
546 .map((transitiveExport) => export.compose(transitiveExport))
547 .toList();
548 hiddenExports.add(export);
549
550 for (var hiddenExport in hiddenExports) {
551 var exportsByExporterPath = hiddenLibraryExportMaps
552 .putIfAbsent(hiddenExport.path, () => <String, Export>{});
553 addOrMergeExport(exportsByExporterPath, exporter, hiddenExport);
554 }
555 }
556 });
557
558 // Now sort the values of the inner maps of `hiddenLibraryExportMaps` to get
559 // the final value of `_hiddenLibraryExports`.
560 var hiddenLibraryExports = <String, List<Export>>{};
561 hiddenLibraryExportMaps.forEach((exporteePath, exportsByExporterPath) {
562 int rank(Export export) {
563 if (export.show.isEmpty && export.hide.isEmpty) return 0;
564 if (export.show.isEmpty) return export.hide.length;
565 // Multiply by 1000 to ensure this sorts after an export with hides.
566 return 1000 * export.show.length;
567 }
568
569 var exports = exportsByExporterPath.values.toList();
570 exports.sort((export1, export2) {
571 var comparison = Comparable.compare(rank(export1), rank(export2));
572 if (comparison != 0) return comparison;
573
574 var library1 = _librariesByPath[export1.exporter];
575 var library2 = _librariesByPath[export2.exporter];
576 return Comparable.compare(library1.displayName, library2.displayName);
577 });
578 hiddenLibraryExports[exporteePath] = exports;
579 });
580 return hiddenLibraryExports;
581 }
582
487 MdnComment lookupMdnComment(Mirror mirror) => null; 583 MdnComment lookupMdnComment(Mirror mirror) => null;
488 584
489 void startFile(String path) { 585 void startFile(String path) {
490 _filePath = new Path(path); 586 _filePath = new Path(path);
491 _file = new StringBuffer(); 587 _file = new StringBuffer();
492 } 588 }
493 589
494 void endFile() { 590 void endFile() {
495 final outPath = outputDir.join(_filePath); 591 final outPath = outputDir.join(_filePath);
496 final dir = new Directory.fromPath(outPath.directoryPath); 592 final dir = new Directory.fromPath(outPath.directoryPath);
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
861 writeHeader('${displayName(library)} Library', 957 writeHeader('${displayName(library)} Library',
862 [displayName(library), libraryUrl(library)]); 958 [displayName(library), libraryUrl(library)]);
863 writeln('<h2><strong>${displayName(library)}</strong> library</h2>'); 959 writeln('<h2><strong>${displayName(library)}</strong> library</h2>');
864 960
865 // Look for a comment for the entire library. 961 // Look for a comment for the entire library.
866 final comment = getLibraryComment(library); 962 final comment = getLibraryComment(library);
867 if (comment != null) { 963 if (comment != null) {
868 writeln('<div class="doc">${comment.html}</div>'); 964 writeln('<div class="doc">${comment.html}</div>');
869 } 965 }
870 966
967 // Document the visible libraries exported by this library.
968 docExports(library);
969
871 // Document the top-level members. 970 // Document the top-level members.
872 docMembers(library); 971 docMembers(library);
873 972
874 // Document the types. 973 // Document the types.
875 final interfaces = <ClassMirror>[]; 974 final interfaces = <ClassMirror>[];
876 final abstractClasses = <ClassMirror>[]; 975 final abstractClasses = <ClassMirror>[];
877 final classes = <ClassMirror>[]; 976 final classes = <ClassMirror>[];
878 final typedefs = <TypedefMirror>[]; 977 final typedefs = <TypedefMirror>[];
879 final exceptions = <ClassMirror>[]; 978 final exceptions = <ClassMirror>[];
880 979
881 for (ClassMirror type in orderByName(library.classes.values)) { 980 var allClasses = _libraryClasses(library);
981 for (ClassMirror type in orderByName(allClasses)) {
882 if (!showPrivate && type.isPrivate) continue; 982 if (!showPrivate && type.isPrivate) continue;
883 983
884 if (isException(type)) { 984 if (isException(type)) {
885 exceptions.add(type); 985 exceptions.add(type);
886 } else if (type.isClass) { 986 } else if (type.isClass) {
887 if (type.isAbstract) { 987 if (type.isAbstract) {
888 abstractClasses.add(type); 988 abstractClasses.add(type);
889 } else { 989 } else {
890 classes.add(type); 990 classes.add(type);
891 } 991 }
892 } else if (type.isInterface){ 992 } else if (type.isInterface){
893 interfaces.add(type); 993 interfaces.add(type);
894 } else if (type is TypedefMirror) { 994 } else if (type is TypedefMirror) {
895 typedefs.add(type); 995 typedefs.add(type);
896 } else { 996 } else {
897 throw new InternalError("internal error: unknown type $type."); 997 throw new InternalError("internal error: unknown type $type.");
898 } 998 }
899 } 999 }
900 1000
901 docTypes(interfaces, 'Interfaces'); 1001 docTypes(interfaces, 'Interfaces');
902 docTypes(abstractClasses, 'Abstract Classes'); 1002 docTypes(abstractClasses, 'Abstract Classes');
903 docTypes(classes, 'Classes'); 1003 docTypes(classes, 'Classes');
904 docTypes(typedefs, 'Typedefs'); 1004 docTypes(typedefs, 'Typedefs');
905 docTypes(exceptions, 'Exceptions'); 1005 docTypes(exceptions, 'Exceptions');
906 1006
907 writeFooter(); 1007 writeFooter();
908 endFile(); 1008 endFile();
909 1009
910 for (final type in library.classes.values) { 1010 for (final type in allClasses) {
911 if (!showPrivate && type.isPrivate) continue; 1011 if (!showPrivate && type.isPrivate) continue;
912 1012
913 docType(type); 1013 docType(type);
914 } 1014 }
915 } 1015 }
916 1016
917 void docTypes(List types, String header) { 1017 void docTypes(List types, String header) {
918 if (types.length == 0) return; 1018 if (types.length == 0) return;
919 1019
920 writeln('<div>'); 1020 writeln('<div>');
(...skipping 27 matching lines...) Expand all
948 } else if (type.isClass) { 1048 } else if (type.isClass) {
949 if (type.isAbstract) { 1049 if (type.isAbstract) {
950 kind = 'abstract class'; 1050 kind = 'abstract class';
951 } else { 1051 } else {
952 kind = 'class'; 1052 kind = 'class';
953 } 1053 }
954 } 1054 }
955 1055
956 final typeTitle = 1056 final typeTitle =
957 '${typeName(type)} ${kind}'; 1057 '${typeName(type)} ${kind}';
958 writeHeader('$typeTitle / ${displayName(type.library)} Library', 1058 var library = _libraryFor(type);
959 [displayName(type.library), libraryUrl(type.library), 1059 writeHeader('$typeTitle / ${displayName(library)} Library',
1060 [displayName(library), libraryUrl(library),
960 typeName(type), typeUrl(type)]); 1061 typeName(type), typeUrl(type)]);
961 writeln( 1062 writeln(
962 ''' 1063 '''
963 <h2><strong>${typeName(type, showBounds: true)}</strong> 1064 <h2><strong>${typeName(type, showBounds: true)}</strong>
964 $kind 1065 $kind
965 </h2> 1066 </h2>
966 '''); 1067 ''');
967 writeln('<button id="show-inherited" class="show-inherited">' 1068 writeln('<button id="show-inherited" class="show-inherited">'
968 'Hide inherited</button>'); 1069 'Hide inherited</button>');
969 1070
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 1242
1142 static final Map<String, int> operatorOrderMap = (){ 1243 static final Map<String, int> operatorOrderMap = (){
1143 var map = new Map<String, int>(); 1244 var map = new Map<String, int>();
1144 var index = 0; 1245 var index = 0;
1145 for (String operator in operatorOrder) { 1246 for (String operator in operatorOrder) {
1146 map[operator] = index++; 1247 map[operator] = index++;
1147 } 1248 }
1148 return map; 1249 return map;
1149 }(); 1250 }();
1150 1251
1252 void docExports(LibraryMirror library) {
1253 // TODO(nweiz): show `dart:` library exports.
1254 var exportLinks = _exports.transitiveExports(_libraryPath(library))
1255 .map((export) {
1256 var library = _librariesByPath[export.path];
1257 // TODO(nweiz): remove this check when issue 9645 is fixed.
1258 if (library == null) return null;
1259 // Only link to publically visible libraries.
1260 if (!shouldIncludeLibrary(library)) return null;
1261
1262 var memberNames = export.show.isEmpty ? export.hide : export.show;
1263 var memberLinks = memberNames.map((name) {
1264 return md.renderToHtml([resolveNameReference(
1265 name, currentLibrary: library)]);
1266 }).join(', ');
1267 var combinator = '';
1268 if (!export.show.isEmpty) {
1269 combinator = ' show $memberLinks';
1270 } else if (!export.hide.isEmpty) {
1271 combinator = ' hide $memberLinks';
1272 }
1273
1274 return '<ul>${a(libraryUrl(library), displayName(library))}'
1275 '$combinator</ul>';
1276 }).where((link) => link != null);
1277
1278 if (!exportLinks.isEmpty) {
1279 writeln('<h3>Exports</h3>');
1280 writeln('<ul>');
1281 writeln(exportLinks.join('\n'));
1282 writeln('</ul>');
1283 }
1284 }
1285
1151 void docMembers(ContainerMirror host) { 1286 void docMembers(ContainerMirror host) {
1152 // Collect the different kinds of members. 1287 // Collect the different kinds of members.
1153 final staticMethods = []; 1288 final staticMethods = [];
1154 final staticGetters = new Map<String,MemberMirror>(); 1289 final staticGetters = new Map<String,MemberMirror>();
1155 final staticSetters = new Map<String,MemberMirror>(); 1290 final staticSetters = new Map<String,MemberMirror>();
1156 final memberMap = new Map<String,MemberMirror>(); 1291 final memberMap = new Map<String,MemberMirror>();
1157 final instanceMethods = []; 1292 final instanceMethods = [];
1158 final instanceOperators = []; 1293 final instanceOperators = [];
1159 final instanceGetters = new Map<String,MemberMirror>(); 1294 final instanceGetters = new Map<String,MemberMirror>();
1160 final instanceSetters = new Map<String,MemberMirror>(); 1295 final instanceSetters = new Map<String,MemberMirror>();
1161 final constructors = []; 1296 final constructors = [];
1162 1297
1163 host.members.forEach((_, MemberMirror member) { 1298 var hostMembers = host is LibraryMirror ?
1164 if (!showPrivate && member.isPrivate) return; 1299 _libraryMembers(host) : host.members.values;
1300 for (var member in hostMembers) {
1301 if (!showPrivate && member.isPrivate) continue;
1165 if (host is LibraryMirror || member.isStatic) { 1302 if (host is LibraryMirror || member.isStatic) {
1166 if (member is MethodMirror) { 1303 if (member is MethodMirror) {
1167 if (member.isGetter) { 1304 if (member.isGetter) {
1168 staticGetters[member.displayName] = member; 1305 staticGetters[member.displayName] = member;
1169 } else if (member.isSetter) { 1306 } else if (member.isSetter) {
1170 staticSetters[member.displayName] = member; 1307 staticSetters[member.displayName] = member;
1171 } else { 1308 } else {
1172 staticMethods.add(member); 1309 staticMethods.add(member);
1173 } 1310 }
1174 } else if (member is VariableMirror) { 1311 } else if (member is VariableMirror) {
1175 staticGetters[member.displayName] = member; 1312 staticGetters[member.displayName] = member;
1176 } 1313 }
1177 } 1314 }
1178 }); 1315 }
1179 1316
1180 if (host is ClassMirror) { 1317 if (host is ClassMirror) {
1181 var iterable = new HierarchyIterable(host, includeType: true); 1318 var iterable = new HierarchyIterable(host, includeType: true);
1182 for (ClassMirror type in iterable) { 1319 for (ClassMirror type in iterable) {
1183 if (!host.isObject && !inheritFromObject && type.isObject) continue; 1320 if (!host.isObject && !inheritFromObject && type.isObject) continue;
1184 1321
1185 type.members.forEach((_, MemberMirror member) { 1322 type.members.forEach((_, MemberMirror member) {
1186 if (member.isStatic) return; 1323 if (member.isStatic) return;
1187 if (!showPrivate && member.isPrivate) return; 1324 if (!showPrivate && member.isPrivate) return;
1188 1325
(...skipping 23 matching lines...) Expand all
1212 } 1349 }
1213 } 1350 }
1214 1351
1215 bool allMethodsInherited = true; 1352 bool allMethodsInherited = true;
1216 bool allPropertiesInherited = true; 1353 bool allPropertiesInherited = true;
1217 bool allOperatorsInherited = true; 1354 bool allOperatorsInherited = true;
1218 memberMap.forEach((_, MemberMirror member) { 1355 memberMap.forEach((_, MemberMirror member) {
1219 if (member is MethodMirror) { 1356 if (member is MethodMirror) {
1220 if (member.isGetter) { 1357 if (member.isGetter) {
1221 instanceGetters[member.displayName] = member; 1358 instanceGetters[member.displayName] = member;
1222 if (member.owner == host) { 1359 if (_ownerFor(member) == host) {
1223 allPropertiesInherited = false; 1360 allPropertiesInherited = false;
1224 } 1361 }
1225 } else if (member.isSetter) { 1362 } else if (member.isSetter) {
1226 instanceSetters[member.displayName] = member; 1363 instanceSetters[member.displayName] = member;
1227 if (member.owner == host) { 1364 if (_ownerFor(member) == host) {
1228 allPropertiesInherited = false; 1365 allPropertiesInherited = false;
1229 } 1366 }
1230 } else if (member.isOperator) { 1367 } else if (member.isOperator) {
1231 instanceOperators.add(member); 1368 instanceOperators.add(member);
1232 if (member.owner == host) { 1369 if (_ownerFor(member) == host) {
1233 allOperatorsInherited = false; 1370 allOperatorsInherited = false;
1234 } 1371 }
1235 } else { 1372 } else {
1236 instanceMethods.add(member); 1373 instanceMethods.add(member);
1237 if (member.owner == host) { 1374 if (_ownerFor(member) == host) {
1238 allMethodsInherited = false; 1375 allMethodsInherited = false;
1239 } 1376 }
1240 } 1377 }
1241 } else if (member is VariableMirror) { 1378 } else if (member is VariableMirror) {
1242 instanceGetters[member.displayName] = member; 1379 instanceGetters[member.displayName] = member;
1243 if (member.owner == host) { 1380 if (_ownerFor(member) == host) {
1244 allPropertiesInherited = false; 1381 allPropertiesInherited = false;
1245 } 1382 }
1246 } 1383 }
1247 }); 1384 });
1248 1385
1249 instanceOperators.sort((MethodMirror a, MethodMirror b) { 1386 instanceOperators.sort((MethodMirror a, MethodMirror b) {
1250 return operatorOrderMap[a.simpleName].compareTo( 1387 return operatorOrderMap[a.simpleName].compareTo(
1251 operatorOrderMap[b.simpleName]); 1388 operatorOrderMap[b.simpleName]);
1252 }); 1389 });
1253 1390
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1298 assert(getter is MethodMirror); 1435 assert(getter is MethodMirror);
1299 docProperty(host, getter, null); 1436 docProperty(host, getter, null);
1300 } 1437 }
1301 } else if (getter == null) { 1438 } else if (getter == null) {
1302 // We only have a setter => Document as a method. 1439 // We only have a setter => Document as a method.
1303 assert(setter is MethodMirror); 1440 assert(setter is MethodMirror);
1304 docMethod(host, setter); 1441 docMethod(host, setter);
1305 } else { 1442 } else {
1306 DocComment getterComment = getMemberComment(getter); 1443 DocComment getterComment = getMemberComment(getter);
1307 DocComment setterComment = getMemberComment(setter); 1444 DocComment setterComment = getMemberComment(setter);
1308 if (getter.owner != setter.owner || 1445 if (_ownerFor(getter) != _ownerFor(setter) ||
1309 getterComment != null && setterComment != null) { 1446 getterComment != null && setterComment != null) {
1310 // Both have comments or are not declared in the same class 1447 // Both have comments or are not declared in the same class
1311 // => Documents separately. 1448 // => Documents separately.
1312 if (getter is VariableMirror) { 1449 if (getter is VariableMirror) {
1313 // Document field as a getter (setter is inherited). 1450 // Document field as a getter (setter is inherited).
1314 docField(host, getter, asGetter: true); 1451 docField(host, getter, asGetter: true);
1315 } else { 1452 } else {
1316 docMethod(host, getter); 1453 docMethod(host, getter);
1317 } 1454 }
1318 if (setter is VariableMirror) { 1455 if (setter is VariableMirror) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1369 if (member.isGetter) { 1506 if (member.isGetter) {
1370 // Getter. 1507 // Getter.
1371 name = 'get $name'; 1508 name = 'get $name';
1372 } else if (member.isSetter) { 1509 } else if (member.isSetter) {
1373 // Setter. 1510 // Setter.
1374 name = 'set $name'; 1511 name = 'set $name';
1375 } 1512 }
1376 } 1513 }
1377 1514
1378 bool showCode = includeSource && !isAbstract; 1515 bool showCode = includeSource && !isAbstract;
1379 bool inherited = host != member.owner; 1516 bool inherited = host != member.owner && member.owner is! LibraryMirror;
1380 1517
1381 writeln('<div class="method${inherited ? ' inherited': ''}">' 1518 writeln('<div class="method${inherited ? ' inherited': ''}">'
1382 '<h4 id="${memberAnchor(member)}">'); 1519 '<h4 id="${memberAnchor(member)}">');
1383 1520
1384 if (showCode) { 1521 if (showCode) {
1385 writeln('<button class="show-code">Code</button>'); 1522 writeln('<button class="show-code">Code</button>');
1386 } 1523 }
1387 1524
1388 if (member is MethodMirror) { 1525 if (member is MethodMirror) {
1389 if (member.isConstructor) { 1526 if (member.isConstructor) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1460 * [host]. If [getter] is a [FieldMirror], [setter] must be [:null:]. 1597 * [host]. If [getter] is a [FieldMirror], [setter] must be [:null:].
1461 * Otherwise, if [getter] is a [MethodMirror], the property is considered 1598 * Otherwise, if [getter] is a [MethodMirror], the property is considered
1462 * final if [setter] is [:null:]. 1599 * final if [setter] is [:null:].
1463 */ 1600 */
1464 void docProperty(ContainerMirror host, 1601 void docProperty(ContainerMirror host,
1465 MemberMirror getter, MemberMirror setter) { 1602 MemberMirror getter, MemberMirror setter) {
1466 assert(getter != null); 1603 assert(getter != null);
1467 _totalMembers++; 1604 _totalMembers++;
1468 _currentMember = getter; 1605 _currentMember = getter;
1469 1606
1470 bool inherited = host != getter.owner; 1607 bool inherited = host != getter.owner && getter.owner is! LibraryMirror;
1471 1608
1472 writeln('<div class="field${inherited ? ' inherited' : ''}">' 1609 writeln('<div class="field${inherited ? ' inherited' : ''}">'
1473 '<h4 id="${memberAnchor(getter)}">'); 1610 '<h4 id="${memberAnchor(getter)}">');
1474 1611
1475 if (includeSource) { 1612 if (includeSource) {
1476 writeln('<button class="show-code">Code</button>'); 1613 writeln('<button class="show-code">Code</button>');
1477 } 1614 }
1478 1615
1479 bool isConst = false; 1616 bool isConst = false;
1480 bool isFinal; 1617 bool isFinal;
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 String typeUrl(ContainerMirror type) { 1804 String typeUrl(ContainerMirror type) {
1668 if (type is LibraryMirror) { 1805 if (type is LibraryMirror) {
1669 return '${sanitize(type.simpleName)}.html'; 1806 return '${sanitize(type.simpleName)}.html';
1670 } 1807 }
1671 if (type.library == null) { 1808 if (type.library == null) {
1672 return ''; 1809 return '';
1673 } 1810 }
1674 // Always get the generic type to strip off any type parameters or 1811 // Always get the generic type to strip off any type parameters or
1675 // arguments. If the type isn't generic, genericType returns `this`, so it 1812 // arguments. If the type isn't generic, genericType returns `this`, so it
1676 // works for non-generic types too. 1813 // works for non-generic types too.
1677 return '${sanitize(displayName(type.library))}/' 1814 return '${sanitize(displayName(_libraryFor(type)))}/'
1678 '${type.originalDeclaration.simpleName}.html'; 1815 '${type.originalDeclaration.simpleName}.html';
1679 } 1816 }
1680 1817
1681 /** Gets the URL for the documentation for [member]. */ 1818 /** Gets the URL for the documentation for [member]. */
1682 String memberUrl(MemberMirror member) { 1819 String memberUrl(MemberMirror member) {
1683 String url = typeUrl(member.owner); 1820 String url = typeUrl(_ownerFor(member));
1684 return '$url#${memberAnchor(member)}'; 1821 return '$url#${memberAnchor(member)}';
1685 } 1822 }
1686 1823
1687 /** Gets the anchor id for the document for [member]. */ 1824 /** Gets the anchor id for the document for [member]. */
1688 String memberAnchor(MemberMirror member) { 1825 String memberAnchor(MemberMirror member) {
1689 return member.simpleName; 1826 return member.simpleName;
1690 } 1827 }
1691 1828
1692 /** 1829 /**
1693 * Creates a hyperlink. Handles turning the [href] into an appropriate 1830 * Creates a hyperlink. Handles turning the [href] into an appropriate
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1752 if (type.isTypeVariable) { 1889 if (type.isTypeVariable) {
1753 // If we're using a type parameter within the body of a generic class then 1890 // If we're using a type parameter within the body of a generic class then
1754 // just link back up to the class. 1891 // just link back up to the class.
1755 write(a(typeUrl(enclosingType), type.simpleName)); 1892 write(a(typeUrl(enclosingType), type.simpleName));
1756 return; 1893 return;
1757 } 1894 }
1758 1895
1759 assert(type is ClassMirror); 1896 assert(type is ClassMirror);
1760 1897
1761 // Link to the type. 1898 // Link to the type.
1762 if (shouldLinkToPublicApi(type.library)) { 1899 var library = _libraryFor(type);
1900 if (shouldLinkToPublicApi(library)) {
1763 write('<a href="$API_LOCATION${typeUrl(type)}">${type.simpleName}</a>'); 1901 write('<a href="$API_LOCATION${typeUrl(type)}">${type.simpleName}</a>');
1764 } else if (shouldIncludeLibrary(type.library)) { 1902 } else if (shouldIncludeLibrary(library)) {
1765 write(a(typeUrl(type), type.simpleName)); 1903 write(a(typeUrl(type), type.simpleName));
1766 } else { 1904 } else {
1767 write(type.simpleName); 1905 write(type.simpleName);
1768 } 1906 }
1769 1907
1770 if (type.isOriginalDeclaration) { 1908 if (type.isOriginalDeclaration) {
1771 // Avoid calling [:typeArguments():] on a declaration. 1909 // Avoid calling [:typeArguments():] on a declaration.
1772 return; 1910 return;
1773 } 1911 }
1774 1912
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1972 onDone: () => endFile()); 2110 onDone: () => endFile());
1973 } 2111 }
1974 2112
1975 /** 2113 /**
1976 * Returns [:true:] if [type] should be regarded as an exception. 2114 * Returns [:true:] if [type] should be regarded as an exception.
1977 */ 2115 */
1978 bool isException(TypeMirror type) { 2116 bool isException(TypeMirror type) {
1979 return type.simpleName.endsWith('Exception') || 2117 return type.simpleName.endsWith('Exception') ||
1980 type.simpleName.endsWith('Error'); 2118 type.simpleName.endsWith('Error');
1981 } 2119 }
2120
2121 /**
2122 * Returns the absolute path to [library] on the filesystem, or `null` if the
2123 * library doesn't exist on the local filesystem.
2124 */
2125 String _libraryPath(LibraryMirror library) =>
2126 importUriToPath(library.uri, packageRoot: _packageRoot);
2127
2128 /**
2129 * Returns a list of classes in [library], including classes it exports from
2130 * hidden libraries.
2131 */
2132 List<ClassMirror> _libraryClasses(LibraryMirror library) =>
2133 _libraryContents(library, (lib) => lib.classes.values);
2134
2135 /**
2136 * Returns a list of top-level members in [library], including members it
2137 * exports from hidden libraries.
2138 */
2139 List<MemberMirror> _libraryMembers(LibraryMirror library) =>
2140 _libraryContents(library, (lib) => lib.members.values);
2141
2142
2143 /**
2144 * Returns a list of elements in [library], including elements it exports from
2145 * hidden libraries. [fn] should return the element list for a single library,
2146 * which will then be merged across all exported libraries.
2147 */
2148 List<DeclarationMirror> _libraryContents(LibraryMirror library,
2149 List<DeclarationMirror> fn(LibraryMirror)) {
2150 var contents = fn(library).toList();
2151 var path = _libraryPath(library);
2152 if (path == null) return contents;
2153
2154 contents.addAll(_exports.exports[path].expand((export) {
2155 var exportedLibrary = _librariesByPath[export.path];
2156 // TODO(nweiz): remove this check when issue 9645 is fixed.
2157 if (exportedLibrary == null) return [];
2158 if (shouldIncludeLibrary(exportedLibrary)) return [];
2159 return fn(exportedLibrary).where((declaration) =>
2160 export.isMemberVisible(declaration.displayName));
2161 }));
2162 return contents;
2163 }
2164
2165 /**
2166 * Returns the library in which [type] was defined. If [type] was defined in a
2167 * hidden library that was exported by another library, this returns the
2168 * exporter.
2169 */
2170 LibraryMirror _libraryFor(TypeMirror type) =>
2171 _visibleLibrary(type.library, type.displayName);
2172
2173 /**
2174 * Returns the owner of [declaration]. If [declaration]'s owner is a hidden
2175 * library that was exported by another library, this returns the exporter.
2176 */
2177 DeclarationMirror _ownerFor(DeclarationMirror declaration) {
2178 var owner = declaration.owner;
2179 if (owner is! LibraryMirror) return owner;
2180 return _visibleLibrary(owner, declaration.displayName);
2181 }
2182
2183 /**
2184 * Returns the best visible library that exports [name] from [library]. If
2185 * [library] is public, it will be returned.
2186 */
2187 LibraryMirror _visibleLibrary(LibraryMirror library, String name) {
2188 if (library == null) return null;
2189
2190 var exports = _hiddenLibraryExports[_libraryPath(library)];
2191 if (exports == null) return library;
2192
2193 var export = exports.firstWhere(
2194 (exp) => exp.isMemberVisible(name),
2195 orElse: () => null);
2196 if (export == null) return library;
2197 return _librariesByPath[export.exporter];
2198 }
1982 } 2199 }
1983 2200
1984 /** 2201 /**
1985 * Used to report an unexpected error in the DartDoc tool or the 2202 * Used to report an unexpected error in the DartDoc tool or the
1986 * underlying data 2203 * underlying data
1987 */ 2204 */
1988 class InternalError { 2205 class InternalError {
1989 final String message; 2206 final String message;
1990 const InternalError(this.message); 2207 const InternalError(this.message);
1991 String toString() => "InternalError: '$message'"; 2208 String toString() => "InternalError: '$message'";
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2069 return ''' 2286 return '''
2070 <div class="mdn"> 2287 <div class="mdn">
2071 $mdnComment 2288 $mdnComment
2072 <div class="mdn-note"><a href="$mdnUrl">from MDN</a></div> 2289 <div class="mdn-note"><a href="$mdnUrl">from MDN</a></div>
2073 </div> 2290 </div>
2074 '''; 2291 ''';
2075 } 2292 }
2076 2293
2077 String toString() => mdnComment; 2294 String toString() => mdnComment;
2078 } 2295 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/dartdoc/bin/dartdoc.dart ('k') | sdk/lib/_internal/dartdoc/lib/src/dartdoc/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698