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 /** | 5 /** |
| 6 * **docgen** is a tool for creating machine readable representations of Dart | 6 * **docgen** is a tool for creating machine readable representations of Dart |
| 7 * code metadata, including: classes, members, comments and annotations. | 7 * code metadata, including: classes, members, comments and annotations. |
| 8 * | 8 * |
| 9 * docgen is run on a `.dart` file or a directory containing `.dart` files. | 9 * docgen is run on a `.dart` file or a directory containing `.dart` files. |
| 10 * | 10 * |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 58 /// Resolves reference links in doc comments. | 58 /// Resolves reference links in doc comments. |
| 59 markdown.Resolver linkResolver; | 59 markdown.Resolver linkResolver; |
| 60 | 60 |
| 61 /// Index of all indexable items. This also ensures that no class is | 61 /// Index of all indexable items. This also ensures that no class is |
| 62 /// created more than once. | 62 /// created more than once. |
| 63 Map<String, Indexable> entityMap = new Map<String, Indexable>(); | 63 Map<String, Indexable> entityMap = new Map<String, Indexable>(); |
| 64 | 64 |
| 65 /// This is set from the command line arguments flag --include-private | 65 /// This is set from the command line arguments flag --include-private |
| 66 bool _includePrivate = false; | 66 bool _includePrivate = false; |
| 67 | 67 |
| 68 /// Map of all the comments for dom elements from MDN. | |
| 69 Map _mdn; | |
| 70 | |
| 68 /** | 71 /** |
| 69 * Docgen constructor initializes the link resolver for markdown parsing. | 72 * Docgen constructor initializes the link resolver for markdown parsing. |
| 70 * Also initializes the command line arguments. | 73 * Also initializes the command line arguments. |
| 71 * | 74 * |
| 72 * [packageRoot] is the packages directory of the directory being analyzed. | 75 * [packageRoot] is the packages directory of the directory being analyzed. |
| 73 * If [includeSdk] is `true`, then any SDK libraries explicitly imported will | 76 * If [includeSdk] is `true`, then any SDK libraries explicitly imported will |
| 74 * also be documented. | 77 * also be documented. |
| 75 * If [parseSdk] is `true`, then all Dart SDK libraries will be documented. | 78 * If [parseSdk] is `true`, then all Dart SDK libraries will be documented. |
| 76 * This option is useful when only the SDK libraries are needed. | 79 * This option is useful when only the SDK libraries are needed. |
| 77 * | 80 * |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 89 if (packageRoot == null && !parseSdk) { | 92 if (packageRoot == null && !parseSdk) { |
| 90 var type = FileSystemEntity.typeSync(files.first); | 93 var type = FileSystemEntity.typeSync(files.first); |
| 91 if (type == FileSystemEntityType.DIRECTORY) { | 94 if (type == FileSystemEntityType.DIRECTORY) { |
| 92 packageRoot = _findPackageRoot(files.first); | 95 packageRoot = _findPackageRoot(files.first); |
| 93 } else if (type == FileSystemEntityType.FILE) { | 96 } else if (type == FileSystemEntityType.FILE) { |
| 94 logger.warning('WARNING: No package root defined. If Docgen fails, try ' | 97 logger.warning('WARNING: No package root defined. If Docgen fails, try ' |
| 95 'again by setting the --package-root option.'); | 98 'again by setting the --package-root option.'); |
| 96 } | 99 } |
| 97 } | 100 } |
| 98 logger.info('Package Root: ${packageRoot}'); | 101 logger.info('Package Root: ${packageRoot}'); |
| 99 | 102 |
|
Emily Fortuna
2013/08/15 17:05:42
remove whitespace please.
janicejl
2013/08/15 17:45:19
Done.
| |
| 100 linkResolver = (name) => | 103 linkResolver = (name) => |
| 101 fixReference(name, _currentLibrary, _currentClass, _currentMember); | 104 fixReference(name, _currentLibrary, _currentClass, _currentMember); |
| 102 | 105 |
| 103 return getMirrorSystem(files, packageRoot: packageRoot, parseSdk: parseSdk) | 106 return getMirrorSystem(files, packageRoot: packageRoot, parseSdk: parseSdk) |
| 104 .then((MirrorSystem mirrorSystem) { | 107 .then((MirrorSystem mirrorSystem) { |
| 105 if (mirrorSystem.libraries.isEmpty) { | 108 if (mirrorSystem.libraries.isEmpty) { |
| 106 throw new StateError('No library mirrors were created.'); | 109 throw new StateError('No library mirrors were created.'); |
| 107 } | 110 } |
| 108 _documentLibraries(mirrorSystem.libraries.values,includeSdk: includeSdk, | 111 _documentLibraries(mirrorSystem.libraries.values,includeSdk: includeSdk, |
| 109 outputToYaml: outputToYaml, append: append, parseSdk: parseSdk); | 112 outputToYaml: outputToYaml, append: append, parseSdk: parseSdk); |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 306 } | 309 } |
| 307 } | 310 } |
| 308 | 311 |
| 309 bool _isVisible(Indexable item) { | 312 bool _isVisible(Indexable item) { |
| 310 return _includePrivate || !item.isPrivate; | 313 return _includePrivate || !item.isPrivate; |
| 311 } | 314 } |
| 312 | 315 |
| 313 /** | 316 /** |
| 314 * Returns a list of meta annotations assocated with a mirror. | 317 * Returns a list of meta annotations assocated with a mirror. |
| 315 */ | 318 */ |
| 316 List<String> _annotations(DeclarationMirror mirror) { | 319 List<Annotation> _annotations(DeclarationMirror mirror) { |
| 317 var annotationMirrors = mirror.metadata.where((e) => | 320 var annotationMirrors = mirror.metadata.where((e) => |
| 318 e is dart2js.Dart2JsConstructedConstantMirror); | 321 e is dart2js.Dart2JsConstructedConstantMirror); |
| 319 var annotations = []; | 322 var annotations = []; |
| 320 annotationMirrors.forEach((annotation) { | 323 annotationMirrors.forEach((annotation) { |
| 321 var parameterList = annotation.type.variables.values | 324 var parameterList = annotation.type.variables.values |
| 322 .where((e) => e.isFinal) | 325 .where((e) => e.isFinal) |
| 323 .map((e) => annotation.getField(e.simpleName).reflectee) | 326 .map((e) => annotation.getField(e.simpleName).reflectee) |
| 324 .where((e) => e != null) | 327 .where((e) => e != null) |
| 325 .toList(); | 328 .toList(); |
| 326 if (validAnnotations.contains(annotation.type.qualifiedName)) { | 329 if (validAnnotations.contains(annotation.type.qualifiedName)) { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 350 } | 353 } |
| 351 }); | 354 }); |
| 352 | 355 |
| 353 commentText = commentText == null ? '' : | 356 commentText = commentText == null ? '' : |
| 354 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver, | 357 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver, |
| 355 inlineSyntaxes: markdownSyntaxes); | 358 inlineSyntaxes: markdownSyntaxes); |
| 356 return commentText; | 359 return commentText; |
| 357 } | 360 } |
| 358 | 361 |
| 359 /** | 362 /** |
| 363 * Generates MDN comments from database.json. | |
| 364 */ | |
| 365 void _mdnComment(Indexable item) { | |
| 366 //Check if MDN is loaded. | |
| 367 if (_mdn == null) { | |
| 368 // Reading in MDN related json file. | |
| 369 var mdnDir = path.join(path.dirname(path.dirname(path.dirname(path.dirname( | |
| 370 path.absolute(new Options().script))))), 'utils', 'apidoc', 'mdn'); | |
| 371 _mdn = parse(new File(path.join(mdnDir, 'database.json')) | |
| 372 .readAsStringSync()); | |
| 373 } | |
| 374 if (item.comment != null && item.comment != '') return; | |
| 375 var domAnnotation = item.annotations.where( | |
| 376 (e) => e.qualifiedName == 'metadata.DomName'); | |
| 377 if (domAnnotation.length != 1) return; | |
|
Emily Fortuna
2013/08/15 17:05:42
are there places where we have more than one domAn
janicejl
2013/08/15 17:45:19
I do not think so. But it is possible for there to
Emily Fortuna
2013/08/15 18:13:05
Right, so firstWhere would be appropriate here, to
janicejl
2013/08/15 18:38:11
Done.
| |
| 378 var domname = domAnnotation.single.parameters.single; | |
|
Emily Fortuna
2013/08/15 17:05:42
domName
janicejl
2013/08/15 17:45:19
Done.
| |
| 379 var parts = domname.split('.'); | |
| 380 if (parts.length == 2) item.comment = _mdnMemberComment(parts[0], parts[1]); | |
| 381 if (parts.length == 1) item.comment = _mdnTypeComment(parts[0]); | |
| 382 } | |
| 383 | |
| 384 /** | |
| 385 * Generates the MDN Comment for variables and method DOM elements. | |
| 386 */ | |
| 387 String _mdnMemberComment(String type, String member) { | |
| 388 var mdnType = _mdn[type]; | |
| 389 if (mdnType == null) return ''; | |
| 390 | |
| 391 var mdnMemberList = mdnType['members'].where((e) => e['name'] == member); | |
|
Emily Fortuna
2013/08/15 17:05:42
what about just calling firstWhere instead?
janicejl
2013/08/15 17:45:19
Done.
| |
| 392 var mdnMember = mdnMemberList.length == 1 ? mdnMemberList.single : null; | |
| 393 | |
| 394 if (mdnMember == null) return ''; | |
| 395 if (mdnMember['help'] == null || mdnMember['help'] == '') return ''; | |
| 396 if (mdnMember['url'] == null) return ''; | |
| 397 | |
| 398 var comment = '<div class="mdn">' + mdnMember['help'].trim() + | |
| 399 '<p class="mdn-note"><a href="' + mdnMember['url'].trim() + | |
|
Emily Fortuna
2013/08/15 17:05:42
can this string and the one below be shared since
janicejl
2013/08/15 17:45:19
Done.
| |
| 400 '">from Mdn</a></p></div>'; | |
| 401 | |
| 402 return comment; | |
| 403 } | |
| 404 | |
| 405 /** | |
| 406 * Generates the MDN Comment for class DOM elements. | |
| 407 */ | |
| 408 String _mdnTypeComment(String type) { | |
| 409 var mdnType = _mdn[type]; | |
| 410 if (mdnType == null) return ''; | |
| 411 if (mdnType['summary'] == null || mdnType['summary'] == "") return ''; | |
| 412 if (mdnType['srcUrl'] == null) return ''; | |
| 413 var comment = '<div class="mdn">' + mdnType['summary'].trim() + | |
| 414 '<p class="mdn-note"><a href="' + mdnType['srcUrl'].trim() + | |
| 415 '">from Mdn</a></p></div>'; | |
| 416 | |
| 417 return comment; | |
| 418 } | |
| 419 | |
| 420 /** | |
| 360 * Converts all [foo] references in comments to <a>libraryName.foo</a>. | 421 * Converts all [foo] references in comments to <a>libraryName.foo</a>. |
| 361 */ | 422 */ |
| 362 markdown.Node fixReference(String name, LibraryMirror currentLibrary, | 423 markdown.Node fixReference(String name, LibraryMirror currentLibrary, |
| 363 ClassMirror currentClass, MemberMirror currentMember) { | 424 ClassMirror currentClass, MemberMirror currentMember) { |
| 364 var reference; | 425 var reference; |
| 365 var memberScope = currentMember == null ? | 426 var memberScope = currentMember == null ? |
| 366 null : currentMember.lookupInScope(name); | 427 null : currentMember.lookupInScope(name); |
| 367 if (memberScope != null) { | 428 if (memberScope != null) { |
| 368 reference = memberScope.qualifiedName; | 429 reference = memberScope.qualifiedName; |
| 369 } else { | 430 } else { |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 614 /// Inherited methods in the class. | 675 /// Inherited methods in the class. |
| 615 MethodGroup inheritedMethods = new MethodGroup(); | 676 MethodGroup inheritedMethods = new MethodGroup(); |
| 616 | 677 |
| 617 /// Generic infomation about the class. | 678 /// Generic infomation about the class. |
| 618 Map<String, Generic> generics; | 679 Map<String, Generic> generics; |
| 619 | 680 |
| 620 Class superclass; | 681 Class superclass; |
| 621 bool isAbstract; | 682 bool isAbstract; |
| 622 | 683 |
| 623 /// List of the meta annotations on the class. | 684 /// List of the meta annotations on the class. |
| 624 List<String> annotations; | 685 List<Annotation> annotations; |
| 625 | 686 |
| 626 Class(String name, this.superclass, String comment, this.interfaces, | 687 Class(String name, this.superclass, String comment, this.interfaces, |
| 627 this.variables, this.methods, this.annotations, this.generics, | 688 this.variables, this.methods, this.annotations, this.generics, |
| 628 String qualifiedName, bool isPrivate, String owner, this.isAbstract) | 689 String qualifiedName, bool isPrivate, String owner, this.isAbstract) |
| 629 : super(name, comment, qualifiedName, isPrivate, owner); | 690 : super(name, comment, qualifiedName, isPrivate, owner) { |
| 691 _mdnComment(this); | |
| 692 } | |
| 630 | 693 |
| 631 String get typeName => 'class'; | 694 String get typeName => 'class'; |
| 632 | 695 |
| 633 /** | 696 /** |
| 634 * Returns a list of all the parent classes. | 697 * Returns a list of all the parent classes. |
| 635 */ | 698 */ |
| 636 List<Class> parent() { | 699 List<Class> parent() { |
| 637 var parent = superclass == null ? [] : [superclass]; | 700 var parent = superclass == null ? [] : [superclass]; |
| 638 parent.addAll(interfaces); | 701 parent.addAll(interfaces); |
| 639 return parent; | 702 return parent; |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 801 | 864 |
| 802 class Typedef extends Indexable { | 865 class Typedef extends Indexable { |
| 803 String returnType; | 866 String returnType; |
| 804 | 867 |
| 805 Map<String, Parameter> parameters; | 868 Map<String, Parameter> parameters; |
| 806 | 869 |
| 807 /// Generic information about the typedef. | 870 /// Generic information about the typedef. |
| 808 Map<String, Generic> generics; | 871 Map<String, Generic> generics; |
| 809 | 872 |
| 810 /// List of the meta annotations on the typedef. | 873 /// List of the meta annotations on the typedef. |
| 811 List<String> annotations; | 874 List<Annotation> annotations; |
| 812 | 875 |
| 813 Typedef(String name, this.returnType, String comment, this.generics, | 876 Typedef(String name, this.returnType, String comment, this.generics, |
| 814 this.parameters, this.annotations, | 877 this.parameters, this.annotations, |
| 815 String qualifiedName, bool isPrivate, String owner) | 878 String qualifiedName, bool isPrivate, String owner) |
| 816 : super(name, comment, qualifiedName, isPrivate, owner); | 879 : super(name, comment, qualifiedName, isPrivate, owner); |
| 817 | 880 |
| 818 Map toMap() => { | 881 Map toMap() => { |
| 819 'name': name, | 882 'name': name, |
| 820 'qualifiedName': qualifiedName, | 883 'qualifiedName': qualifiedName, |
| 821 'comment': comment, | 884 'comment': comment, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 832 * A class containing properties of a Dart variable. | 895 * A class containing properties of a Dart variable. |
| 833 */ | 896 */ |
| 834 class Variable extends Indexable { | 897 class Variable extends Indexable { |
| 835 | 898 |
| 836 bool isFinal; | 899 bool isFinal; |
| 837 bool isStatic; | 900 bool isStatic; |
| 838 bool isConst; | 901 bool isConst; |
| 839 Type type; | 902 Type type; |
| 840 | 903 |
| 841 /// List of the meta annotations on the variable. | 904 /// List of the meta annotations on the variable. |
| 842 List<String> annotations; | 905 List<Annotation> annotations; |
| 843 | 906 |
| 844 Variable(String name, this.isFinal, this.isStatic, this.isConst, this.type, | 907 Variable(String name, this.isFinal, this.isStatic, this.isConst, this.type, |
| 845 String comment, this.annotations, String qualifiedName, bool isPrivate, | 908 String comment, this.annotations, String qualifiedName, bool isPrivate, |
| 846 String owner) : super(name, comment, qualifiedName, isPrivate, owner); | 909 String owner) : super(name, comment, qualifiedName, isPrivate, owner) { |
| 910 _mdnComment(this); | |
| 911 } | |
| 847 | 912 |
| 848 /// Generates a map describing the [Variable] object. | 913 /// Generates a map describing the [Variable] object. |
| 849 Map toMap() => { | 914 Map toMap() => { |
| 850 'name': name, | 915 'name': name, |
| 851 'qualifiedName': qualifiedName, | 916 'qualifiedName': qualifiedName, |
| 852 'comment': comment, | 917 'comment': comment, |
| 853 'final': isFinal.toString(), | 918 'final': isFinal.toString(), |
| 854 'static': isStatic.toString(), | 919 'static': isStatic.toString(), |
| 855 'constant': isConst.toString(), | 920 'constant': isConst.toString(), |
| 856 'type': new List.filled(1, type.toMap()), | 921 'type': new List.filled(1, type.toMap()), |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 874 bool isConstructor; | 939 bool isConstructor; |
| 875 bool isGetter; | 940 bool isGetter; |
| 876 bool isSetter; | 941 bool isSetter; |
| 877 bool isOperator; | 942 bool isOperator; |
| 878 Type returnType; | 943 Type returnType; |
| 879 | 944 |
| 880 /// Qualified name to state where the comment is inherited from. | 945 /// Qualified name to state where the comment is inherited from. |
| 881 String commentInheritedFrom = ""; | 946 String commentInheritedFrom = ""; |
| 882 | 947 |
| 883 /// List of the meta annotations on the method. | 948 /// List of the meta annotations on the method. |
| 884 List<String> annotations; | 949 List<Annotation> annotations; |
| 885 | 950 |
| 886 Method(String name, this.isStatic, this.isAbstract, this.isConst, | 951 Method(String name, this.isStatic, this.isAbstract, this.isConst, |
| 887 this.returnType, String comment, this.parameters, this.annotations, | 952 this.returnType, String comment, this.parameters, this.annotations, |
| 888 String qualifiedName, bool isPrivate, String owner, this.isConstructor, | 953 String qualifiedName, bool isPrivate, String owner, this.isConstructor, |
| 889 this.isGetter, this.isSetter, this.isOperator) | 954 this.isGetter, this.isSetter, this.isOperator) |
| 890 : super(name, comment, qualifiedName, isPrivate, owner); | 955 : super(name, comment, qualifiedName, isPrivate, owner) { |
| 956 _mdnComment(this); | |
| 957 } | |
| 891 | 958 |
| 892 /** | 959 /** |
| 893 * Makes sure that the method with an inherited equivalent have comments. | 960 * Makes sure that the method with an inherited equivalent have comments. |
| 894 */ | 961 */ |
| 895 void ensureCommentFor(Method inheritedMethod) { | 962 void ensureCommentFor(Method inheritedMethod) { |
| 896 if (comment.isNotEmpty) return; | 963 if (comment.isNotEmpty && comment != "") return; |
|
Emily Fortuna
2013/08/15 17:05:42
does isNotEmpty really not cover the case where co
janicejl
2013/08/15 17:45:19
Done.
| |
| 897 entityMap[inheritedMethod.owner].ensureComments(); | 964 entityMap[inheritedMethod.owner].ensureComments(); |
| 898 comment = inheritedMethod.comment; | 965 comment = inheritedMethod.comment; |
| 899 commentInheritedFrom = inheritedMethod.commentInheritedFrom == '' ? | 966 commentInheritedFrom = inheritedMethod.commentInheritedFrom == '' ? |
| 900 inheritedMethod.qualifiedName : inheritedMethod.commentInheritedFrom; | 967 inheritedMethod.qualifiedName : inheritedMethod.commentInheritedFrom; |
| 901 } | 968 } |
| 902 | 969 |
| 903 /// Generates a map describing the [Method] object. | 970 /// Generates a map describing the [Method] object. |
| 904 Map toMap() => { | 971 Map toMap() => { |
| 905 'name': name, | 972 'name': name, |
| 906 'qualifiedName': qualifiedName, | 973 'qualifiedName': qualifiedName, |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 999 class Parameter { | 1066 class Parameter { |
| 1000 | 1067 |
| 1001 String name; | 1068 String name; |
| 1002 bool isOptional; | 1069 bool isOptional; |
| 1003 bool isNamed; | 1070 bool isNamed; |
| 1004 bool hasDefaultValue; | 1071 bool hasDefaultValue; |
| 1005 Type type; | 1072 Type type; |
| 1006 String defaultValue; | 1073 String defaultValue; |
| 1007 | 1074 |
| 1008 /// List of the meta annotations on the parameter. | 1075 /// List of the meta annotations on the parameter. |
| 1009 List<String> annotations; | 1076 List<Annotation> annotations; |
| 1010 | 1077 |
| 1011 Parameter(this.name, this.isOptional, this.isNamed, this.hasDefaultValue, | 1078 Parameter(this.name, this.isOptional, this.isNamed, this.hasDefaultValue, |
| 1012 this.type, this.defaultValue, this.annotations); | 1079 this.type, this.defaultValue, this.annotations); |
| 1013 | 1080 |
| 1014 /// Generates a map describing the [Parameter] object. | 1081 /// Generates a map describing the [Parameter] object. |
| 1015 Map toMap() => { | 1082 Map toMap() => { |
| 1016 'name': name, | 1083 'name': name, |
| 1017 'optional': isOptional.toString(), | 1084 'optional': isOptional.toString(), |
| 1018 'named': isNamed.toString(), | 1085 'named': isNamed.toString(), |
| 1019 'default': hasDefaultValue.toString(), | 1086 'default': hasDefaultValue.toString(), |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1087 String qualifiedName; | 1154 String qualifiedName; |
| 1088 List<String> parameters; | 1155 List<String> parameters; |
| 1089 | 1156 |
| 1090 Annotation(this.qualifiedName, this.parameters); | 1157 Annotation(this.qualifiedName, this.parameters); |
| 1091 | 1158 |
| 1092 Map toMap() => { | 1159 Map toMap() => { |
| 1093 'name': qualifiedName, | 1160 'name': qualifiedName, |
| 1094 'parameters': parameters | 1161 'parameters': parameters |
| 1095 }; | 1162 }; |
| 1096 } | 1163 } |
| OLD | NEW |