Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 /// **docgen** is a tool for creating machine readable representations of Dart | 5 /// **docgen** is a tool for creating machine readable representations of Dart |
| 6 /// code metadata, including: classes, members, comments and annotations. | 6 /// code metadata, including: classes, members, comments and annotations. |
| 7 /// | 7 /// |
| 8 /// docgen is run on a `.dart` file or a directory containing `.dart` files. | 8 /// docgen is run on a `.dart` file or a directory containing `.dart` files. |
| 9 /// | 9 /// |
| 10 /// $ dart docgen.dart [OPTIONS] [FILE/DIR] | 10 /// $ dart docgen.dart [OPTIONS] [FILE/DIR] |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 44 '_js_helper.Returns']; | 44 '_js_helper.Returns']; |
| 45 | 45 |
| 46 /// Set of libraries declared in the SDK, so libraries that can be accessed | 46 /// Set of libraries declared in the SDK, so libraries that can be accessed |
| 47 /// when running dart by default. | 47 /// when running dart by default. |
| 48 Iterable<LibraryMirror> _sdkLibraries; | 48 Iterable<LibraryMirror> _sdkLibraries; |
| 49 | 49 |
| 50 /// The dart:core library, which contains all types that are always available | 50 /// The dart:core library, which contains all types that are always available |
| 51 /// without import. | 51 /// without import. |
| 52 LibraryMirror _coreLibrary; | 52 LibraryMirror _coreLibrary; |
| 53 | 53 |
| 54 /// Current library being documented to be used for comment links. | |
| 55 LibraryMirror _currentLibrary; | |
|
Emily Fortuna
2013/11/18 21:00:41
yay! :-)
| |
| 56 | |
| 57 /// Current class being documented to be used for comment links. | |
| 58 ClassMirror _currentClass; | |
| 59 | |
| 60 /// Current member being documented to be used for comment links. | |
| 61 MemberMirror _currentMember; | |
| 62 | |
| 63 /// Support for [:foo:]-style code comments to the markdown parser. | 54 /// Support for [:foo:]-style code comments to the markdown parser. |
| 64 List<markdown.InlineSyntax> markdownSyntaxes = | 55 List<markdown.InlineSyntax> markdownSyntaxes = |
| 65 [new markdown.CodeSyntax(r'\[:\s?((?:.|\n)*?)\s?:\]')]; | 56 [new markdown.CodeSyntax(r'\[:\s?((?:.|\n)*?)\s?:\]')]; |
| 66 | 57 |
| 67 /// Resolves reference links in doc comments. | |
| 68 markdown.Resolver linkResolver; | |
| 69 | |
| 70 /// Index of all indexable items. This also ensures that no class is | 58 /// Index of all indexable items. This also ensures that no class is |
| 71 /// created more than once. | 59 /// created more than once. |
| 72 Map<String, Indexable> entityMap = new Map<String, Indexable>(); | 60 Map<String, Indexable> entityMap = new Map<String, Indexable>(); |
| 73 | 61 |
| 74 /// This is set from the command line arguments flag --include-private | 62 /// This is set from the command line arguments flag --include-private |
| 75 bool _includePrivate = false; | 63 bool _includePrivate = false; |
| 76 | 64 |
| 77 // TODO(janicejl): Make MDN content generic or pluggable. Maybe move | 65 // TODO(janicejl): Make MDN content generic or pluggable. Maybe move |
| 78 // MDN-specific code to its own library that is imported into the default impl? | 66 // MDN-specific code to its own library that is imported into the default impl? |
| 79 /// Map of all the comments for dom elements from MDN. | 67 /// Map of all the comments for dom elements from MDN. |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 101 if (packageRoot == null && !parseSdk) { | 89 if (packageRoot == null && !parseSdk) { |
| 102 var type = FileSystemEntity.typeSync(files.first); | 90 var type = FileSystemEntity.typeSync(files.first); |
| 103 if (type == FileSystemEntityType.DIRECTORY) { | 91 if (type == FileSystemEntityType.DIRECTORY) { |
| 104 packageRoot = _findPackageRoot(files.first); | 92 packageRoot = _findPackageRoot(files.first); |
| 105 } else if (type == FileSystemEntityType.FILE) { | 93 } else if (type == FileSystemEntityType.FILE) { |
| 106 logger.warning('WARNING: No package root defined. If Docgen fails, try ' | 94 logger.warning('WARNING: No package root defined. If Docgen fails, try ' |
| 107 'again by setting the --package-root option.'); | 95 'again by setting the --package-root option.'); |
| 108 } | 96 } |
| 109 } | 97 } |
| 110 logger.info('Package Root: ${packageRoot}'); | 98 logger.info('Package Root: ${packageRoot}'); |
| 111 linkResolver = (name) => | |
| 112 fixReference(name, _currentLibrary, _currentClass, _currentMember); | |
| 113 | 99 |
| 114 return getMirrorSystem(files, packageRoot: packageRoot, parseSdk: parseSdk) | 100 return getMirrorSystem(files, packageRoot: packageRoot, parseSdk: parseSdk) |
| 115 .then((MirrorSystem mirrorSystem) { | 101 .then((MirrorSystem mirrorSystem) { |
| 116 if (mirrorSystem.libraries.isEmpty) { | 102 if (mirrorSystem.libraries.isEmpty) { |
| 117 throw new StateError('No library mirrors were created.'); | 103 throw new StateError('No library mirrors were created.'); |
| 118 } | 104 } |
| 119 var librariesWeAskedFor = _listLibraries(files); | 105 var librariesWeAskedFor = _listLibraries(files); |
| 120 var librariesWeGot = mirrorSystem.libraries.values.where( | 106 var librariesWeGot = mirrorSystem.libraries.values.where( |
| 121 (each) => each.uri.scheme == 'file'); | 107 (each) => each.uri.scheme == 'file'); |
| 122 _sdkLibraries = mirrorSystem.libraries.values.where( | 108 _sdkLibraries = mirrorSystem.libraries.values.where( |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 136 return true; | 122 return true; |
| 137 }); | 123 }); |
| 138 } | 124 } |
| 139 | 125 |
| 140 /// For a library's [mirror], determine the name of the package (if any) we | 126 /// For a library's [mirror], determine the name of the package (if any) we |
| 141 /// believe it came from (because of its file URI). | 127 /// believe it came from (because of its file URI). |
| 142 /// | 128 /// |
| 143 /// If [library] is specified, we set the packageName field. If no package could | 129 /// If [library] is specified, we set the packageName field. If no package could |
| 144 /// be determined, we return an empty string. | 130 /// be determined, we return an empty string. |
| 145 String _findPackage(LibraryMirror mirror, [Library library]) { | 131 String _findPackage(LibraryMirror mirror, [Library library]) { |
| 132 if (mirror == null) return ''; | |
| 146 if (mirror.uri.scheme != 'file') return ''; | 133 if (mirror.uri.scheme != 'file') return ''; |
| 147 var filePath = mirror.uri.toFilePath(); | 134 var filePath = mirror.uri.toFilePath(); |
| 148 // We assume that we are documenting only libraries under package/lib | 135 // We assume that we are documenting only libraries under package/lib |
| 149 var rootdir = path.dirname((path.dirname(filePath))); | 136 var rootdir = path.dirname((path.dirname(filePath))); |
| 150 var pubspec = path.join(rootdir, 'pubspec.yaml'); | 137 var pubspec = path.join(rootdir, 'pubspec.yaml'); |
| 151 var packageName = _packageName(pubspec); | 138 var packageName = _packageName(pubspec); |
| 152 if (library != null) { | 139 if (library != null) { |
| 153 library.packageName = packageName; | 140 library.packageName = packageName; |
| 154 // If we are the main library in a package, associate the package readme | 141 // If we are the main library in a package, associate the package readme |
| 155 // with us. | 142 // with us. |
| 156 // TODO(alanknight): We can't really rely on all packages having a library | 143 // TODO(alanknight): We can't really rely on all packages having a library |
| 157 // that matches the package name. Need a better way to store this. | 144 // that matches the package name. Need a better way to store this. |
| 158 if (library.packageName == library.name) { | 145 if (library.packageName == library.name) { |
| 159 library.packageIntro = _packageIntro(rootdir); | 146 library.packageIntro = _packageIntro(rootdir); |
| 160 } | 147 } |
| 161 } | 148 } |
| 162 return packageName; | 149 return packageName; |
| 163 } | 150 } |
| 164 | 151 |
| 165 String _packageIntro(packageDir) { | 152 String _packageIntro(packageDir) { |
| 166 var dir = new Directory(packageDir); | 153 var dir = new Directory(packageDir); |
| 167 var files = dir.listSync(); | 154 var files = dir.listSync(); |
| 168 var readmes = files.where((FileSystemEntity each) => (each is File && | 155 var readmes = files.where((FileSystemEntity each) => (each is File && |
| 169 each.path.substring(packageDir.length + 1, each.path.length) | 156 each.path.substring(packageDir.length + 1, each.path.length) |
| 170 .startsWith('README'))).toList(); | 157 .startsWith('README'))).toList(); |
| 171 if (readmes.isEmpty) return ''; | 158 if (readmes.isEmpty) return ''; |
| 172 // If there are multiples, pick the shortest name. | 159 // If there are multiples, pick the shortest name. |
| 173 readmes.sort((a, b) => a.length.compareTo(b.length)); | 160 readmes.sort((a, b) => a.length.compareTo(b.length)); |
| 174 var readme = readmes.first; | 161 var readme = readmes.first; |
| 162 var linkResolver = (name) => fixReference(name, null, null, null); | |
| 175 var contents = markdown.markdownToHtml(readme | 163 var contents = markdown.markdownToHtml(readme |
| 176 .readAsStringSync(), linkResolver: linkResolver, | 164 .readAsStringSync(), linkResolver: linkResolver, |
| 177 inlineSyntaxes: markdownSyntaxes); | 165 inlineSyntaxes: markdownSyntaxes); |
| 178 return contents; | 166 return contents; |
| 179 } | 167 } |
| 180 | 168 |
| 181 | |
| 182 List<String> _listLibraries(List<String> args) { | 169 List<String> _listLibraries(List<String> args) { |
| 183 var libraries = new List<String>(); | 170 var libraries = new List<String>(); |
| 184 for (var arg in args) { | 171 for (var arg in args) { |
| 185 var type = FileSystemEntity.typeSync(arg); | 172 var type = FileSystemEntity.typeSync(arg); |
| 186 | 173 |
| 187 if (type == FileSystemEntityType.FILE) { | 174 if (type == FileSystemEntityType.FILE) { |
| 188 if (arg.endsWith('.dart')) { | 175 if (arg.endsWith('.dart')) { |
| 189 libraries.add(path.absolute(arg)); | 176 libraries.add(path.absolute(arg)); |
| 190 logger.info('Added to libraries: ${libraries.last}'); | 177 logger.info('Added to libraries: ${libraries.last}'); |
| 191 } | 178 } |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 entityMap.values.where((e) => e is Class).forEach((c) => c.makeValid()); | 310 entityMap.values.where((e) => e is Class).forEach((c) => c.makeValid()); |
| 324 // Everything is a subclass of Object, therefore empty the list to avoid a | 311 // Everything is a subclass of Object, therefore empty the list to avoid a |
| 325 // giant list of subclasses to be printed out. | 312 // giant list of subclasses to be printed out. |
| 326 if (includeSdk) (entityMap['dart-core.Object'] as Class).subclasses.clear(); | 313 if (includeSdk) (entityMap['dart-core.Object'] as Class).subclasses.clear(); |
| 327 | 314 |
| 328 var filteredEntities = entityMap.values.where(_isVisible); | 315 var filteredEntities = entityMap.values.where(_isVisible); |
| 329 | 316 |
| 330 // Outputs a JSON file with all libraries and their preview comments. | 317 // Outputs a JSON file with all libraries and their preview comments. |
| 331 // This will help the viewer know what libraries are available to read in. | 318 // This will help the viewer know what libraries are available to read in. |
| 332 var libraryMap; | 319 var libraryMap; |
| 320 var linkResolver = (name) => fixReference(name, null, null, null); | |
| 333 if (append) { | 321 if (append) { |
| 334 var docsDir = listDir('docs'); | 322 var docsDir = listDir('docs'); |
| 335 if (!docsDir.contains('docs/library_list.json')) { | 323 if (!docsDir.contains('docs/library_list.json')) { |
| 336 throw new StateError('No library_list.json'); | 324 throw new StateError('No library_list.json'); |
| 337 } | 325 } |
| 338 libraryMap = | 326 libraryMap = |
| 339 JSON.decode(new File('docs/library_list.json').readAsStringSync()); | 327 JSON.decode(new File('docs/library_list.json').readAsStringSync()); |
| 340 libraryMap['libraries'].addAll(filteredEntities | 328 libraryMap['libraries'].addAll(filteredEntities |
| 341 .where((e) => e is Library) | 329 .where((e) => e is Library) |
| 342 .map((e) => e.previewMap)); | 330 .map((e) => e.previewMap)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 filteredEntities.map((e) => e.typeName)); | 365 filteredEntities.map((e) => e.typeName)); |
| 378 if (append) { | 366 if (append) { |
| 379 var previousIndex = | 367 var previousIndex = |
| 380 JSON.decode(new File('docs/index.json').readAsStringSync()); | 368 JSON.decode(new File('docs/index.json').readAsStringSync()); |
| 381 index.addAll(previousIndex); | 369 index.addAll(previousIndex); |
| 382 } | 370 } |
| 383 _writeToFile(JSON.encode(index), 'index.json'); | 371 _writeToFile(JSON.encode(index), 'index.json'); |
| 384 } | 372 } |
| 385 | 373 |
| 386 Library generateLibrary(dart2js.Dart2JsLibraryMirror library) { | 374 Library generateLibrary(dart2js.Dart2JsLibraryMirror library) { |
| 387 _currentLibrary = library; | 375 var result = new Library(docName(library), |
| 388 var result = new Library(docName(library), _commentToHtml(library), | 376 (actualLibrary) => _commentToHtml(library, actualLibrary), |
| 389 _classes(library.classes), | 377 _classes(library.classes), |
| 390 _methods(library.functions), | 378 _methods(library.functions), |
| 391 _variables(library.variables), | 379 _variables(library.variables), |
| 392 _isHidden(library)); | 380 _isHidden(library), library); |
| 393 _findPackage(library, result); | 381 _findPackage(library, result); |
| 394 logger.fine('Generated library for ${result.name}'); | 382 logger.fine('Generated library for ${result.name}'); |
| 395 return result; | 383 return result; |
| 396 } | 384 } |
| 397 | 385 |
| 398 void _writeIndexableToFile(Indexable result, bool outputToYaml) { | 386 void _writeIndexableToFile(Indexable result, bool outputToYaml) { |
| 399 var outputFile = result.fileName; | 387 var outputFile = result.fileName; |
| 400 var output; | 388 var output; |
| 401 if (outputToYaml) { | 389 if (outputToYaml) { |
| 402 output = getYamlString(result.toMap()); | 390 output = getYamlString(result.toMap()); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 453 .where((e) => e != null) | 441 .where((e) => e != null) |
| 454 .toList(); | 442 .toList(); |
| 455 if (!skippedAnnotations.contains(docName(annotation.type))) { | 443 if (!skippedAnnotations.contains(docName(annotation.type))) { |
| 456 annotations.add(new Annotation(docName(annotation.type), | 444 annotations.add(new Annotation(docName(annotation.type), |
| 457 parameterList)); | 445 parameterList)); |
| 458 } | 446 } |
| 459 }); | 447 }); |
| 460 return annotations; | 448 return annotations; |
| 461 } | 449 } |
| 462 | 450 |
| 463 /// Update the global pointers to the current mirror to the particular mirror | |
| 464 /// we're documenting. | |
| 465 void _updateCurrentMirror(DeclarationMirror mirror) { | |
| 466 if (mirror is LibraryMirror) { | |
| 467 _currentLibrary = mirror; | |
| 468 } else if (mirror is ClassMirror) { | |
| 469 _currentClass = mirror; | |
| 470 } else if (mirror is MethodMirror) { | |
| 471 _currentMember = mirror; | |
| 472 } | |
| 473 } | |
| 474 | |
| 475 /// Returns any documentation comments associated with a mirror with | 451 /// Returns any documentation comments associated with a mirror with |
| 476 /// simple markdown converted to html. | 452 /// simple markdown converted to html. |
| 477 String _commentToHtml(DeclarationMirror mirror) { | 453 /// |
| 454 /// It's possible to have a comment that comes from one mirror applied to | |
| 455 /// another, in the case of an inherited comment. | |
| 456 String _commentToHtml(DeclarationMirror mirror, [DeclarationMirror appliedTo]) { | |
| 457 if (appliedTo == null) appliedTo = mirror; | |
| 478 String commentText; | 458 String commentText; |
| 479 _updateCurrentMirror(mirror); | |
| 480 mirror.metadata.forEach((metadata) { | 459 mirror.metadata.forEach((metadata) { |
| 481 if (metadata is CommentInstanceMirror) { | 460 if (metadata is CommentInstanceMirror) { |
| 482 CommentInstanceMirror comment = metadata; | 461 CommentInstanceMirror comment = metadata; |
| 483 if (comment.isDocComment) { | 462 if (comment.isDocComment) { |
| 484 if (commentText == null) { | 463 if (commentText == null) { |
| 485 commentText = comment.trimmedText; | 464 commentText = comment.trimmedText; |
| 486 } else { | 465 } else { |
| 487 commentText = '$commentText\n${comment.trimmedText}'; | 466 commentText = '$commentText\n${comment.trimmedText}'; |
| 488 } | 467 } |
| 489 } | 468 } |
| 490 } | 469 } |
| 491 }); | 470 }); |
| 492 | 471 |
| 472 var linkResolver = (name) => fixReferenceWithScope(name, appliedTo); | |
| 493 commentText = commentText == null ? '' : | 473 commentText = commentText == null ? '' : |
| 494 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver, | 474 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver, |
| 495 inlineSyntaxes: markdownSyntaxes); | 475 inlineSyntaxes: markdownSyntaxes); |
| 496 return commentText; | 476 return commentText; |
| 497 } | 477 } |
| 498 | 478 |
| 499 /// Generates MDN comments from database.json. | 479 /// Generates MDN comments from database.json. |
| 500 void _mdnComment(Indexable item) { | 480 void _mdnComment(Indexable item) { |
| 501 //Check if MDN is loaded. | 481 //Check if MDN is loaded. |
| 502 if (_mdn == null) { | 482 if (_mdn == null) { |
| 503 // Reading in MDN related json file. | 483 // Reading in MDN related json file. |
| 504 var root = findRootDirectory(); | 484 var root = findRootDirectory(); |
| 505 var mdnPath = path.join(root, 'utils/apidoc/mdn/database.json'); | 485 var mdnPath = path.join(root, 'utils/apidoc/mdn/database.json'); |
| 506 _mdn = JSON.decode(new File(mdnPath).readAsStringSync()); | 486 _mdn = JSON.decode(new File(mdnPath).readAsStringSync()); |
| 507 } | 487 } |
| 508 if (item.comment.isNotEmpty) return; | 488 if (item is Library) return; |
| 509 var domAnnotation = item.annotations.firstWhere( | 489 var domAnnotation = item.annotations.firstWhere( |
| 510 (e) => e.qualifiedName == 'metadata.DomName', orElse: () => null); | 490 (e) => e.qualifiedName == 'metadata.DomName', orElse: () => null); |
| 511 if (domAnnotation == null) return; | 491 if (domAnnotation == null) return; |
| 512 var domName = domAnnotation.parameters.single; | 492 var domName = domAnnotation.parameters.single; |
| 513 var parts = domName.split('.'); | 493 var parts = domName.split('.'); |
| 514 if (parts.length == 2) item.comment = _mdnMemberComment(parts[0], parts[1]); | 494 if (parts.length == 2) item.comment = _mdnMemberComment(parts[0], parts[1]); |
| 515 if (parts.length == 1) item.comment = _mdnTypeComment(parts[0]); | 495 if (parts.length == 1) item.comment = _mdnTypeComment(parts[0]); |
| 516 } | 496 } |
| 517 | 497 |
| 518 /// Generates the MDN Comment for variables and method DOM elements. | 498 /// Generates the MDN Comment for variables and method DOM elements. |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 668 ClassMirror currentClass, MemberMirror currentMember) { | 648 ClassMirror currentClass, MemberMirror currentMember) { |
| 669 // Attempt the look up the whole name up in the scope. | 649 // Attempt the look up the whole name up in the scope. |
| 670 String elementName = | 650 String elementName = |
| 671 findElementInScope(name, currentLibrary, currentClass, currentMember); | 651 findElementInScope(name, currentLibrary, currentClass, currentMember); |
| 672 if (elementName != null) { | 652 if (elementName != null) { |
| 673 return new markdown.Element.text('a', elementName); | 653 return new markdown.Element.text('a', elementName); |
| 674 } | 654 } |
| 675 return _fixComplexReference(name, currentLibrary, currentClass, currentMember) ; | 655 return _fixComplexReference(name, currentLibrary, currentClass, currentMember) ; |
| 676 } | 656 } |
| 677 | 657 |
| 658 markdown.Node fixReferenceWithScope(String name, DeclarationMirror scope) { | |
| 659 if (scope is LibraryMirror) return fixReference(name, scope, null, null); | |
| 660 if (scope is ClassMirror) | |
| 661 return fixReference(name, scope.library, scope, null); | |
| 662 if (scope is MemberMirror) { | |
| 663 var owner = scope.owner; | |
| 664 if (owner is ClassMirror) { | |
| 665 return fixReference(name, owner.library, owner, scope); | |
| 666 } else { | |
| 667 return fixReference(name, owner, null, scope); | |
| 668 } | |
| 669 } | |
| 670 return null; | |
| 671 } | |
| 672 | |
| 678 /// Returns a map of [Variable] objects constructed from [mirrorMap]. | 673 /// Returns a map of [Variable] objects constructed from [mirrorMap]. |
| 679 Map<String, Variable> _variables(Map<String, VariableMirror> mirrorMap) { | 674 Map<String, Variable> _variables(Map<String, VariableMirror> mirrorMap) { |
| 680 var data = {}; | 675 var data = {}; |
| 681 // TODO(janicejl): When map to map feature is created, replace the below with | 676 // TODO(janicejl): When map to map feature is created, replace the below with |
| 682 // a filter. Issue(#9590). | 677 // a filter. Issue(#9590). |
| 683 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { | 678 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { |
| 684 _currentMember = mirror; | |
| 685 if (_includePrivate || !_isHidden(mirror)) { | 679 if (_includePrivate || !_isHidden(mirror)) { |
| 686 entityMap[docName(mirror)] = new Variable(mirrorName, mirror.isFinal, | 680 entityMap[docName(mirror)] = new Variable(mirrorName, mirror.isFinal, |
| 687 mirror.isStatic, mirror.isConst, _type(mirror.type), | 681 mirror.isStatic, mirror.isConst, _type(mirror.type), |
| 688 _commentToHtml(mirror), _annotations(mirror), docName(mirror), | 682 (actualVariable) => _commentToHtml(mirror, actualVariable), |
| 689 _isHidden(mirror), docName(mirror.owner)); | 683 _annotations(mirror), docName(mirror), |
| 684 _isHidden(mirror), docName(mirror.owner), mirror); | |
| 690 data[mirrorName] = entityMap[docName(mirror)]; | 685 data[mirrorName] = entityMap[docName(mirror)]; |
| 691 } | 686 } |
| 692 }); | 687 }); |
| 693 return data; | 688 return data; |
| 694 } | 689 } |
| 695 | 690 |
| 696 /// Returns a map of [Method] objects constructed from [mirrorMap]. | 691 /// Returns a map of [Method] objects constructed from [mirrorMap]. |
| 697 MethodGroup _methods(Map<String, MethodMirror> mirrorMap) { | 692 MethodGroup _methods(Map<String, MethodMirror> mirrorMap) { |
| 698 var group = new MethodGroup(); | 693 var group = new MethodGroup(); |
| 699 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { | 694 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { |
| 700 if (_includePrivate || !mirror.isPrivate) { | 695 if (_includePrivate || !mirror.isPrivate) { |
| 701 group.addMethod(mirror); | 696 group.addMethod(mirror); |
| 702 } | 697 } |
| 703 }); | 698 }); |
| 704 return group; | 699 return group; |
| 705 } | 700 } |
| 706 | 701 |
| 707 /// Returns the [Class] for the given [mirror] has already been created, and if | 702 /// Returns the [Class] for the given [mirror] has already been created, and if |
| 708 /// it does not exist, creates it. | 703 /// it does not exist, creates it. |
| 709 Class _class(ClassMirror mirror) { | 704 Class _class(ClassMirror mirror) { |
| 710 var clazz = entityMap[docName(mirror)]; | 705 var clazz = entityMap[docName(mirror)]; |
| 711 if (clazz == null) { | 706 if (clazz == null) { |
| 712 var superclass = mirror.superclass != null ? | 707 var superclass = mirror.superclass != null ? |
| 713 _class(mirror.superclass) : null; | 708 _class(mirror.superclass) : null; |
| 714 var interfaces = | 709 var interfaces = |
| 715 mirror.superinterfaces.map((interface) => _class(interface)); | 710 mirror.superinterfaces.map((interface) => _class(interface)); |
| 716 clazz = new Class(mirror.simpleName, superclass, _commentToHtml(mirror), | 711 clazz = new Class(mirror.simpleName, superclass, |
| 712 (actualClass) => _commentToHtml(mirror, actualClass), | |
| 717 interfaces.toList(), _variables(mirror.variables), | 713 interfaces.toList(), _variables(mirror.variables), |
| 718 _methods(mirror.methods), _annotations(mirror), _generics(mirror), | 714 _methods(mirror.methods), _annotations(mirror), _generics(mirror), |
| 719 docName(mirror), _isHidden(mirror), docName(mirror.owner), | 715 docName(mirror), _isHidden(mirror), docName(mirror.owner), |
| 720 mirror.isAbstract); | 716 mirror.isAbstract, mirror); |
| 721 if (superclass != null) clazz.addInherited(superclass); | 717 if (superclass != null) clazz.addInherited(superclass); |
| 722 interfaces.forEach((interface) => clazz.addInherited(interface)); | 718 interfaces.forEach((interface) => clazz.addInherited(interface)); |
| 723 entityMap[docName(mirror)] = clazz; | 719 entityMap[docName(mirror)] = clazz; |
| 724 } | 720 } |
| 725 return clazz; | 721 return clazz; |
| 726 } | 722 } |
| 727 | 723 |
| 728 /// Returns a map of [Class] objects constructed from [mirrorMap]. | 724 /// Returns a map of [Class] objects constructed from [mirrorMap]. |
| 729 ClassGroup _classes(Map<String, ClassMirror> mirrorMap) { | 725 ClassGroup _classes(Map<String, ClassMirror> mirrorMap) { |
| 730 var group = new ClassGroup(); | 726 var group = new ClassGroup(); |
| 731 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { | 727 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { |
| 732 group.addClass(mirror); | 728 group.addClass(mirror); |
| 733 }); | 729 }); |
| 734 return group; | 730 return group; |
| 735 } | 731 } |
| 736 | 732 |
| 737 /// Returns a map of [Parameter] objects constructed from [mirrorList]. | 733 /// Returns a map of [Parameter] objects constructed from [mirrorList]. |
| 738 Map<String, Parameter> _parameters(List<ParameterMirror> mirrorList) { | 734 Map<String, Parameter> _parameters(List<ParameterMirror> mirrorList) { |
| 739 var data = {}; | 735 var data = {}; |
| 740 mirrorList.forEach((ParameterMirror mirror) { | 736 mirrorList.forEach((ParameterMirror mirror) { |
| 741 _currentMember = mirror; | |
| 742 data[mirror.simpleName] = new Parameter(mirror.simpleName, | 737 data[mirror.simpleName] = new Parameter(mirror.simpleName, |
| 743 mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, | 738 mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, |
| 744 _type(mirror.type), mirror.defaultValue, | 739 _type(mirror.type), mirror.defaultValue, |
| 745 _annotations(mirror)); | 740 _annotations(mirror)); |
| 746 }); | 741 }); |
| 747 return data; | 742 return data; |
| 748 } | 743 } |
| 749 | 744 |
| 750 /// Returns a map of [Generic] objects constructed from the class mirror. | 745 /// Returns a map of [Generic] objects constructed from the class mirror. |
| 751 Map<String, Generic> _generics(ClassMirror mirror) { | 746 Map<String, Generic> _generics(ClassMirror mirror) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 799 inputMap.forEach((key, value) { | 794 inputMap.forEach((key, value) { |
| 800 if (value is Map) { | 795 if (value is Map) { |
| 801 outputMap[key] = recurseMap(value); | 796 outputMap[key] = recurseMap(value); |
| 802 } else { | 797 } else { |
| 803 outputMap[key] = value.toMap(); | 798 outputMap[key] = value.toMap(); |
| 804 } | 799 } |
| 805 }); | 800 }); |
| 806 return outputMap; | 801 return outputMap; |
| 807 } | 802 } |
| 808 | 803 |
| 804 /// A type for the function that generates a comment from a mirror. | |
| 805 typedef String CommentGenerator(Mirror m); | |
| 806 | |
| 809 /// A class representing all programming constructs, like library or class. | 807 /// A class representing all programming constructs, like library or class. |
| 810 class Indexable { | 808 class Indexable { |
| 811 String name; | 809 String name; |
| 812 String get qualifiedName => fileName; | 810 String get qualifiedName => fileName; |
| 813 bool isPrivate; | 811 bool isPrivate; |
| 812 Mirror mirror; | |
| 814 | 813 |
| 815 // The qualified name (for URL purposes) and the file name are the same, | 814 // The qualified name (for URL purposes) and the file name are the same, |
| 816 // of the form packageName/ClassName or packageName/ClassName.methodName. | 815 // of the form packageName/ClassName or packageName/ClassName.methodName. |
| 817 // This defines both the URL and the directory structure. | 816 // This defines both the URL and the directory structure. |
| 818 String get fileName => packagePrefix + ownerPrefix + name; | 817 String get fileName => packagePrefix + ownerPrefix + name; |
| 819 | 818 |
| 820 Indexable get owningEntity { | 819 Indexable get owningEntity => entityMap[owner]; |
| 821 var result = entityMap[owner]; | 820 |
| 822 return result; | |
| 823 } | |
| 824 String get ownerPrefix => owningEntity == null | 821 String get ownerPrefix => owningEntity == null |
| 825 ? (owner == null || owner.isEmpty ? '' : owner + '.') | 822 ? (owner == null || owner.isEmpty ? '' : owner + '.') |
| 826 : owningEntity.qualifiedName + '.'; | 823 : owningEntity.qualifiedName + '.'; |
| 827 | 824 |
| 828 String get packagePrefix => ''; | 825 String get packagePrefix => ''; |
| 826 | |
| 829 /// Documentation comment with converted markdown. | 827 /// Documentation comment with converted markdown. |
| 830 String comment; | 828 String _comment; |
| 829 | |
| 830 String get comment { | |
| 831 if (_comment != null) return _comment; | |
| 832 _comment = _commentFunction(mirror); | |
| 833 if (_comment.isEmpty) { | |
| 834 _mdnComment(this); | |
| 835 } | |
| 836 return _comment; | |
| 837 } | |
| 838 | |
| 839 set comment(x) => _comment = x; | |
| 840 | |
| 841 /// We defer evaluating the comment until we have all the context available | |
| 842 CommentGenerator _commentFunction; | |
| 831 | 843 |
| 832 /// Qualified Name of the owner of this Indexable Item. | 844 /// Qualified Name of the owner of this Indexable Item. |
| 833 /// For Library, owner will be ""; | 845 /// For Library, owner will be ""; |
| 834 String owner; | 846 String owner; |
| 835 | 847 |
| 836 Indexable(this.name, this.comment, this.isPrivate, this.owner); | 848 Indexable(this.name, this._commentFunction, this.isPrivate, this.owner, |
| 849 this.mirror); | |
| 837 | 850 |
| 838 /// The type of this member to be used in index.txt. | 851 /// The type of this member to be used in index.txt. |
| 839 String get typeName => ''; | 852 String get typeName => ''; |
| 840 | 853 |
| 841 /// Creates a [Map] with this [Indexable]'s name and a preview comment. | 854 /// Creates a [Map] with this [Indexable]'s name and a preview comment. |
| 842 Map get previewMap { | 855 Map get previewMap { |
| 843 var finalMap = { 'name' : name, 'qualifiedName' : qualifiedName }; | 856 var finalMap = { 'name' : name, 'qualifiedName' : qualifiedName }; |
| 844 if (comment != '') { | 857 if (comment != '') { |
| 845 var index = comment.indexOf('</p>'); | 858 var index = comment.indexOf('</p>'); |
| 846 finalMap['preview'] = '${comment.substring(0, index)}</p>'; | 859 finalMap['preview'] = '${comment.substring(0, index)}</p>'; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 877 | 890 |
| 878 Map get previewMap { | 891 Map get previewMap { |
| 879 var basic = super.previewMap; | 892 var basic = super.previewMap; |
| 880 basic['packageName'] = packageName; | 893 basic['packageName'] = packageName; |
| 881 if (packageIntro != null) { | 894 if (packageIntro != null) { |
| 882 basic['packageIntro'] = packageIntro; | 895 basic['packageIntro'] = packageIntro; |
| 883 } | 896 } |
| 884 return basic; | 897 return basic; |
| 885 } | 898 } |
| 886 | 899 |
| 887 Library(String name, String comment, this.classes, this.functions, | 900 Library(String name, Function commentFunction, this.classes, this.functions, |
| 888 this.variables, bool isPrivate) : super(name, comment, | 901 this.variables, bool isPrivate, Mirror mirror) |
| 889 isPrivate, ""); | 902 : super(name, commentFunction, isPrivate, "", mirror); |
| 890 | 903 |
| 891 /// Generates a map describing the [Library] object. | 904 /// Generates a map describing the [Library] object. |
| 892 Map toMap() => { | 905 Map toMap() => { |
| 893 'name': name, | 906 'name': name, |
| 894 'qualifiedName': qualifiedName, | 907 'qualifiedName': qualifiedName, |
| 895 'comment': comment, | 908 'comment': comment, |
| 896 'variables': recurseMap(variables), | 909 'variables': recurseMap(variables), |
| 897 'functions': functions.toMap(), | 910 'functions': functions.toMap(), |
| 898 'classes': classes.toMap(), | 911 'classes': classes.toMap(), |
| 899 'packageName': packageName, | 912 'packageName': packageName, |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 926 | 939 |
| 927 /// Generic infomation about the class. | 940 /// Generic infomation about the class. |
| 928 Map<String, Generic> generics; | 941 Map<String, Generic> generics; |
| 929 | 942 |
| 930 Class superclass; | 943 Class superclass; |
| 931 bool isAbstract; | 944 bool isAbstract; |
| 932 | 945 |
| 933 /// List of the meta annotations on the class. | 946 /// List of the meta annotations on the class. |
| 934 List<Annotation> annotations; | 947 List<Annotation> annotations; |
| 935 | 948 |
| 936 Class(String name, this.superclass, String comment, this.interfaces, | 949 bool _commentsEnsured = false; |
|
Emily Fortuna
2013/11/18 21:00:41
comment explaining this variable?
Alan Knight
2013/11/18 22:04:46
Done.
| |
| 950 | |
| 951 Class(String name, this.superclass, Function commentFunction, this.interfaces, | |
| 937 this.variables, this.methods, this.annotations, this.generics, | 952 this.variables, this.methods, this.annotations, this.generics, |
| 938 String qualifiedName, bool isPrivate, String owner, this.isAbstract) | 953 String qualifiedName, bool isPrivate, String owner, this.isAbstract, |
| 939 : super(name, comment, isPrivate, owner) { | 954 Mirror mirror) |
| 940 _mdnComment(this); | 955 : super(name, commentFunction, isPrivate, owner, mirror) { |
|
Emily Fortuna
2013/11/18 21:00:41
you can take out the { } and just have a semicolon
Alan Knight
2013/11/18 22:04:46
Done.
| |
| 941 } | 956 } |
| 942 | 957 |
| 943 String get typeName => 'class'; | 958 String get typeName => 'class'; |
| 944 | 959 |
| 945 /// Returns a list of all the parent classes. | 960 /// Returns a list of all the parent classes. |
| 946 List<Class> parent() { | 961 List<Class> parent() { |
| 947 var parent = superclass == null ? [] : [superclass]; | 962 var parent = superclass == null ? [] : [superclass]; |
| 948 parent.addAll(interfaces); | 963 parent.addAll(interfaces); |
| 949 return parent; | 964 return parent; |
| 950 } | 965 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 997 // with the mixin as an owner private too. | 1012 // with the mixin as an owner private too. |
| 998 entityMap.values.where((e) => e.owner == qualifiedName) | 1013 entityMap.values.where((e) => e.owner == qualifiedName) |
| 999 .forEach((element) => element.isPrivate = true); | 1014 .forEach((element) => element.isPrivate = true); |
| 1000 // Move the subclass up to the next public superclass | 1015 // Move the subclass up to the next public superclass |
| 1001 subclasses.forEach((subclass) => addSubclass(subclass)); | 1016 subclasses.forEach((subclass) => addSubclass(subclass)); |
| 1002 } | 1017 } |
| 1003 } | 1018 } |
| 1004 | 1019 |
| 1005 /// Makes sure that all methods with inherited equivalents have comments. | 1020 /// Makes sure that all methods with inherited equivalents have comments. |
| 1006 void ensureComments() { | 1021 void ensureComments() { |
| 1022 if (_commentsEnsured) return; | |
| 1023 _commentsEnsured = true; | |
| 1007 inheritedMethods.forEach((qualifiedName, inheritedMethod) { | 1024 inheritedMethods.forEach((qualifiedName, inheritedMethod) { |
| 1008 var method = methods[qualifiedName]; | 1025 var method = methods[qualifiedName]; |
| 1009 if (method != null) method.ensureCommentFor(inheritedMethod); | 1026 if (method != null) method.ensureCommentFor(inheritedMethod); |
| 1010 }); | 1027 }); |
| 1011 } | 1028 } |
| 1012 | 1029 |
| 1013 /// If a class extends a private superclass, find the closest public superclas s | 1030 /// If a class extends a private superclass, find the closest public superclas s |
| 1014 /// of the private superclass. | 1031 /// of the private superclass. |
| 1015 String validSuperclass() { | 1032 String validSuperclass() { |
| 1016 if (superclass == null) return 'dart.core.Object'; | 1033 if (superclass == null) return 'dart.core.Object'; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1040 int compareTo(aClass) => name.compareTo(aClass.name); | 1057 int compareTo(aClass) => name.compareTo(aClass.name); |
| 1041 } | 1058 } |
| 1042 | 1059 |
| 1043 /// A container to categorize classes into the following groups: abstract | 1060 /// A container to categorize classes into the following groups: abstract |
| 1044 /// classes, regular classes, typedefs, and errors. | 1061 /// classes, regular classes, typedefs, and errors. |
| 1045 class ClassGroup { | 1062 class ClassGroup { |
| 1046 Map<String, Class> classes = {}; | 1063 Map<String, Class> classes = {}; |
| 1047 Map<String, Typedef> typedefs = {}; | 1064 Map<String, Typedef> typedefs = {}; |
| 1048 Map<String, Class> errors = {}; | 1065 Map<String, Class> errors = {}; |
| 1049 | 1066 |
| 1050 void addClass(ClassMirror mirror) { | 1067 void addClass(ClassMirror classMirror) { |
| 1051 _currentClass = mirror; | 1068 if (classMirror.isTypedef) { |
| 1052 if (mirror.isTypedef) { | |
| 1053 // This is actually a Dart2jsTypedefMirror, and it does define value, | 1069 // This is actually a Dart2jsTypedefMirror, and it does define value, |
| 1054 // but we don't have visibility to that type. | 1070 // but we don't have visibility to that type. |
| 1055 var mirror = _currentClass; | 1071 var mirror = classMirror; |
| 1056 if (_includePrivate || !mirror.isPrivate) { | 1072 if (_includePrivate || !mirror.isPrivate) { |
| 1057 entityMap[docName(mirror)] = new Typedef(mirror.simpleName, | 1073 entityMap[docName(mirror)] = new Typedef(mirror.simpleName, |
| 1058 docName(mirror.value.returnType), _commentToHtml(mirror), | 1074 docName(mirror.value.returnType), |
| 1075 (actualTypedef) => _commentToHtml(mirror, actualTypedef), | |
| 1059 _generics(mirror), _parameters(mirror.value.parameters), | 1076 _generics(mirror), _parameters(mirror.value.parameters), |
| 1060 _annotations(mirror), docName(mirror), _isHidden(mirror), | 1077 _annotations(mirror), docName(mirror), _isHidden(mirror), |
| 1061 docName(mirror.owner)); | 1078 docName(mirror.owner), mirror); |
| 1062 typedefs[mirror.simpleName] = entityMap[docName(mirror)]; | 1079 typedefs[mirror.simpleName] = entityMap[docName(mirror)]; |
| 1063 } | 1080 } |
| 1064 } else { | 1081 } else { |
| 1065 var clazz = _class(mirror); | 1082 var clazz = _class(classMirror); |
| 1066 | 1083 |
| 1067 // Adding inherited parent variables and methods. | 1084 // Adding inherited parent variables and methods. |
| 1068 clazz.parent().forEach((parent) { | 1085 clazz.parent().forEach((parent) { |
| 1069 if (_isVisible(clazz)) { | 1086 if (_isVisible(clazz)) { |
| 1070 parent.addSubclass(clazz); | 1087 parent.addSubclass(clazz); |
| 1071 } | 1088 } |
| 1072 }); | 1089 }); |
| 1073 | 1090 |
| 1074 clazz.ensureComments(); | |
| 1075 | |
| 1076 if (clazz.isError()) { | 1091 if (clazz.isError()) { |
| 1077 errors[mirror.simpleName] = clazz; | 1092 errors[classMirror.simpleName] = clazz; |
| 1078 } else if (mirror.isClass) { | 1093 } else if (classMirror.isClass) { |
| 1079 classes[mirror.simpleName] = clazz; | 1094 classes[classMirror.simpleName] = clazz; |
| 1080 } else { | 1095 } else { |
| 1081 throw new ArgumentError('${mirror.simpleName} - no class type match. '); | 1096 throw new ArgumentError( |
| 1097 '${classMirror.simpleName} - no class type match. '); | |
| 1082 } | 1098 } |
| 1083 } | 1099 } |
| 1084 } | 1100 } |
| 1085 | 1101 |
| 1086 /// Checks if the given name is a key for any of the Class Maps. | 1102 /// Checks if the given name is a key for any of the Class Maps. |
| 1087 bool containsKey(String name) { | 1103 bool containsKey(String name) { |
| 1088 return classes.containsKey(name) || errors.containsKey(name); | 1104 return classes.containsKey(name) || errors.containsKey(name); |
| 1089 } | 1105 } |
| 1090 | 1106 |
| 1091 Map toMap() => { | 1107 Map toMap() => { |
| 1092 'class': classes.values.where(_isVisible) | 1108 'class': classes.values.where(_isVisible) |
| 1093 .map((e) => e.previewMap).toList(), | 1109 .map((e) => e.previewMap).toList(), |
| 1094 'typedef': recurseMap(typedefs), | 1110 'typedef': recurseMap(typedefs), |
| 1095 'error': errors.values.where(_isVisible) | 1111 'error': errors.values.where(_isVisible) |
| 1096 .map((e) => e.previewMap).toList() | 1112 .map((e) => e.previewMap).toList() |
| 1097 }; | 1113 }; |
| 1098 } | 1114 } |
| 1099 | 1115 |
| 1100 class Typedef extends Indexable { | 1116 class Typedef extends Indexable { |
| 1101 String returnType; | 1117 String returnType; |
| 1102 | 1118 |
| 1103 Map<String, Parameter> parameters; | 1119 Map<String, Parameter> parameters; |
| 1104 | 1120 |
| 1105 /// Generic information about the typedef. | 1121 /// Generic information about the typedef. |
| 1106 Map<String, Generic> generics; | 1122 Map<String, Generic> generics; |
| 1107 | 1123 |
| 1108 /// List of the meta annotations on the typedef. | 1124 /// List of the meta annotations on the typedef. |
| 1109 List<Annotation> annotations; | 1125 List<Annotation> annotations; |
| 1110 | 1126 |
| 1111 Typedef(String name, this.returnType, String comment, this.generics, | 1127 Typedef(String name, this.returnType, Function commentFunction, this.generics, |
| 1112 this.parameters, this.annotations, | 1128 this.parameters, this.annotations, |
| 1113 String qualifiedName, bool isPrivate, String owner) | 1129 String qualifiedName, bool isPrivate, String owner, Mirror mirror) |
| 1114 : super(name, comment, isPrivate, owner); | 1130 : super(name, commentFunction, isPrivate, owner, mirror); |
| 1115 | 1131 |
| 1116 Map toMap() => { | 1132 Map toMap() => { |
| 1117 'name': name, | 1133 'name': name, |
| 1118 'qualifiedName': qualifiedName, | 1134 'qualifiedName': qualifiedName, |
| 1119 'comment': comment, | 1135 'comment': comment, |
| 1120 'return': returnType, | 1136 'return': returnType, |
| 1121 'parameters': recurseMap(parameters), | 1137 'parameters': recurseMap(parameters), |
| 1122 'annotations': annotations.map((a) => a.toMap()).toList(), | 1138 'annotations': annotations.map((a) => a.toMap()).toList(), |
| 1123 'generics': recurseMap(generics) | 1139 'generics': recurseMap(generics) |
| 1124 }; | 1140 }; |
| 1125 | 1141 |
| 1126 String get typeName => 'typedef'; | 1142 String get typeName => 'typedef'; |
| 1127 } | 1143 } |
| 1128 | 1144 |
| 1129 /// A class containing properties of a Dart variable. | 1145 /// A class containing properties of a Dart variable. |
| 1130 class Variable extends Indexable { | 1146 class Variable extends Indexable { |
| 1131 | 1147 |
| 1132 bool isFinal; | 1148 bool isFinal; |
| 1133 bool isStatic; | 1149 bool isStatic; |
| 1134 bool isConst; | 1150 bool isConst; |
| 1135 Type type; | 1151 Type type; |
| 1136 | 1152 |
| 1137 /// List of the meta annotations on the variable. | 1153 /// List of the meta annotations on the variable. |
| 1138 List<Annotation> annotations; | 1154 List<Annotation> annotations; |
| 1139 | 1155 |
| 1140 Variable(String name, this.isFinal, this.isStatic, this.isConst, this.type, | 1156 Variable(String name, this.isFinal, this.isStatic, this.isConst, this.type, |
| 1141 String comment, this.annotations, String qualifiedName, bool isPrivate, | 1157 Function commentFunction, this.annotations, String qualifiedName, |
| 1142 String owner) : super(name, comment, isPrivate, owner) { | 1158 bool isPrivate, String owner, Mirror mirror) |
| 1143 _mdnComment(this); | 1159 : super(name, commentFunction, isPrivate, owner, mirror) { |
| 1144 } | 1160 } |
| 1145 | 1161 |
| 1146 /// Generates a map describing the [Variable] object. | 1162 /// Generates a map describing the [Variable] object. |
| 1147 Map toMap() => { | 1163 Map toMap() => { |
| 1148 'name': name, | 1164 'name': name, |
| 1149 'qualifiedName': qualifiedName, | 1165 'qualifiedName': qualifiedName, |
| 1150 'comment': comment, | 1166 'comment': comment, |
| 1151 'final': isFinal.toString(), | 1167 'final': isFinal.toString(), |
| 1152 'static': isStatic.toString(), | 1168 'static': isStatic.toString(), |
| 1153 'constant': isConst.toString(), | 1169 'constant': isConst.toString(), |
| 1154 'type': new List.filled(1, type.toMap()), | 1170 'type': new List.filled(1, type.toMap()), |
| 1155 'annotations': annotations.map((a) => a.toMap()).toList() | 1171 'annotations': annotations.map((a) => a.toMap()).toList() |
| 1156 }; | 1172 }; |
| 1157 | 1173 |
| 1158 String get typeName => 'property'; | 1174 String get typeName => 'property'; |
| 1175 | |
| 1176 get comment { | |
| 1177 if (_comment != null) return _comment; | |
| 1178 var owningClass = owningEntity; | |
| 1179 if (owningClass is Class) { | |
| 1180 owningClass.ensureComments(); | |
| 1181 } | |
| 1182 return super.comment; | |
| 1183 } | |
| 1159 } | 1184 } |
| 1160 | 1185 |
| 1161 /// A class containing properties of a Dart method. | 1186 /// A class containing properties of a Dart method. |
| 1162 class Method extends Indexable { | 1187 class Method extends Indexable { |
| 1163 | 1188 |
| 1164 /// Parameters for this method. | 1189 /// Parameters for this method. |
| 1165 Map<String, Parameter> parameters; | 1190 Map<String, Parameter> parameters; |
| 1166 | 1191 |
| 1167 bool isStatic; | 1192 bool isStatic; |
| 1168 bool isAbstract; | 1193 bool isAbstract; |
| 1169 bool isConst; | 1194 bool isConst; |
| 1170 bool isConstructor; | 1195 bool isConstructor; |
| 1171 bool isGetter; | 1196 bool isGetter; |
| 1172 bool isSetter; | 1197 bool isSetter; |
| 1173 bool isOperator; | 1198 bool isOperator; |
| 1174 Type returnType; | 1199 Type returnType; |
| 1175 | 1200 |
| 1176 /// Qualified name to state where the comment is inherited from. | 1201 /// Qualified name to state where the comment is inherited from. |
| 1177 String commentInheritedFrom = ""; | 1202 String commentInheritedFrom = ""; |
| 1178 | 1203 |
| 1179 /// List of the meta annotations on the method. | 1204 /// List of the meta annotations on the method. |
| 1180 List<Annotation> annotations; | 1205 List<Annotation> annotations; |
| 1181 | 1206 |
| 1182 Method(String name, this.isStatic, this.isAbstract, this.isConst, | 1207 Method(String name, this.isStatic, this.isAbstract, this.isConst, |
| 1183 this.returnType, String comment, this.parameters, this.annotations, | 1208 this.returnType, Function commentFunction, this.parameters, |
| 1209 this.annotations, | |
| 1184 String qualifiedName, bool isPrivate, String owner, this.isConstructor, | 1210 String qualifiedName, bool isPrivate, String owner, this.isConstructor, |
| 1185 this.isGetter, this.isSetter, this.isOperator) | 1211 this.isGetter, this.isSetter, this.isOperator, Mirror mirror) |
| 1186 : super(name, comment, isPrivate, owner) { | 1212 : super(name, commentFunction, isPrivate, owner, mirror) { |
| 1187 _mdnComment(this); | |
| 1188 } | 1213 } |
| 1189 | 1214 |
| 1190 /// Makes sure that the method with an inherited equivalent have comments. | 1215 /// Makes sure that the method with an inherited equivalent have comments. |
| 1191 void ensureCommentFor(Method inheritedMethod) { | 1216 void ensureCommentFor(Method inheritedMethod) { |
| 1192 if (comment.isNotEmpty) return; | 1217 if (comment.isNotEmpty) return; |
| 1193 (entityMap[inheritedMethod.owner] as Class).ensureComments(); | 1218 comment = inheritedMethod._commentFunction(mirror); |
| 1194 comment = inheritedMethod.comment; | |
| 1195 commentInheritedFrom = inheritedMethod.commentInheritedFrom == '' ? | 1219 commentInheritedFrom = inheritedMethod.commentInheritedFrom == '' ? |
| 1196 inheritedMethod.qualifiedName : inheritedMethod.commentInheritedFrom; | 1220 inheritedMethod.qualifiedName : inheritedMethod.commentInheritedFrom; |
| 1197 } | 1221 } |
| 1198 | 1222 |
| 1199 /// Generates a map describing the [Method] object. | 1223 /// Generates a map describing the [Method] object. |
| 1200 Map toMap() => { | 1224 Map toMap() => { |
| 1201 'name': name, | 1225 'name': name, |
| 1202 'qualifiedName': qualifiedName, | 1226 'qualifiedName': qualifiedName, |
| 1203 'comment': comment, | 1227 'comment': comment, |
| 1204 'commentFrom': commentInheritedFrom, | 1228 'commentFrom': commentInheritedFrom, |
| 1205 'static': isStatic.toString(), | 1229 'static': isStatic.toString(), |
| 1206 'abstract': isAbstract.toString(), | 1230 'abstract': isAbstract.toString(), |
| 1207 'constant': isConst.toString(), | 1231 'constant': isConst.toString(), |
| 1208 'return': new List.filled(1, returnType.toMap()), | 1232 'return': new List.filled(1, returnType.toMap()), |
| 1209 'parameters': recurseMap(parameters), | 1233 'parameters': recurseMap(parameters), |
| 1210 'annotations': annotations.map((a) => a.toMap()).toList() | 1234 'annotations': annotations.map((a) => a.toMap()).toList() |
| 1211 }; | 1235 }; |
| 1212 | 1236 |
| 1213 String get typeName => isConstructor ? 'constructor' : | 1237 String get typeName => isConstructor ? 'constructor' : |
| 1214 isGetter ? 'getter' : isSetter ? 'setter' : | 1238 isGetter ? 'getter' : isSetter ? 'setter' : |
| 1215 isOperator ? 'operator' : 'method'; | 1239 isOperator ? 'operator' : 'method'; |
| 1240 | |
| 1241 get comment { | |
| 1242 if (_comment != null) return _comment; | |
| 1243 var owningClass = owningEntity; | |
| 1244 if (owningClass is Class) { | |
| 1245 owningClass.ensureComments(); | |
| 1246 } | |
| 1247 return super.comment; | |
| 1248 } | |
| 1216 } | 1249 } |
| 1217 | 1250 |
| 1218 /// A container to categorize methods into the following groups: setters, | 1251 /// A container to categorize methods into the following groups: setters, |
| 1219 /// getters, constructors, operators, regular methods. | 1252 /// getters, constructors, operators, regular methods. |
| 1220 class MethodGroup { | 1253 class MethodGroup { |
| 1221 Map<String, Method> setters = {}; | 1254 Map<String, Method> setters = {}; |
| 1222 Map<String, Method> getters = {}; | 1255 Map<String, Method> getters = {}; |
| 1223 Map<String, Method> constructors = {}; | 1256 Map<String, Method> constructors = {}; |
| 1224 Map<String, Method> operators = {}; | 1257 Map<String, Method> operators = {}; |
| 1225 Map<String, Method> regularMethods = {}; | 1258 Map<String, Method> regularMethods = {}; |
| 1226 | 1259 |
| 1227 void addMethod(MethodMirror mirror) { | 1260 void addMethod(MethodMirror mirror) { |
| 1228 var method = new Method(mirror.simpleName, mirror.isStatic, | 1261 var method = new Method(mirror.simpleName, mirror.isStatic, |
| 1229 mirror.isAbstract, mirror.isConstConstructor, _type(mirror.returnType), | 1262 mirror.isAbstract, mirror.isConstConstructor, _type(mirror.returnType), |
| 1230 _commentToHtml(mirror), _parameters(mirror.parameters), | 1263 (actualMethod) => _commentToHtml(mirror, actualMethod), |
| 1264 _parameters(mirror.parameters), | |
| 1231 _annotations(mirror), docName(mirror), _isHidden(mirror), | 1265 _annotations(mirror), docName(mirror), _isHidden(mirror), |
| 1232 docName(mirror.owner), mirror.isConstructor, mirror.isGetter, | 1266 docName(mirror.owner), mirror.isConstructor, mirror.isGetter, |
| 1233 mirror.isSetter, mirror.isOperator); | 1267 mirror.isSetter, mirror.isOperator, mirror); |
| 1234 entityMap[docName(mirror)] = method; | 1268 entityMap[docName(mirror)] = method; |
| 1235 _currentMember = mirror; | |
| 1236 if (mirror.isSetter) { | 1269 if (mirror.isSetter) { |
| 1237 setters[mirror.simpleName] = method; | 1270 setters[mirror.simpleName] = method; |
| 1238 } else if (mirror.isGetter) { | 1271 } else if (mirror.isGetter) { |
| 1239 getters[mirror.simpleName] = method; | 1272 getters[mirror.simpleName] = method; |
| 1240 } else if (mirror.isConstructor) { | 1273 } else if (mirror.isConstructor) { |
| 1241 constructors[mirror.simpleName] = method; | 1274 constructors[mirror.simpleName] = method; |
| 1242 } else if (mirror.isOperator) { | 1275 } else if (mirror.isOperator) { |
| 1243 operators[mirror.simpleName] = method; | 1276 operators[mirror.simpleName] = method; |
| 1244 } else if (mirror.isRegularMethod) { | 1277 } else if (mirror.isRegularMethod) { |
| 1245 regularMethods[mirror.simpleName] = method; | 1278 regularMethods[mirror.simpleName] = method; |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1396 /// Remove statics from the map of inherited items before adding them. | 1429 /// Remove statics from the map of inherited items before adding them. |
| 1397 Map _filterStatics(Map items) { | 1430 Map _filterStatics(Map items) { |
| 1398 var result = {}; | 1431 var result = {}; |
| 1399 items.forEach((name, item) { | 1432 items.forEach((name, item) { |
| 1400 if (!item.isStatic) { | 1433 if (!item.isStatic) { |
| 1401 result[name] = item; | 1434 result[name] = item; |
| 1402 } | 1435 } |
| 1403 }); | 1436 }); |
| 1404 return result; | 1437 return result; |
| 1405 } | 1438 } |
| OLD | NEW |