| 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; | |
| 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 (library == null) { | 133 if (library == null) { |
| 147 library = entityMap[mirror.simpleName]; | 134 library = entityMap[mirror.simpleName]; |
| 148 } | 135 } |
| 149 if (library != null) { | 136 if (library != null) { |
| 150 if (library.hasBeenCheckedForPackage) return library.packageName; | 137 if (library.hasBeenCheckedForPackage) return library.packageName; |
| 151 library.hasBeenCheckedForPackage = true; | 138 library.hasBeenCheckedForPackage = true; |
| 152 } | 139 } |
| 153 if (mirror.uri.scheme != 'file') return ''; | 140 if (mirror.uri.scheme != 'file') return ''; |
| 154 var filePath = mirror.uri.toFilePath(); | 141 var filePath = mirror.uri.toFilePath(); |
| 155 // We assume that we are documenting only libraries under package/lib | 142 // We assume that we are documenting only libraries under package/lib |
| (...skipping 13 matching lines...) Expand all Loading... |
| 169 String _packageIntro(packageDir) { | 156 String _packageIntro(packageDir) { |
| 170 var dir = new Directory(packageDir); | 157 var dir = new Directory(packageDir); |
| 171 var files = dir.listSync(); | 158 var files = dir.listSync(); |
| 172 var readmes = files.where((FileSystemEntity each) => (each is File && | 159 var readmes = files.where((FileSystemEntity each) => (each is File && |
| 173 each.path.substring(packageDir.length + 1, each.path.length) | 160 each.path.substring(packageDir.length + 1, each.path.length) |
| 174 .startsWith('README'))).toList(); | 161 .startsWith('README'))).toList(); |
| 175 if (readmes.isEmpty) return ''; | 162 if (readmes.isEmpty) return ''; |
| 176 // If there are multiples, pick the shortest name. | 163 // If there are multiples, pick the shortest name. |
| 177 readmes.sort((a, b) => a.length.compareTo(b.length)); | 164 readmes.sort((a, b) => a.length.compareTo(b.length)); |
| 178 var readme = readmes.first; | 165 var readme = readmes.first; |
| 166 var linkResolver = (name) => fixReference(name, null, null, null); |
| 179 var contents = markdown.markdownToHtml(readme | 167 var contents = markdown.markdownToHtml(readme |
| 180 .readAsStringSync(), linkResolver: linkResolver, | 168 .readAsStringSync(), linkResolver: linkResolver, |
| 181 inlineSyntaxes: markdownSyntaxes); | 169 inlineSyntaxes: markdownSyntaxes); |
| 182 return contents; | 170 return contents; |
| 183 } | 171 } |
| 184 | 172 |
| 185 List<String> _listLibraries(List<String> args) { | 173 List<String> _listLibraries(List<String> args) { |
| 186 var libraries = new List<String>(); | 174 var libraries = new List<String>(); |
| 187 for (var arg in args) { | 175 for (var arg in args) { |
| 188 var type = FileSystemEntity.typeSync(arg); | 176 var type = FileSystemEntity.typeSync(arg); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 entityMap.values.where((e) => e is Class).forEach((c) => c.makeValid()); | 314 entityMap.values.where((e) => e is Class).forEach((c) => c.makeValid()); |
| 327 // Everything is a subclass of Object, therefore empty the list to avoid a | 315 // Everything is a subclass of Object, therefore empty the list to avoid a |
| 328 // giant list of subclasses to be printed out. | 316 // giant list of subclasses to be printed out. |
| 329 if (includeSdk) (entityMap['dart-core.Object'] as Class).subclasses.clear(); | 317 if (includeSdk) (entityMap['dart-core.Object'] as Class).subclasses.clear(); |
| 330 | 318 |
| 331 var filteredEntities = entityMap.values.where(_isVisible); | 319 var filteredEntities = entityMap.values.where(_isVisible); |
| 332 | 320 |
| 333 // Outputs a JSON file with all libraries and their preview comments. | 321 // Outputs a JSON file with all libraries and their preview comments. |
| 334 // This will help the viewer know what libraries are available to read in. | 322 // This will help the viewer know what libraries are available to read in. |
| 335 var libraryMap; | 323 var libraryMap; |
| 324 var linkResolver = (name) => fixReference(name, null, null, null); |
| 336 if (append) { | 325 if (append) { |
| 337 var docsDir = listDir('docs'); | 326 var docsDir = listDir('docs'); |
| 338 if (!docsDir.contains('docs/library_list.json')) { | 327 if (!docsDir.contains('docs/library_list.json')) { |
| 339 throw new StateError('No library_list.json'); | 328 throw new StateError('No library_list.json'); |
| 340 } | 329 } |
| 341 libraryMap = | 330 libraryMap = |
| 342 JSON.decode(new File('docs/library_list.json').readAsStringSync()); | 331 JSON.decode(new File('docs/library_list.json').readAsStringSync()); |
| 343 libraryMap['libraries'].addAll(filteredEntities | 332 libraryMap['libraries'].addAll(filteredEntities |
| 344 .where((e) => e is Library) | 333 .where((e) => e is Library) |
| 345 .map((e) => e.previewMap)); | 334 .map((e) => e.previewMap)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 filteredEntities.map((e) => e.typeName)); | 369 filteredEntities.map((e) => e.typeName)); |
| 381 if (append) { | 370 if (append) { |
| 382 var previousIndex = | 371 var previousIndex = |
| 383 JSON.decode(new File('docs/index.json').readAsStringSync()); | 372 JSON.decode(new File('docs/index.json').readAsStringSync()); |
| 384 index.addAll(previousIndex); | 373 index.addAll(previousIndex); |
| 385 } | 374 } |
| 386 _writeToFile(JSON.encode(index), 'index.json'); | 375 _writeToFile(JSON.encode(index), 'index.json'); |
| 387 } | 376 } |
| 388 | 377 |
| 389 Library generateLibrary(dart2js.Dart2JsLibraryMirror library) { | 378 Library generateLibrary(dart2js.Dart2JsLibraryMirror library) { |
| 390 _currentLibrary = library; | 379 var result = new Library(docName(library), |
| 391 var result = new Library(docName(library), _commentToHtml(library), | 380 (actualLibrary) => _commentToHtml(library, actualLibrary), |
| 392 _classes(library.classes), | 381 _classes(library.classes), |
| 393 _methods(library.functions), | 382 _methods(library.functions), |
| 394 _variables(library.variables), | 383 _variables(library.variables), |
| 395 _isHidden(library)); | 384 _isHidden(library), library); |
| 396 _findPackage(library, result); | 385 _findPackage(library, result); |
| 397 logger.fine('Generated library for ${result.name}'); | 386 logger.fine('Generated library for ${result.name}'); |
| 398 return result; | 387 return result; |
| 399 } | 388 } |
| 400 | 389 |
| 401 void _writeIndexableToFile(Indexable result, bool outputToYaml) { | 390 void _writeIndexableToFile(Indexable result, bool outputToYaml) { |
| 402 var outputFile = result.fileName; | 391 var outputFile = result.fileName; |
| 403 var output; | 392 var output; |
| 404 if (outputToYaml) { | 393 if (outputToYaml) { |
| 405 output = getYamlString(result.toMap()); | 394 output = getYamlString(result.toMap()); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 .where((e) => e != null) | 445 .where((e) => e != null) |
| 457 .toList(); | 446 .toList(); |
| 458 if (!skippedAnnotations.contains(docName(annotation.type))) { | 447 if (!skippedAnnotations.contains(docName(annotation.type))) { |
| 459 annotations.add(new Annotation(docName(annotation.type), | 448 annotations.add(new Annotation(docName(annotation.type), |
| 460 parameterList)); | 449 parameterList)); |
| 461 } | 450 } |
| 462 }); | 451 }); |
| 463 return annotations; | 452 return annotations; |
| 464 } | 453 } |
| 465 | 454 |
| 466 /// Update the global pointers to the current mirror to the particular mirror | |
| 467 /// we're documenting. | |
| 468 void _updateCurrentMirror(DeclarationMirror mirror) { | |
| 469 if (mirror is LibraryMirror) { | |
| 470 _currentLibrary = mirror; | |
| 471 } else if (mirror is ClassMirror) { | |
| 472 _currentClass = mirror; | |
| 473 } else if (mirror is MethodMirror) { | |
| 474 _currentMember = mirror; | |
| 475 } | |
| 476 } | |
| 477 | |
| 478 /// Returns any documentation comments associated with a mirror with | 455 /// Returns any documentation comments associated with a mirror with |
| 479 /// simple markdown converted to html. | 456 /// simple markdown converted to html. |
| 480 String _commentToHtml(DeclarationMirror mirror) { | 457 /// |
| 458 /// It's possible to have a comment that comes from one mirror applied to |
| 459 /// another, in the case of an inherited comment. |
| 460 String _commentToHtml(DeclarationMirror mirror, [DeclarationMirror appliedTo]) { |
| 461 if (appliedTo == null) appliedTo = mirror; |
| 481 String commentText; | 462 String commentText; |
| 482 _updateCurrentMirror(mirror); | |
| 483 mirror.metadata.forEach((metadata) { | 463 mirror.metadata.forEach((metadata) { |
| 484 if (metadata is CommentInstanceMirror) { | 464 if (metadata is CommentInstanceMirror) { |
| 485 CommentInstanceMirror comment = metadata; | 465 CommentInstanceMirror comment = metadata; |
| 486 if (comment.isDocComment) { | 466 if (comment.isDocComment) { |
| 487 if (commentText == null) { | 467 if (commentText == null) { |
| 488 commentText = comment.trimmedText; | 468 commentText = comment.trimmedText; |
| 489 } else { | 469 } else { |
| 490 commentText = '$commentText\n${comment.trimmedText}'; | 470 commentText = '$commentText\n${comment.trimmedText}'; |
| 491 } | 471 } |
| 492 } | 472 } |
| 493 } | 473 } |
| 494 }); | 474 }); |
| 495 | 475 |
| 476 var linkResolver = (name) => fixReferenceWithScope(name, appliedTo); |
| 496 commentText = commentText == null ? '' : | 477 commentText = commentText == null ? '' : |
| 497 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver, | 478 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver, |
| 498 inlineSyntaxes: markdownSyntaxes); | 479 inlineSyntaxes: markdownSyntaxes); |
| 499 return commentText; | 480 return commentText; |
| 500 } | 481 } |
| 501 | 482 |
| 502 /// Generates MDN comments from database.json. | 483 /// Generates MDN comments from database.json. |
| 503 void _mdnComment(Indexable item) { | 484 void _mdnComment(Indexable item) { |
| 504 //Check if MDN is loaded. | 485 //Check if MDN is loaded. |
| 505 if (_mdn == null) { | 486 if (_mdn == null) { |
| 506 // Reading in MDN related json file. | 487 // Reading in MDN related json file. |
| 507 var root = findRootDirectory(); | 488 var root = findRootDirectory(); |
| 508 var mdnPath = path.join(root, 'utils/apidoc/mdn/database.json'); | 489 var mdnPath = path.join(root, 'utils/apidoc/mdn/database.json'); |
| 509 _mdn = JSON.decode(new File(mdnPath).readAsStringSync()); | 490 _mdn = JSON.decode(new File(mdnPath).readAsStringSync()); |
| 510 } | 491 } |
| 511 if (item.comment.isNotEmpty) return; | 492 if (item is Library) return; |
| 512 var domAnnotation = item.annotations.firstWhere( | 493 var domAnnotation = item.annotations.firstWhere( |
| 513 (e) => e.qualifiedName == 'metadata.DomName', orElse: () => null); | 494 (e) => e.qualifiedName == 'metadata.DomName', orElse: () => null); |
| 514 if (domAnnotation == null) return; | 495 if (domAnnotation == null) return; |
| 515 var domName = domAnnotation.parameters.single; | 496 var domName = domAnnotation.parameters.single; |
| 516 var parts = domName.split('.'); | 497 var parts = domName.split('.'); |
| 517 if (parts.length == 2) item.comment = _mdnMemberComment(parts[0], parts[1]); | 498 if (parts.length == 2) item.comment = _mdnMemberComment(parts[0], parts[1]); |
| 518 if (parts.length == 1) item.comment = _mdnTypeComment(parts[0]); | 499 if (parts.length == 1) item.comment = _mdnTypeComment(parts[0]); |
| 519 } | 500 } |
| 520 | 501 |
| 521 /// Generates the MDN Comment for variables and method DOM elements. | 502 /// Generates the MDN Comment for variables and method DOM elements. |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 ClassMirror currentClass, MemberMirror currentMember) { | 652 ClassMirror currentClass, MemberMirror currentMember) { |
| 672 // Attempt the look up the whole name up in the scope. | 653 // Attempt the look up the whole name up in the scope. |
| 673 String elementName = | 654 String elementName = |
| 674 findElementInScope(name, currentLibrary, currentClass, currentMember); | 655 findElementInScope(name, currentLibrary, currentClass, currentMember); |
| 675 if (elementName != null) { | 656 if (elementName != null) { |
| 676 return new markdown.Element.text('a', elementName); | 657 return new markdown.Element.text('a', elementName); |
| 677 } | 658 } |
| 678 return _fixComplexReference(name, currentLibrary, currentClass, currentMember)
; | 659 return _fixComplexReference(name, currentLibrary, currentClass, currentMember)
; |
| 679 } | 660 } |
| 680 | 661 |
| 662 markdown.Node fixReferenceWithScope(String name, DeclarationMirror scope) { |
| 663 if (scope is LibraryMirror) return fixReference(name, scope, null, null); |
| 664 if (scope is ClassMirror) |
| 665 return fixReference(name, scope.library, scope, null); |
| 666 if (scope is MemberMirror) { |
| 667 var owner = scope.owner; |
| 668 if (owner is ClassMirror) { |
| 669 return fixReference(name, owner.library, owner, scope); |
| 670 } else { |
| 671 return fixReference(name, owner, null, scope); |
| 672 } |
| 673 } |
| 674 return null; |
| 675 } |
| 676 |
| 681 /// Returns a map of [Variable] objects constructed from [mirrorMap]. | 677 /// Returns a map of [Variable] objects constructed from [mirrorMap]. |
| 682 Map<String, Variable> _variables(Map<String, VariableMirror> mirrorMap) { | 678 Map<String, Variable> _variables(Map<String, VariableMirror> mirrorMap) { |
| 683 var data = {}; | 679 var data = {}; |
| 684 // TODO(janicejl): When map to map feature is created, replace the below with | 680 // TODO(janicejl): When map to map feature is created, replace the below with |
| 685 // a filter. Issue(#9590). | 681 // a filter. Issue(#9590). |
| 686 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { | 682 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { |
| 687 _currentMember = mirror; | |
| 688 if (_includePrivate || !_isHidden(mirror)) { | 683 if (_includePrivate || !_isHidden(mirror)) { |
| 689 entityMap[docName(mirror)] = new Variable(mirrorName, mirror.isFinal, | 684 entityMap[docName(mirror)] = new Variable(mirrorName, mirror.isFinal, |
| 690 mirror.isStatic, mirror.isConst, _type(mirror.type), | 685 mirror.isStatic, mirror.isConst, _type(mirror.type), |
| 691 _commentToHtml(mirror), _annotations(mirror), docName(mirror), | 686 (actualVariable) => _commentToHtml(mirror, actualVariable), |
| 692 _isHidden(mirror), docName(mirror.owner)); | 687 _annotations(mirror), docName(mirror), |
| 688 _isHidden(mirror), docName(mirror.owner), mirror); |
| 693 data[mirrorName] = entityMap[docName(mirror)]; | 689 data[mirrorName] = entityMap[docName(mirror)]; |
| 694 } | 690 } |
| 695 }); | 691 }); |
| 696 return data; | 692 return data; |
| 697 } | 693 } |
| 698 | 694 |
| 699 /// Returns a map of [Method] objects constructed from [mirrorMap]. | 695 /// Returns a map of [Method] objects constructed from [mirrorMap]. |
| 700 MethodGroup _methods(Map<String, MethodMirror> mirrorMap) { | 696 MethodGroup _methods(Map<String, MethodMirror> mirrorMap) { |
| 701 var group = new MethodGroup(); | 697 var group = new MethodGroup(); |
| 702 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { | 698 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { |
| 703 if (_includePrivate || !mirror.isPrivate) { | 699 if (_includePrivate || !mirror.isPrivate) { |
| 704 group.addMethod(mirror); | 700 group.addMethod(mirror); |
| 705 } | 701 } |
| 706 }); | 702 }); |
| 707 return group; | 703 return group; |
| 708 } | 704 } |
| 709 | 705 |
| 710 /// Returns the [Class] for the given [mirror] has already been created, and if | 706 /// Returns the [Class] for the given [mirror] has already been created, and if |
| 711 /// it does not exist, creates it. | 707 /// it does not exist, creates it. |
| 712 Class _class(ClassMirror mirror) { | 708 Class _class(ClassMirror mirror) { |
| 713 var clazz = entityMap[docName(mirror)]; | 709 var clazz = entityMap[docName(mirror)]; |
| 714 if (clazz == null) { | 710 if (clazz == null) { |
| 715 var superclass = mirror.superclass != null ? | 711 var superclass = mirror.superclass != null ? |
| 716 _class(mirror.superclass) : null; | 712 _class(mirror.superclass) : null; |
| 717 var interfaces = | 713 var interfaces = |
| 718 mirror.superinterfaces.map((interface) => _class(interface)); | 714 mirror.superinterfaces.map((interface) => _class(interface)); |
| 719 clazz = new Class(mirror.simpleName, superclass, _commentToHtml(mirror), | 715 clazz = new Class(mirror.simpleName, superclass, |
| 716 (actualClass) => _commentToHtml(mirror, actualClass), |
| 720 interfaces.toList(), _variables(mirror.variables), | 717 interfaces.toList(), _variables(mirror.variables), |
| 721 _methods(mirror.methods), _annotations(mirror), _generics(mirror), | 718 _methods(mirror.methods), _annotations(mirror), _generics(mirror), |
| 722 docName(mirror), _isHidden(mirror), docName(mirror.owner), | 719 docName(mirror), _isHidden(mirror), docName(mirror.owner), |
| 723 mirror.isAbstract); | 720 mirror.isAbstract, mirror); |
| 724 if (superclass != null) clazz.addInherited(superclass); | 721 if (superclass != null) clazz.addInherited(superclass); |
| 725 interfaces.forEach((interface) => clazz.addInherited(interface)); | 722 interfaces.forEach((interface) => clazz.addInherited(interface)); |
| 726 entityMap[docName(mirror)] = clazz; | 723 entityMap[docName(mirror)] = clazz; |
| 727 } | 724 } |
| 728 return clazz; | 725 return clazz; |
| 729 } | 726 } |
| 730 | 727 |
| 731 /// Returns a map of [Class] objects constructed from [mirrorMap]. | 728 /// Returns a map of [Class] objects constructed from [mirrorMap]. |
| 732 ClassGroup _classes(Map<String, ClassMirror> mirrorMap) { | 729 ClassGroup _classes(Map<String, ClassMirror> mirrorMap) { |
| 733 var group = new ClassGroup(); | 730 var group = new ClassGroup(); |
| 734 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { | 731 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { |
| 735 group.addClass(mirror); | 732 group.addClass(mirror); |
| 736 }); | 733 }); |
| 737 return group; | 734 return group; |
| 738 } | 735 } |
| 739 | 736 |
| 740 /// Returns a map of [Parameter] objects constructed from [mirrorList]. | 737 /// Returns a map of [Parameter] objects constructed from [mirrorList]. |
| 741 Map<String, Parameter> _parameters(List<ParameterMirror> mirrorList) { | 738 Map<String, Parameter> _parameters(List<ParameterMirror> mirrorList) { |
| 742 var data = {}; | 739 var data = {}; |
| 743 mirrorList.forEach((ParameterMirror mirror) { | 740 mirrorList.forEach((ParameterMirror mirror) { |
| 744 _currentMember = mirror; | |
| 745 data[mirror.simpleName] = new Parameter(mirror.simpleName, | 741 data[mirror.simpleName] = new Parameter(mirror.simpleName, |
| 746 mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, | 742 mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, |
| 747 _type(mirror.type), mirror.defaultValue, | 743 _type(mirror.type), mirror.defaultValue, |
| 748 _annotations(mirror)); | 744 _annotations(mirror)); |
| 749 }); | 745 }); |
| 750 return data; | 746 return data; |
| 751 } | 747 } |
| 752 | 748 |
| 753 /// Returns a map of [Generic] objects constructed from the class mirror. | 749 /// Returns a map of [Generic] objects constructed from the class mirror. |
| 754 Map<String, Generic> _generics(ClassMirror mirror) { | 750 Map<String, Generic> _generics(ClassMirror mirror) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 802 inputMap.forEach((key, value) { | 798 inputMap.forEach((key, value) { |
| 803 if (value is Map) { | 799 if (value is Map) { |
| 804 outputMap[key] = recurseMap(value); | 800 outputMap[key] = recurseMap(value); |
| 805 } else { | 801 } else { |
| 806 outputMap[key] = value.toMap(); | 802 outputMap[key] = value.toMap(); |
| 807 } | 803 } |
| 808 }); | 804 }); |
| 809 return outputMap; | 805 return outputMap; |
| 810 } | 806 } |
| 811 | 807 |
| 808 /// A type for the function that generates a comment from a mirror. |
| 809 typedef String CommentGenerator(Mirror m); |
| 810 |
| 812 /// A class representing all programming constructs, like library or class. | 811 /// A class representing all programming constructs, like library or class. |
| 813 class Indexable { | 812 class Indexable { |
| 814 String name; | 813 String name; |
| 815 String get qualifiedName => fileName; | 814 String get qualifiedName => fileName; |
| 816 bool isPrivate; | 815 bool isPrivate; |
| 816 Mirror mirror; |
| 817 | 817 |
| 818 // The qualified name (for URL purposes) and the file name are the same, | 818 // The qualified name (for URL purposes) and the file name are the same, |
| 819 // of the form packageName/ClassName or packageName/ClassName.methodName. | 819 // of the form packageName/ClassName or packageName/ClassName.methodName. |
| 820 // This defines both the URL and the directory structure. | 820 // This defines both the URL and the directory structure. |
| 821 String get fileName => packagePrefix + ownerPrefix + name; | 821 String get fileName => packagePrefix + ownerPrefix + name; |
| 822 | 822 |
| 823 Indexable get owningEntity { | 823 Indexable get owningEntity => entityMap[owner]; |
| 824 var result = entityMap[owner]; | 824 |
| 825 return result; | |
| 826 } | |
| 827 String get ownerPrefix => owningEntity == null | 825 String get ownerPrefix => owningEntity == null |
| 828 ? (owner == null || owner.isEmpty ? '' : owner + '.') | 826 ? (owner == null || owner.isEmpty ? '' : owner + '.') |
| 829 : owningEntity.qualifiedName + '.'; | 827 : owningEntity.qualifiedName + '.'; |
| 830 | 828 |
| 831 String get packagePrefix => ''; | 829 String get packagePrefix => ''; |
| 830 |
| 832 /// Documentation comment with converted markdown. | 831 /// Documentation comment with converted markdown. |
| 833 String comment; | 832 String _comment; |
| 833 |
| 834 String get comment { |
| 835 if (_comment != null) return _comment; |
| 836 _comment = _commentFunction(mirror); |
| 837 if (_comment.isEmpty) { |
| 838 _mdnComment(this); |
| 839 } |
| 840 return _comment; |
| 841 } |
| 842 |
| 843 set comment(x) => _comment = x; |
| 844 |
| 845 /// We defer evaluating the comment until we have all the context available |
| 846 CommentGenerator _commentFunction; |
| 834 | 847 |
| 835 /// Qualified Name of the owner of this Indexable Item. | 848 /// Qualified Name of the owner of this Indexable Item. |
| 836 /// For Library, owner will be ""; | 849 /// For Library, owner will be ""; |
| 837 String owner; | 850 String owner; |
| 838 | 851 |
| 839 Indexable(this.name, this.comment, this.isPrivate, this.owner); | 852 Indexable(this.name, this._commentFunction, this.isPrivate, this.owner, |
| 853 this.mirror); |
| 840 | 854 |
| 841 /// The type of this member to be used in index.txt. | 855 /// The type of this member to be used in index.txt. |
| 842 String get typeName => ''; | 856 String get typeName => ''; |
| 843 | 857 |
| 844 /// Creates a [Map] with this [Indexable]'s name and a preview comment. | 858 /// Creates a [Map] with this [Indexable]'s name and a preview comment. |
| 845 Map get previewMap { | 859 Map get previewMap { |
| 846 var finalMap = { 'name' : name, 'qualifiedName' : qualifiedName }; | 860 var finalMap = { 'name' : name, 'qualifiedName' : qualifiedName }; |
| 847 if (comment != '') { | 861 if (comment != '') { |
| 848 var index = comment.indexOf('</p>'); | 862 var index = comment.indexOf('</p>'); |
| 849 finalMap['preview'] = '${comment.substring(0, index)}</p>'; | 863 finalMap['preview'] = '${comment.substring(0, index)}</p>'; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 | 895 |
| 882 Map get previewMap { | 896 Map get previewMap { |
| 883 var basic = super.previewMap; | 897 var basic = super.previewMap; |
| 884 basic['packageName'] = packageName; | 898 basic['packageName'] = packageName; |
| 885 if (packageIntro != null) { | 899 if (packageIntro != null) { |
| 886 basic['packageIntro'] = packageIntro; | 900 basic['packageIntro'] = packageIntro; |
| 887 } | 901 } |
| 888 return basic; | 902 return basic; |
| 889 } | 903 } |
| 890 | 904 |
| 891 Library(String name, String comment, this.classes, this.functions, | 905 Library(String name, Function commentFunction, this.classes, this.functions, |
| 892 this.variables, bool isPrivate) : super(name, comment, | 906 this.variables, bool isPrivate, Mirror mirror) |
| 893 isPrivate, ""); | 907 : super(name, commentFunction, isPrivate, "", mirror); |
| 894 | 908 |
| 895 /// Generates a map describing the [Library] object. | 909 /// Generates a map describing the [Library] object. |
| 896 Map toMap() => { | 910 Map toMap() => { |
| 897 'name': name, | 911 'name': name, |
| 898 'qualifiedName': qualifiedName, | 912 'qualifiedName': qualifiedName, |
| 899 'comment': comment, | 913 'comment': comment, |
| 900 'variables': recurseMap(variables), | 914 'variables': recurseMap(variables), |
| 901 'functions': functions.toMap(), | 915 'functions': functions.toMap(), |
| 902 'classes': classes.toMap(), | 916 'classes': classes.toMap(), |
| 903 'packageName': packageName, | 917 'packageName': packageName, |
| (...skipping 26 matching lines...) Expand all Loading... |
| 930 | 944 |
| 931 /// Generic infomation about the class. | 945 /// Generic infomation about the class. |
| 932 Map<String, Generic> generics; | 946 Map<String, Generic> generics; |
| 933 | 947 |
| 934 Class superclass; | 948 Class superclass; |
| 935 bool isAbstract; | 949 bool isAbstract; |
| 936 | 950 |
| 937 /// List of the meta annotations on the class. | 951 /// List of the meta annotations on the class. |
| 938 List<Annotation> annotations; | 952 List<Annotation> annotations; |
| 939 | 953 |
| 940 Class(String name, this.superclass, String comment, this.interfaces, | 954 /// Make sure that we don't check for inherited comments more than once. |
| 955 bool _commentsEnsured = false; |
| 956 |
| 957 Class(String name, this.superclass, Function commentFunction, this.interfaces, |
| 941 this.variables, this.methods, this.annotations, this.generics, | 958 this.variables, this.methods, this.annotations, this.generics, |
| 942 String qualifiedName, bool isPrivate, String owner, this.isAbstract) | 959 String qualifiedName, bool isPrivate, String owner, this.isAbstract, |
| 943 : super(name, comment, isPrivate, owner) { | 960 Mirror mirror) |
| 944 _mdnComment(this); | 961 : super(name, commentFunction, isPrivate, owner, mirror); |
| 945 } | |
| 946 | 962 |
| 947 String get typeName => 'class'; | 963 String get typeName => 'class'; |
| 948 | 964 |
| 949 /// Returns a list of all the parent classes. | 965 /// Returns a list of all the parent classes. |
| 950 List<Class> parent() { | 966 List<Class> parent() { |
| 951 var parent = superclass == null ? [] : [superclass]; | 967 var parent = superclass == null ? [] : [superclass]; |
| 952 parent.addAll(interfaces); | 968 parent.addAll(interfaces); |
| 953 return parent; | 969 return parent; |
| 954 } | 970 } |
| 955 | 971 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 // with the mixin as an owner private too. | 1017 // with the mixin as an owner private too. |
| 1002 entityMap.values.where((e) => e.owner == qualifiedName) | 1018 entityMap.values.where((e) => e.owner == qualifiedName) |
| 1003 .forEach((element) => element.isPrivate = true); | 1019 .forEach((element) => element.isPrivate = true); |
| 1004 // Move the subclass up to the next public superclass | 1020 // Move the subclass up to the next public superclass |
| 1005 subclasses.forEach((subclass) => addSubclass(subclass)); | 1021 subclasses.forEach((subclass) => addSubclass(subclass)); |
| 1006 } | 1022 } |
| 1007 } | 1023 } |
| 1008 | 1024 |
| 1009 /// Makes sure that all methods with inherited equivalents have comments. | 1025 /// Makes sure that all methods with inherited equivalents have comments. |
| 1010 void ensureComments() { | 1026 void ensureComments() { |
| 1027 if (_commentsEnsured) return; |
| 1028 _commentsEnsured = true; |
| 1011 inheritedMethods.forEach((qualifiedName, inheritedMethod) { | 1029 inheritedMethods.forEach((qualifiedName, inheritedMethod) { |
| 1012 var method = methods[qualifiedName]; | 1030 var method = methods[qualifiedName]; |
| 1013 if (method != null) method.ensureCommentFor(inheritedMethod); | 1031 if (method != null) method.ensureCommentFor(inheritedMethod); |
| 1014 }); | 1032 }); |
| 1015 } | 1033 } |
| 1016 | 1034 |
| 1017 /// If a class extends a private superclass, find the closest public superclas
s | 1035 /// If a class extends a private superclass, find the closest public superclas
s |
| 1018 /// of the private superclass. | 1036 /// of the private superclass. |
| 1019 String validSuperclass() { | 1037 String validSuperclass() { |
| 1020 if (superclass == null) return 'dart.core.Object'; | 1038 if (superclass == null) return 'dart.core.Object'; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1044 int compareTo(aClass) => name.compareTo(aClass.name); | 1062 int compareTo(aClass) => name.compareTo(aClass.name); |
| 1045 } | 1063 } |
| 1046 | 1064 |
| 1047 /// A container to categorize classes into the following groups: abstract | 1065 /// A container to categorize classes into the following groups: abstract |
| 1048 /// classes, regular classes, typedefs, and errors. | 1066 /// classes, regular classes, typedefs, and errors. |
| 1049 class ClassGroup { | 1067 class ClassGroup { |
| 1050 Map<String, Class> classes = {}; | 1068 Map<String, Class> classes = {}; |
| 1051 Map<String, Typedef> typedefs = {}; | 1069 Map<String, Typedef> typedefs = {}; |
| 1052 Map<String, Class> errors = {}; | 1070 Map<String, Class> errors = {}; |
| 1053 | 1071 |
| 1054 void addClass(ClassMirror mirror) { | 1072 void addClass(ClassMirror classMirror) { |
| 1055 _currentClass = mirror; | 1073 if (classMirror.isTypedef) { |
| 1056 if (mirror.isTypedef) { | |
| 1057 // This is actually a Dart2jsTypedefMirror, and it does define value, | 1074 // This is actually a Dart2jsTypedefMirror, and it does define value, |
| 1058 // but we don't have visibility to that type. | 1075 // but we don't have visibility to that type. |
| 1059 var mirror = _currentClass; | 1076 var mirror = classMirror; |
| 1060 if (_includePrivate || !mirror.isPrivate) { | 1077 if (_includePrivate || !mirror.isPrivate) { |
| 1061 entityMap[docName(mirror)] = new Typedef(mirror.simpleName, | 1078 entityMap[docName(mirror)] = new Typedef(mirror.simpleName, |
| 1062 docName(mirror.value.returnType), _commentToHtml(mirror), | 1079 docName(mirror.value.returnType), |
| 1080 (actualTypedef) => _commentToHtml(mirror, actualTypedef), |
| 1063 _generics(mirror), _parameters(mirror.value.parameters), | 1081 _generics(mirror), _parameters(mirror.value.parameters), |
| 1064 _annotations(mirror), docName(mirror), _isHidden(mirror), | 1082 _annotations(mirror), docName(mirror), _isHidden(mirror), |
| 1065 docName(mirror.owner)); | 1083 docName(mirror.owner), mirror); |
| 1066 typedefs[mirror.simpleName] = entityMap[docName(mirror)]; | 1084 typedefs[mirror.simpleName] = entityMap[docName(mirror)]; |
| 1067 } | 1085 } |
| 1068 } else { | 1086 } else { |
| 1069 var clazz = _class(mirror); | 1087 var clazz = _class(classMirror); |
| 1070 | 1088 |
| 1071 // Adding inherited parent variables and methods. | 1089 // Adding inherited parent variables and methods. |
| 1072 clazz.parent().forEach((parent) { | 1090 clazz.parent().forEach((parent) { |
| 1073 if (_isVisible(clazz)) { | 1091 if (_isVisible(clazz)) { |
| 1074 parent.addSubclass(clazz); | 1092 parent.addSubclass(clazz); |
| 1075 } | 1093 } |
| 1076 }); | 1094 }); |
| 1077 | 1095 |
| 1078 clazz.ensureComments(); | |
| 1079 | |
| 1080 if (clazz.isError()) { | 1096 if (clazz.isError()) { |
| 1081 errors[mirror.simpleName] = clazz; | 1097 errors[classMirror.simpleName] = clazz; |
| 1082 } else if (mirror.isClass) { | 1098 } else if (classMirror.isClass) { |
| 1083 classes[mirror.simpleName] = clazz; | 1099 classes[classMirror.simpleName] = clazz; |
| 1084 } else { | 1100 } else { |
| 1085 throw new ArgumentError('${mirror.simpleName} - no class type match. '); | 1101 throw new ArgumentError( |
| 1102 '${classMirror.simpleName} - no class type match. '); |
| 1086 } | 1103 } |
| 1087 } | 1104 } |
| 1088 } | 1105 } |
| 1089 | 1106 |
| 1090 /// Checks if the given name is a key for any of the Class Maps. | 1107 /// Checks if the given name is a key for any of the Class Maps. |
| 1091 bool containsKey(String name) { | 1108 bool containsKey(String name) { |
| 1092 return classes.containsKey(name) || errors.containsKey(name); | 1109 return classes.containsKey(name) || errors.containsKey(name); |
| 1093 } | 1110 } |
| 1094 | 1111 |
| 1095 Map toMap() => { | 1112 Map toMap() => { |
| 1096 'class': classes.values.where(_isVisible) | 1113 'class': classes.values.where(_isVisible) |
| 1097 .map((e) => e.previewMap).toList(), | 1114 .map((e) => e.previewMap).toList(), |
| 1098 'typedef': recurseMap(typedefs), | 1115 'typedef': recurseMap(typedefs), |
| 1099 'error': errors.values.where(_isVisible) | 1116 'error': errors.values.where(_isVisible) |
| 1100 .map((e) => e.previewMap).toList() | 1117 .map((e) => e.previewMap).toList() |
| 1101 }; | 1118 }; |
| 1102 } | 1119 } |
| 1103 | 1120 |
| 1104 class Typedef extends Indexable { | 1121 class Typedef extends Indexable { |
| 1105 String returnType; | 1122 String returnType; |
| 1106 | 1123 |
| 1107 Map<String, Parameter> parameters; | 1124 Map<String, Parameter> parameters; |
| 1108 | 1125 |
| 1109 /// Generic information about the typedef. | 1126 /// Generic information about the typedef. |
| 1110 Map<String, Generic> generics; | 1127 Map<String, Generic> generics; |
| 1111 | 1128 |
| 1112 /// List of the meta annotations on the typedef. | 1129 /// List of the meta annotations on the typedef. |
| 1113 List<Annotation> annotations; | 1130 List<Annotation> annotations; |
| 1114 | 1131 |
| 1115 Typedef(String name, this.returnType, String comment, this.generics, | 1132 Typedef(String name, this.returnType, Function commentFunction, this.generics, |
| 1116 this.parameters, this.annotations, | 1133 this.parameters, this.annotations, |
| 1117 String qualifiedName, bool isPrivate, String owner) | 1134 String qualifiedName, bool isPrivate, String owner, Mirror mirror) |
| 1118 : super(name, comment, isPrivate, owner); | 1135 : super(name, commentFunction, isPrivate, owner, mirror); |
| 1119 | 1136 |
| 1120 Map toMap() => { | 1137 Map toMap() => { |
| 1121 'name': name, | 1138 'name': name, |
| 1122 'qualifiedName': qualifiedName, | 1139 'qualifiedName': qualifiedName, |
| 1123 'comment': comment, | 1140 'comment': comment, |
| 1124 'return': returnType, | 1141 'return': returnType, |
| 1125 'parameters': recurseMap(parameters), | 1142 'parameters': recurseMap(parameters), |
| 1126 'annotations': annotations.map((a) => a.toMap()).toList(), | 1143 'annotations': annotations.map((a) => a.toMap()).toList(), |
| 1127 'generics': recurseMap(generics) | 1144 'generics': recurseMap(generics) |
| 1128 }; | 1145 }; |
| 1129 | 1146 |
| 1130 String get typeName => 'typedef'; | 1147 String get typeName => 'typedef'; |
| 1131 } | 1148 } |
| 1132 | 1149 |
| 1133 /// A class containing properties of a Dart variable. | 1150 /// A class containing properties of a Dart variable. |
| 1134 class Variable extends Indexable { | 1151 class Variable extends Indexable { |
| 1135 | 1152 |
| 1136 bool isFinal; | 1153 bool isFinal; |
| 1137 bool isStatic; | 1154 bool isStatic; |
| 1138 bool isConst; | 1155 bool isConst; |
| 1139 Type type; | 1156 Type type; |
| 1140 | 1157 |
| 1141 /// List of the meta annotations on the variable. | 1158 /// List of the meta annotations on the variable. |
| 1142 List<Annotation> annotations; | 1159 List<Annotation> annotations; |
| 1143 | 1160 |
| 1144 Variable(String name, this.isFinal, this.isStatic, this.isConst, this.type, | 1161 Variable(String name, this.isFinal, this.isStatic, this.isConst, this.type, |
| 1145 String comment, this.annotations, String qualifiedName, bool isPrivate, | 1162 Function commentFunction, this.annotations, String qualifiedName, |
| 1146 String owner) : super(name, comment, isPrivate, owner) { | 1163 bool isPrivate, String owner, Mirror mirror) |
| 1147 _mdnComment(this); | 1164 : super(name, commentFunction, isPrivate, owner, mirror) { |
| 1148 } | 1165 } |
| 1149 | 1166 |
| 1150 /// Generates a map describing the [Variable] object. | 1167 /// Generates a map describing the [Variable] object. |
| 1151 Map toMap() => { | 1168 Map toMap() => { |
| 1152 'name': name, | 1169 'name': name, |
| 1153 'qualifiedName': qualifiedName, | 1170 'qualifiedName': qualifiedName, |
| 1154 'comment': comment, | 1171 'comment': comment, |
| 1155 'final': isFinal.toString(), | 1172 'final': isFinal.toString(), |
| 1156 'static': isStatic.toString(), | 1173 'static': isStatic.toString(), |
| 1157 'constant': isConst.toString(), | 1174 'constant': isConst.toString(), |
| 1158 'type': new List.filled(1, type.toMap()), | 1175 'type': new List.filled(1, type.toMap()), |
| 1159 'annotations': annotations.map((a) => a.toMap()).toList() | 1176 'annotations': annotations.map((a) => a.toMap()).toList() |
| 1160 }; | 1177 }; |
| 1161 | 1178 |
| 1162 String get typeName => 'property'; | 1179 String get typeName => 'property'; |
| 1180 |
| 1181 get comment { |
| 1182 if (_comment != null) return _comment; |
| 1183 var owningClass = owningEntity; |
| 1184 if (owningClass is Class) { |
| 1185 owningClass.ensureComments(); |
| 1186 } |
| 1187 return super.comment; |
| 1188 } |
| 1163 } | 1189 } |
| 1164 | 1190 |
| 1165 /// A class containing properties of a Dart method. | 1191 /// A class containing properties of a Dart method. |
| 1166 class Method extends Indexable { | 1192 class Method extends Indexable { |
| 1167 | 1193 |
| 1168 /// Parameters for this method. | 1194 /// Parameters for this method. |
| 1169 Map<String, Parameter> parameters; | 1195 Map<String, Parameter> parameters; |
| 1170 | 1196 |
| 1171 bool isStatic; | 1197 bool isStatic; |
| 1172 bool isAbstract; | 1198 bool isAbstract; |
| 1173 bool isConst; | 1199 bool isConst; |
| 1174 bool isConstructor; | 1200 bool isConstructor; |
| 1175 bool isGetter; | 1201 bool isGetter; |
| 1176 bool isSetter; | 1202 bool isSetter; |
| 1177 bool isOperator; | 1203 bool isOperator; |
| 1178 Type returnType; | 1204 Type returnType; |
| 1179 | 1205 |
| 1180 /// Qualified name to state where the comment is inherited from. | 1206 /// Qualified name to state where the comment is inherited from. |
| 1181 String commentInheritedFrom = ""; | 1207 String commentInheritedFrom = ""; |
| 1182 | 1208 |
| 1183 /// List of the meta annotations on the method. | 1209 /// List of the meta annotations on the method. |
| 1184 List<Annotation> annotations; | 1210 List<Annotation> annotations; |
| 1185 | 1211 |
| 1186 Method(String name, this.isStatic, this.isAbstract, this.isConst, | 1212 Method(String name, this.isStatic, this.isAbstract, this.isConst, |
| 1187 this.returnType, String comment, this.parameters, this.annotations, | 1213 this.returnType, Function commentFunction, this.parameters, |
| 1214 this.annotations, |
| 1188 String qualifiedName, bool isPrivate, String owner, this.isConstructor, | 1215 String qualifiedName, bool isPrivate, String owner, this.isConstructor, |
| 1189 this.isGetter, this.isSetter, this.isOperator) | 1216 this.isGetter, this.isSetter, this.isOperator, Mirror mirror) |
| 1190 : super(name, comment, isPrivate, owner) { | 1217 : super(name, commentFunction, isPrivate, owner, mirror) { |
| 1191 _mdnComment(this); | |
| 1192 } | 1218 } |
| 1193 | 1219 |
| 1194 /// Makes sure that the method with an inherited equivalent have comments. | 1220 /// Makes sure that the method with an inherited equivalent have comments. |
| 1195 void ensureCommentFor(Method inheritedMethod) { | 1221 void ensureCommentFor(Method inheritedMethod) { |
| 1196 if (comment.isNotEmpty) return; | 1222 if (comment.isNotEmpty) return; |
| 1197 (entityMap[inheritedMethod.owner] as Class).ensureComments(); | 1223 comment = inheritedMethod._commentFunction(mirror); |
| 1198 comment = inheritedMethod.comment; | |
| 1199 commentInheritedFrom = inheritedMethod.commentInheritedFrom == '' ? | 1224 commentInheritedFrom = inheritedMethod.commentInheritedFrom == '' ? |
| 1200 inheritedMethod.qualifiedName : inheritedMethod.commentInheritedFrom; | 1225 inheritedMethod.qualifiedName : inheritedMethod.commentInheritedFrom; |
| 1201 } | 1226 } |
| 1202 | 1227 |
| 1203 /// Generates a map describing the [Method] object. | 1228 /// Generates a map describing the [Method] object. |
| 1204 Map toMap() => { | 1229 Map toMap() => { |
| 1205 'name': name, | 1230 'name': name, |
| 1206 'qualifiedName': qualifiedName, | 1231 'qualifiedName': qualifiedName, |
| 1207 'comment': comment, | 1232 'comment': comment, |
| 1208 'commentFrom': commentInheritedFrom, | 1233 'commentFrom': commentInheritedFrom, |
| 1209 'static': isStatic.toString(), | 1234 'static': isStatic.toString(), |
| 1210 'abstract': isAbstract.toString(), | 1235 'abstract': isAbstract.toString(), |
| 1211 'constant': isConst.toString(), | 1236 'constant': isConst.toString(), |
| 1212 'return': new List.filled(1, returnType.toMap()), | 1237 'return': new List.filled(1, returnType.toMap()), |
| 1213 'parameters': recurseMap(parameters), | 1238 'parameters': recurseMap(parameters), |
| 1214 'annotations': annotations.map((a) => a.toMap()).toList() | 1239 'annotations': annotations.map((a) => a.toMap()).toList() |
| 1215 }; | 1240 }; |
| 1216 | 1241 |
| 1217 String get typeName => isConstructor ? 'constructor' : | 1242 String get typeName => isConstructor ? 'constructor' : |
| 1218 isGetter ? 'getter' : isSetter ? 'setter' : | 1243 isGetter ? 'getter' : isSetter ? 'setter' : |
| 1219 isOperator ? 'operator' : 'method'; | 1244 isOperator ? 'operator' : 'method'; |
| 1245 |
| 1246 get comment { |
| 1247 if (_comment != null) return _comment; |
| 1248 var owningClass = owningEntity; |
| 1249 if (owningClass is Class) { |
| 1250 owningClass.ensureComments(); |
| 1251 } |
| 1252 return super.comment; |
| 1253 } |
| 1220 } | 1254 } |
| 1221 | 1255 |
| 1222 /// A container to categorize methods into the following groups: setters, | 1256 /// A container to categorize methods into the following groups: setters, |
| 1223 /// getters, constructors, operators, regular methods. | 1257 /// getters, constructors, operators, regular methods. |
| 1224 class MethodGroup { | 1258 class MethodGroup { |
| 1225 Map<String, Method> setters = {}; | 1259 Map<String, Method> setters = {}; |
| 1226 Map<String, Method> getters = {}; | 1260 Map<String, Method> getters = {}; |
| 1227 Map<String, Method> constructors = {}; | 1261 Map<String, Method> constructors = {}; |
| 1228 Map<String, Method> operators = {}; | 1262 Map<String, Method> operators = {}; |
| 1229 Map<String, Method> regularMethods = {}; | 1263 Map<String, Method> regularMethods = {}; |
| 1230 | 1264 |
| 1231 void addMethod(MethodMirror mirror) { | 1265 void addMethod(MethodMirror mirror) { |
| 1232 var method = new Method(mirror.simpleName, mirror.isStatic, | 1266 var method = new Method(mirror.simpleName, mirror.isStatic, |
| 1233 mirror.isAbstract, mirror.isConstConstructor, _type(mirror.returnType), | 1267 mirror.isAbstract, mirror.isConstConstructor, _type(mirror.returnType), |
| 1234 _commentToHtml(mirror), _parameters(mirror.parameters), | 1268 (actualMethod) => _commentToHtml(mirror, actualMethod), |
| 1269 _parameters(mirror.parameters), |
| 1235 _annotations(mirror), docName(mirror), _isHidden(mirror), | 1270 _annotations(mirror), docName(mirror), _isHidden(mirror), |
| 1236 docName(mirror.owner), mirror.isConstructor, mirror.isGetter, | 1271 docName(mirror.owner), mirror.isConstructor, mirror.isGetter, |
| 1237 mirror.isSetter, mirror.isOperator); | 1272 mirror.isSetter, mirror.isOperator, mirror); |
| 1238 entityMap[docName(mirror)] = method; | 1273 entityMap[docName(mirror)] = method; |
| 1239 _currentMember = mirror; | |
| 1240 if (mirror.isSetter) { | 1274 if (mirror.isSetter) { |
| 1241 setters[mirror.simpleName] = method; | 1275 setters[mirror.simpleName] = method; |
| 1242 } else if (mirror.isGetter) { | 1276 } else if (mirror.isGetter) { |
| 1243 getters[mirror.simpleName] = method; | 1277 getters[mirror.simpleName] = method; |
| 1244 } else if (mirror.isConstructor) { | 1278 } else if (mirror.isConstructor) { |
| 1245 constructors[mirror.simpleName] = method; | 1279 constructors[mirror.simpleName] = method; |
| 1246 } else if (mirror.isOperator) { | 1280 } else if (mirror.isOperator) { |
| 1247 operators[mirror.simpleName] = method; | 1281 operators[mirror.simpleName] = method; |
| 1248 } else if (mirror.isRegularMethod) { | 1282 } else if (mirror.isRegularMethod) { |
| 1249 regularMethods[mirror.simpleName] = method; | 1283 regularMethods[mirror.simpleName] = method; |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 /// Remove statics from the map of inherited items before adding them. | 1434 /// Remove statics from the map of inherited items before adding them. |
| 1401 Map _filterStatics(Map items) { | 1435 Map _filterStatics(Map items) { |
| 1402 var result = {}; | 1436 var result = {}; |
| 1403 items.forEach((name, item) { | 1437 items.forEach((name, item) { |
| 1404 if (!item.isStatic) { | 1438 if (!item.isStatic) { |
| 1405 result[name] = item; | 1439 result[name] = item; |
| 1406 } | 1440 } |
| 1407 }); | 1441 }); |
| 1408 return result; | 1442 return result; |
| 1409 } | 1443 } |
| OLD | NEW |