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 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
369 filteredEntities.map((e) => e.typeName)); | 369 filteredEntities.map((e) => e.typeName)); |
370 if (append) { | 370 if (append) { |
371 var previousIndex = | 371 var previousIndex = |
372 JSON.decode(new File('docs/index.json').readAsStringSync()); | 372 JSON.decode(new File('docs/index.json').readAsStringSync()); |
373 index.addAll(previousIndex); | 373 index.addAll(previousIndex); |
374 } | 374 } |
375 _writeToFile(JSON.encode(index), 'index.json'); | 375 _writeToFile(JSON.encode(index), 'index.json'); |
376 } | 376 } |
377 | 377 |
378 Library generateLibrary(dart2js.Dart2JsLibraryMirror library) { | 378 Library generateLibrary(dart2js.Dart2JsLibraryMirror library) { |
379 var result = new Library(docName(library), | 379 var result = new Library(library); |
Alan Knight
2013/11/20 21:29:20
Awesome!
| |
380 (actualLibrary) => _commentToHtml(library, actualLibrary), | |
381 _classes(library.classes), | |
382 _methods(library.functions), | |
383 _variables(library.variables), | |
384 _isHidden(library), library); | |
385 _findPackage(library, result); | 380 _findPackage(library, result); |
386 logger.fine('Generated library for ${result.name}'); | 381 logger.fine('Generated library for ${result.name}'); |
387 return result; | 382 return result; |
388 } | 383 } |
389 | 384 |
390 void _writeIndexableToFile(Indexable result, bool outputToYaml) { | 385 void _writeIndexableToFile(Indexable result, bool outputToYaml) { |
391 var outputFile = result.fileName; | 386 var outputFile = result.fileName; |
392 var output; | 387 var output; |
393 if (outputToYaml) { | 388 if (outputToYaml) { |
394 output = getYamlString(result.toMap()); | 389 output = getYamlString(result.toMap()); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
426 return (mirror.isPrivate || _isLibraryPrivate(mirror.owner)); | 421 return (mirror.isPrivate || _isLibraryPrivate(mirror.owner)); |
427 } else { | 422 } else { |
428 return (mirror.isPrivate || _isHidden(mirror.owner)); | 423 return (mirror.isPrivate || _isHidden(mirror.owner)); |
429 } | 424 } |
430 } | 425 } |
431 | 426 |
432 bool _isVisible(Indexable item) { | 427 bool _isVisible(Indexable item) { |
433 return _includePrivate || !item.isPrivate; | 428 return _includePrivate || !item.isPrivate; |
434 } | 429 } |
435 | 430 |
436 /// Returns a list of meta annotations assocated with a mirror. | |
437 List<Annotation> _annotations(DeclarationMirror mirror) { | |
438 var annotationMirrors = mirror.metadata.where((e) => | |
439 e is dart2js.Dart2JsConstructedConstantMirror); | |
440 var annotations = []; | |
441 annotationMirrors.forEach((annotation) { | |
442 var parameterList = annotation.type.variables.values | |
443 .where((e) => e.isFinal) | |
444 .map((e) => annotation.getField(e.simpleName).reflectee) | |
445 .where((e) => e != null) | |
446 .toList(); | |
447 if (!skippedAnnotations.contains(docName(annotation.type))) { | |
448 annotations.add(new Annotation(docName(annotation.type), | |
449 parameterList)); | |
450 } | |
451 }); | |
452 return annotations; | |
453 } | |
454 | |
455 /// Returns any documentation comments associated with a mirror with | 431 /// Returns any documentation comments associated with a mirror with |
456 /// simple markdown converted to html. | 432 /// simple markdown converted to html. |
457 /// | 433 /// |
458 /// It's possible to have a comment that comes from one mirror applied to | 434 /// It's possible to have a comment that comes from one mirror applied to |
459 /// another, in the case of an inherited comment. | 435 /// another, in the case of an inherited comment. |
460 String _commentToHtml(DeclarationMirror mirror, [DeclarationMirror appliedTo]) { | 436 String _commentToHtml(DeclarationMirror mirror, [DeclarationMirror appliedTo]) { |
461 if (appliedTo == null) appliedTo = mirror; | 437 if (appliedTo == null) appliedTo = mirror; |
462 String commentText; | 438 String commentText; |
463 mirror.metadata.forEach((metadata) { | 439 mirror.metadata.forEach((metadata) { |
464 if (metadata is CommentInstanceMirror) { | 440 if (metadata is CommentInstanceMirror) { |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
667 var owner = scope.owner; | 643 var owner = scope.owner; |
668 if (owner is ClassMirror) { | 644 if (owner is ClassMirror) { |
669 return fixReference(name, owner.library, owner, scope); | 645 return fixReference(name, owner.library, owner, scope); |
670 } else { | 646 } else { |
671 return fixReference(name, owner, null, scope); | 647 return fixReference(name, owner, null, scope); |
672 } | 648 } |
673 } | 649 } |
674 return null; | 650 return null; |
675 } | 651 } |
676 | 652 |
677 /// Returns a map of [Variable] objects constructed from [mirrorMap]. | |
678 Map<String, Variable> _variables(Map<String, VariableMirror> mirrorMap) { | |
679 var data = {}; | |
680 // TODO(janicejl): When map to map feature is created, replace the below with | |
681 // a filter. Issue(#9590). | |
682 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { | |
683 if (_includePrivate || !_isHidden(mirror)) { | |
684 entityMap[docName(mirror)] = new Variable(mirrorName, mirror.isFinal, | |
685 mirror.isStatic, mirror.isConst, _type(mirror.type), | |
686 (actualVariable) => _commentToHtml(mirror, actualVariable), | |
687 _annotations(mirror), docName(mirror), | |
688 _isHidden(mirror), docName(mirror.owner), mirror); | |
689 data[mirrorName] = entityMap[docName(mirror)]; | |
690 } | |
691 }); | |
692 return data; | |
693 } | |
694 | |
695 /// Returns a map of [Method] objects constructed from [mirrorMap]. | |
696 MethodGroup _methods(Map<String, MethodMirror> mirrorMap) { | |
697 var group = new MethodGroup(); | |
698 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { | |
699 if (_includePrivate || !mirror.isPrivate) { | |
700 group.addMethod(mirror); | |
701 } | |
702 }); | |
703 return group; | |
704 } | |
705 | |
706 /// Returns the [Class] for the given [mirror] has already been created, and if | |
707 /// it does not exist, creates it. | |
708 Class _class(ClassMirror mirror) { | |
709 var clazz = entityMap[docName(mirror)]; | |
710 if (clazz == null) { | |
711 var superclass = mirror.superclass != null ? | |
712 _class(mirror.superclass) : null; | |
713 var interfaces = | |
714 mirror.superinterfaces.map((interface) => _class(interface)); | |
715 clazz = new Class(mirror.simpleName, superclass, | |
716 (actualClass) => _commentToHtml(mirror, actualClass), | |
717 interfaces.toList(), _variables(mirror.variables), | |
718 _methods(mirror.methods), _annotations(mirror), _generics(mirror), | |
719 docName(mirror), _isHidden(mirror), docName(mirror.owner), | |
720 mirror.isAbstract, mirror); | |
721 if (superclass != null) clazz.addInherited(superclass); | |
722 interfaces.forEach((interface) => clazz.addInherited(interface)); | |
723 entityMap[docName(mirror)] = clazz; | |
724 } | |
725 return clazz; | |
726 } | |
727 | |
728 /// Returns a map of [Class] objects constructed from [mirrorMap]. | |
729 ClassGroup _classes(Map<String, ClassMirror> mirrorMap) { | |
730 var group = new ClassGroup(); | |
731 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { | |
732 group.addClass(mirror); | |
733 }); | |
734 return group; | |
735 } | |
736 | |
737 /// Returns a map of [Parameter] objects constructed from [mirrorList]. | |
738 Map<String, Parameter> _parameters(List<ParameterMirror> mirrorList) { | |
739 var data = {}; | |
740 mirrorList.forEach((ParameterMirror mirror) { | |
741 data[mirror.simpleName] = new Parameter(mirror.simpleName, | |
742 mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, | |
743 _type(mirror.type), mirror.defaultValue, | |
744 _annotations(mirror)); | |
745 }); | |
746 return data; | |
747 } | |
748 | |
749 /// Returns a map of [Generic] objects constructed from the class mirror. | |
750 Map<String, Generic> _generics(ClassMirror mirror) { | |
751 return new Map.fromIterable(mirror.typeVariables, | |
752 key: (e) => e.toString(), | |
753 value: (e) => new Generic(e.toString(), e.upperBound.qualifiedName)); | |
754 } | |
755 | |
756 /// Returns a single [Type] object constructed from the Method.returnType | |
757 /// Type mirror. | |
758 Type _type(TypeMirror mirror) { | |
759 return new Type(docName(mirror), _typeGenerics(mirror)); | |
760 } | |
761 | |
762 /// Returns a list of [Type] objects constructed from TypeMirrors. | |
763 List<Type> _typeGenerics(TypeMirror mirror) { | |
764 if (mirror is ClassMirror && !mirror.isTypedef) { | |
765 var innerList = []; | |
766 mirror.typeArguments.forEach((e) { | |
767 innerList.add(new Type(docName(e), _typeGenerics(e))); | |
768 }); | |
769 return innerList; | |
770 } | |
771 return []; | |
772 } | |
773 | |
774 /// Writes text to a file in the 'docs' directory. | 653 /// Writes text to a file in the 'docs' directory. |
775 void _writeToFile(String text, String filename, {bool append: false}) { | 654 void _writeToFile(String text, String filename, {bool append: false}) { |
776 Directory dir = new Directory('docs'); | 655 Directory dir = new Directory('docs'); |
777 if (!dir.existsSync()) { | 656 if (!dir.existsSync()) { |
778 dir.createSync(); | 657 dir.createSync(); |
779 } | 658 } |
780 // We assume there's a single extra level of directory structure for packages. | 659 // We assume there's a single extra level of directory structure for packages. |
781 if (path.split(filename).length > 1) { | 660 if (path.split(filename).length > 1) { |
782 var subdir = new Directory(path.join('docs', path.dirname(filename))); | 661 var subdir = new Directory(path.join('docs', path.dirname(filename))); |
783 if (!subdir.existsSync()) { | 662 if (!subdir.existsSync()) { |
(...skipping 19 matching lines...) Expand all Loading... | |
803 } | 682 } |
804 }); | 683 }); |
805 return outputMap; | 684 return outputMap; |
806 } | 685 } |
807 | 686 |
808 /// A type for the function that generates a comment from a mirror. | 687 /// A type for the function that generates a comment from a mirror. |
809 typedef String CommentGenerator(Mirror m); | 688 typedef String CommentGenerator(Mirror m); |
810 | 689 |
811 /// A class representing all programming constructs, like library or class. | 690 /// A class representing all programming constructs, like library or class. |
812 class Indexable { | 691 class Indexable { |
813 String name; | |
814 String get qualifiedName => fileName; | 692 String get qualifiedName => fileName; |
815 bool isPrivate; | 693 bool isPrivate; |
816 Mirror mirror; | 694 DeclarationMirror mirror; |
695 | |
696 Indexable(this.mirror) { | |
697 this.isPrivate = _isHidden(mirror); | |
698 } | |
817 | 699 |
818 // The qualified name (for URL purposes) and the file name are the same, | 700 // The qualified name (for URL purposes) and the file name are the same, |
819 // of the form packageName/ClassName or packageName/ClassName.methodName. | 701 // of the form packageName/ClassName or packageName/ClassName.methodName. |
820 // This defines both the URL and the directory structure. | 702 // This defines both the URL and the directory structure. |
821 String get fileName => packagePrefix + ownerPrefix + name; | 703 String get fileName => packagePrefix + ownerPrefix + name; |
822 | 704 |
823 Indexable get owningEntity => entityMap[owner]; | 705 Indexable get owningEntity => entityMap[owner]; |
824 | 706 |
825 String get ownerPrefix => owningEntity == null | 707 String get ownerPrefix => owningEntity == null ? |
826 ? (owner == null || owner.isEmpty ? '' : owner + '.') | 708 (owner == null || owner.isEmpty ? '' : owner + '.') : |
827 : owningEntity.qualifiedName + '.'; | 709 owningEntity.qualifiedName + '.'; |
828 | 710 |
829 String get packagePrefix => ''; | 711 String get packagePrefix => ''; |
830 | 712 |
831 /// Documentation comment with converted markdown. | 713 /// Documentation comment with converted markdown. |
832 String _comment; | 714 String _comment; |
833 | 715 |
834 String get comment { | 716 String get comment { |
835 if (_comment != null) return _comment; | 717 if (_comment != null) return _comment; |
836 _comment = _commentFunction(mirror); | 718 _comment = _commentFunction(mirror); |
837 if (_comment.isEmpty) { | 719 if (_comment.isEmpty) { |
838 _mdnComment(this); | 720 _mdnComment(this); |
839 } | 721 } |
840 return _comment; | 722 return _comment; |
841 } | 723 } |
842 | 724 |
843 set comment(x) => _comment = x; | 725 set comment(x) => _comment = x; |
844 | 726 |
845 /// We defer evaluating the comment until we have all the context available | 727 String get name => mirror.simpleName; |
846 CommentGenerator _commentFunction; | |
847 | 728 |
848 /// Qualified Name of the owner of this Indexable Item. | 729 /// Qualified Name of the owner of this Indexable Item. |
849 /// For Library, owner will be ""; | 730 String get owner => docName(mirror.owner); |
850 String owner; | |
851 | 731 |
852 Indexable(this.name, this._commentFunction, this.isPrivate, this.owner, | 732 /// We defer evaluating the comment until we have all the context available |
853 this.mirror); | 733 CommentGenerator get _commentFunction => |
Alan Knight
2013/11/20 21:29:20
If this is always there, could we just call make i
Emily Fortuna
2013/11/21 19:29:59
Good point. I ended up doing this refactor in incr
| |
734 (itemToDocument) => _commentToHtml(mirror, itemToDocument); | |
854 | 735 |
855 /// The type of this member to be used in index.txt. | 736 /// The type of this member to be used in index.txt. |
856 String get typeName => ''; | 737 String get typeName => ''; |
857 | 738 |
858 /// Creates a [Map] with this [Indexable]'s name and a preview comment. | 739 /// Creates a [Map] with this [Indexable]'s name and a preview comment. |
859 Map get previewMap { | 740 Map get previewMap { |
860 var finalMap = { 'name' : name, 'qualifiedName' : qualifiedName }; | 741 var finalMap = { 'name' : name, 'qualifiedName' : qualifiedName }; |
861 if (comment != '') { | 742 if (comment != '') { |
862 var index = comment.indexOf('</p>'); | 743 var index = comment.indexOf('</p>'); |
863 finalMap['preview'] = '${comment.substring(0, index)}</p>'; | 744 finalMap['preview'] = '${comment.substring(0, index)}</p>'; |
864 } | 745 } |
865 return finalMap; | 746 return finalMap; |
866 } | 747 } |
867 | 748 |
749 /// Returns a map of [Variable] objects constructed from [mirrorMap]. | |
750 Map<String, Variable> _processVariables(Map<String, | |
751 VariableMirror> mirrorMap) { | |
752 var data = {}; | |
753 // TODO(janicejl): When map to map feature is created, replace the below | |
754 // with a filter. Issue(#9590). | |
755 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { | |
756 if (_includePrivate || !_isHidden(mirror)) { | |
757 entityMap[docName(mirror)] = new Variable(mirrorName, mirror); | |
758 data[mirrorName] = entityMap[docName(mirror)]; | |
759 } | |
760 }); | |
761 return data; | |
762 } | |
763 | |
764 /// Returns a map of [Method] objects constructed from [mirrorMap]. | |
765 MethodGroup _processMethods(Map<String, MethodMirror> mirrorMap) { | |
Alan Knight
2013/11/20 21:29:20
A bit of inconsistency with naming that we're proc
Emily Fortuna
2013/11/21 19:29:59
renamed to create
| |
766 var group = new MethodGroup(); | |
767 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { | |
768 if (_includePrivate || !mirror.isPrivate) { | |
769 group.addMethod(mirror); | |
770 } | |
771 }); | |
772 return group; | |
773 } | |
774 | |
775 /// Returns a map of [Parameter] objects constructed from [mirrorList]. | |
776 Map<String, Parameter> _processParameters(List<ParameterMirror> mirrorList) { | |
777 var data = {}; | |
778 mirrorList.forEach((ParameterMirror mirror) { | |
779 data[mirror.simpleName] = new Parameter(mirror.simpleName, | |
780 mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, | |
781 _processType(mirror.type), mirror.defaultValue, | |
782 _processAnnotations(mirror)); | |
783 }); | |
784 return data; | |
785 } | |
786 | |
787 /// Returns a map of [Generic] objects constructed from the class mirror. | |
788 Map<String, Generic> _processGenerics(ClassMirror mirror) { | |
789 return new Map.fromIterable(mirror.typeVariables, | |
790 key: (e) => e.toString(), | |
791 value: (e) => new Generic(e.toString(), e.upperBound.qualifiedName)); | |
792 } | |
793 | |
794 /// Returns a single [Type] object constructed from the Method.returnType | |
795 /// Type mirror. | |
796 Type _processType(TypeMirror mirror) { | |
797 return new Type(docName(mirror), _processTypeGenerics(mirror)); | |
798 } | |
799 | |
800 /// Returns a list of [Type] objects constructed from TypeMirrors. | |
801 List<Type> _processTypeGenerics(TypeMirror mirror) { | |
802 if (mirror is ClassMirror && !mirror.isTypedef) { | |
803 var innerList = []; | |
804 mirror.typeArguments.forEach((e) { | |
805 innerList.add(new Type(docName(e), _processTypeGenerics(e))); | |
806 }); | |
807 return innerList; | |
808 } | |
809 return []; | |
810 } | |
811 | |
812 /// Returns a list of meta annotations assocated with a mirror. | |
813 List<Annotation> _processAnnotations(DeclarationMirror mirror) { | |
814 var annotationMirrors = mirror.metadata.where((e) => | |
815 e is dart2js.Dart2JsConstructedConstantMirror); | |
816 var annotations = []; | |
817 annotationMirrors.forEach((annotation) { | |
818 var parameterList = annotation.type.variables.values | |
819 .where((e) => e.isFinal) | |
820 .map((e) => annotation.getField(e.simpleName).reflectee) | |
821 .where((e) => e != null) | |
822 .toList(); | |
823 if (!skippedAnnotations.contains(docName(annotation.type))) { | |
824 annotations.add(new Annotation(docName(annotation.type), | |
825 parameterList)); | |
826 } | |
827 }); | |
828 return annotations; | |
829 } | |
830 | |
868 /// Return an informative [Object.toString] for debugging. | 831 /// Return an informative [Object.toString] for debugging. |
869 String toString() => "${super.toString()}(${name.toString()})"; | 832 String toString() => "${super.toString()}(${name.toString()})"; |
870 | 833 |
871 /// Return a map representation of this type. | 834 /// Return a map representation of this type. |
872 Map toMap() {} | 835 Map toMap() {} |
873 } | 836 } |
874 | 837 |
875 /// A class containing contents of a Dart library. | 838 /// A class containing contents of a Dart library. |
876 class Library extends Indexable { | 839 class Library extends Indexable { |
877 | 840 |
878 /// Top-level variables in the library. | 841 /// Top-level variables in the library. |
879 Map<String, Variable> variables; | 842 Map<String, Variable> variables; |
880 | 843 |
881 /// Top-level functions in the library. | 844 /// Top-level functions in the library. |
882 MethodGroup functions; | 845 MethodGroup functions; |
883 | 846 |
884 /// Classes defined within the library | 847 /// Classes defined within the library |
885 ClassGroup classes; | 848 ClassGroup classes; |
886 | 849 |
887 String packageName = ''; | 850 String packageName = ''; |
888 bool hasBeenCheckedForPackage = false; | 851 bool hasBeenCheckedForPackage = false; |
852 String packageIntro; | |
889 | 853 |
890 String get packagePrefix => packageName == null || packageName.isEmpty | 854 Library(LibraryMirror libraryMirror) : super(libraryMirror) { |
891 ? '' | 855 var exported = _calcExportedItems(libraryMirror); |
892 : '$packageName/'; | 856 this.classes = _processClasses( |
857 exported['classes']..addAll(libraryMirror.classes)); | |
858 this.functions = _processMethods( | |
859 exported['methods']..addAll(libraryMirror.functions)); | |
860 this.variables = _processVariables( | |
861 exported['variables']..addAll(libraryMirror.variables)); | |
862 print(classes.toMap().toString()); | |
Alan Knight
2013/11/20 21:29:20
Leftover debugging?
Emily Fortuna
2013/11/21 19:29:59
yep. removed.
| |
863 } | |
893 | 864 |
894 String packageIntro; | 865 String get packagePrefix => packageName == null || packageName.isEmpty ? |
866 '' : '$packageName/'; | |
895 | 867 |
896 Map get previewMap { | 868 Map get previewMap { |
897 var basic = super.previewMap; | 869 var basic = super.previewMap; |
898 basic['packageName'] = packageName; | 870 basic['packageName'] = packageName; |
899 if (packageIntro != null) { | 871 if (packageIntro != null) { |
900 basic['packageIntro'] = packageIntro; | 872 basic['packageIntro'] = packageIntro; |
901 } | 873 } |
902 return basic; | 874 return basic; |
903 } | 875 } |
904 | 876 |
905 Library(String name, Function commentFunction, this.classes, this.functions, | 877 String get owner => ''; |
906 this.variables, bool isPrivate, Mirror mirror) | 878 |
907 : super(name, commentFunction, isPrivate, "", mirror); | 879 String get name => docName(mirror); |
880 | |
881 /// Returns a map of [Class] objects constructed from [mirrorMap]. | |
Alan Knight
2013/11/20 21:29:20
"Returns a [ClassGroup] with a map of" ?
Emily Fortuna
2013/11/21 19:29:59
Done.
| |
882 ClassGroup _processClasses(Map<String, ClassMirror> mirrorMap) { | |
883 var group = new ClassGroup(); | |
884 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { | |
885 group.addClass(mirror); | |
886 }); | |
887 return group; | |
888 } | |
889 | |
890 /// For the given library determine what items (if any) are exported. | |
891 /// | |
892 /// Returns a Map with three keys: "classes", "methods", and "variables" the | |
893 /// values of which point to a map of exported name identifiers with values | |
894 /// corresponding to the actual DeclarationMirror. | |
895 Map<String, Map<String, DeclarationMirror>> _calcExportedItems( | |
896 LibraryMirror library) { | |
897 var exports = {}; | |
898 exports['classes'] = {}; | |
899 exports['methods'] = {}; | |
900 exports['variables'] = {}; | |
901 | |
902 // Determine the classes, variables and methods that are exported for a | |
903 // specific dependency. | |
904 _populateExports(LibraryDependencyMirror export, bool showExport) { | |
905 if (!showExport) { | |
906 // Add all items, and then remove the hidden ones. | |
907 // Ex: "export foo hide bar" | |
908 exports['classes'].addAll(export.targetLibrary.classes); | |
909 exports['methods'].addAll(export.targetLibrary.functions); | |
910 exports['variables'].addAll(export.targetLibrary.variables); | |
911 } | |
912 for (CombinatorMirror combinator in export.combinators) { | |
913 for (String identifier in combinator.identifiers) { | |
914 DeclarationMirror declaration = | |
915 export.targetLibrary.lookupInScope(identifier); | |
916 if (declaration == null) { | |
917 // Technically this should be a bug, but some of our packages | |
918 // (such as the polymer package) are curently broken in this | |
919 // way, so we just produce a warning. | |
920 print('Warning identifier $identifier not found in library ' | |
921 '${export.targetLibrary.qualifiedName}'); | |
922 } else { | |
923 var subMap = exports['classes']; | |
924 if (declaration is MethodMirror) { | |
925 subMap = exports['methods']; | |
926 } else if (declaration is VariableMirror) { | |
927 subMap = exports['variables']; | |
928 } | |
929 if (showExport) { | |
930 subMap[identifier] = declaration; | |
931 } else { | |
932 subMap.remove(identifier); | |
933 } | |
934 } | |
935 } | |
936 } | |
937 } | |
938 | |
939 Iterable<LibraryDependencyMirror> exportList = | |
940 library.libraryDependencies.where((lib) => lib.isExport); | |
941 for (LibraryDependencyMirror export in exportList) { | |
942 // If there is a show in the export, add only the show items to the | |
943 // library. Ex: "export foo show bar" | |
944 // Otherwise, add all items, and then remove the hidden ones. | |
945 // Ex: "export foo hide bar" | |
946 _populateExports(export, | |
947 export.combinators.any((combinator) => combinator.isShow)); | |
948 } | |
949 return exports; | |
950 } | |
908 | 951 |
909 /// Generates a map describing the [Library] object. | 952 /// Generates a map describing the [Library] object. |
910 Map toMap() => { | 953 Map toMap() => { |
911 'name': name, | 954 'name': name, |
912 'qualifiedName': qualifiedName, | 955 'qualifiedName': qualifiedName, |
913 'comment': comment, | 956 'comment': comment, |
914 'variables': recurseMap(variables), | 957 'variables': recurseMap(variables), |
915 'functions': functions.toMap(), | 958 'functions': functions.toMap(), |
916 'classes': classes.toMap(), | 959 'classes': classes.toMap(), |
917 'packageName': packageName, | 960 'packageName': packageName, |
(...skipping 29 matching lines...) Expand all Loading... | |
947 | 990 |
948 Class superclass; | 991 Class superclass; |
949 bool isAbstract; | 992 bool isAbstract; |
950 | 993 |
951 /// List of the meta annotations on the class. | 994 /// List of the meta annotations on the class. |
952 List<Annotation> annotations; | 995 List<Annotation> annotations; |
953 | 996 |
954 /// Make sure that we don't check for inherited comments more than once. | 997 /// Make sure that we don't check for inherited comments more than once. |
955 bool _commentsEnsured = false; | 998 bool _commentsEnsured = false; |
956 | 999 |
957 Class(String name, this.superclass, Function commentFunction, this.interfaces, | 1000 Class(ClassMirror classMirror) : super(classMirror) { |
958 this.variables, this.methods, this.annotations, this.generics, | 1001 var superclass = classMirror.superclass != null ? |
959 String qualifiedName, bool isPrivate, String owner, this.isAbstract, | 1002 _getClassFromClassMirror(classMirror.superclass) : null; |
960 Mirror mirror) | 1003 var interfaces = classMirror.superinterfaces.map( |
961 : super(name, commentFunction, isPrivate, owner, mirror); | 1004 (interface) => _getClassFromClassMirror(interface)); |
1005 | |
1006 this.superclass = superclass; | |
1007 this.interfaces = interfaces.toList(); | |
1008 this.variables = _processVariables(classMirror.variables); | |
1009 this.methods = _processMethods(classMirror.methods); | |
1010 this.annotations = _processAnnotations(classMirror); | |
1011 this.generics = _processGenerics(classMirror); | |
1012 this.isAbstract = classMirror.isAbstract; | |
1013 | |
1014 // Tell all superclasses that you are a subclass. | |
1015 if (!classMirror.isNameSynthetic && _isVisible(this)) { | |
1016 parentChain().forEach((parentClass) { | |
1017 parentClass.addSubclass(this); | |
1018 }); | |
1019 } | |
1020 | |
1021 if (this.superclass != null) addInherited(superclass); | |
1022 interfaces.forEach((interface) => addInherited(interface)); | |
1023 } | |
962 | 1024 |
963 String get typeName => 'class'; | 1025 String get typeName => 'class'; |
964 | 1026 |
965 /// Returns a list of all the parent classes. | 1027 /// Returns a list of all the parent classes. |
966 List<Class> parent() { | 1028 List<Class> parentChain() { |
967 var parent = superclass == null ? [] : [superclass]; | 1029 var parent = superclass == null ? [] : [superclass]; |
968 parent.addAll(interfaces); | 1030 parent.addAll(interfaces); |
969 return parent; | 1031 return parent; |
970 } | 1032 } |
971 | 1033 |
972 /// Add all inherited variables and methods from the provided superclass. | 1034 /// Add all inherited variables and methods from the provided superclass. |
973 /// If [_includePrivate] is true, it also adds the variables and methods from | 1035 /// If [_includePrivate] is true, it also adds the variables and methods from |
974 /// the superclass. | 1036 /// the superclass. |
975 void addInherited(Class superclass) { | 1037 void addInherited(Class superclass) { |
976 inheritedVariables.addAll(superclass.inheritedVariables); | 1038 inheritedVariables.addAll(superclass.inheritedVariables); |
977 inheritedVariables.addAll(_filterStatics(superclass.variables)); | 1039 inheritedVariables.addAll(_filterStatics(superclass.variables)); |
978 inheritedMethods.addInherited(superclass); | 1040 inheritedMethods.addInherited(superclass); |
979 } | 1041 } |
980 | 1042 |
981 /// Add the subclass to the class. | 1043 /// Add the subclass to the class. |
982 /// | 1044 /// |
983 /// If [this] is private, it will add the subclass to the list of subclasses i n | 1045 /// If [this] is private, it will add the subclass to the list of subclasses |
984 /// the superclasses. | 1046 /// in the superclasses. |
985 void addSubclass(Class subclass) { | 1047 void addSubclass(Class subclass) { |
986 if (!_includePrivate && isPrivate) { | 1048 if (!_includePrivate && isPrivate) { |
987 if (superclass != null) superclass.addSubclass(subclass); | 1049 if (superclass != null) superclass.addSubclass(subclass); |
988 interfaces.forEach((interface) { | 1050 interfaces.forEach((interface) { |
989 interface.addSubclass(subclass); | 1051 interface.addSubclass(subclass); |
990 }); | 1052 }); |
991 } else { | 1053 } else { |
992 subclasses.add(subclass); | 1054 subclasses.add(subclass); |
993 } | 1055 } |
994 } | 1056 } |
995 | 1057 |
1058 /// Returns the [Class] for the given [mirror] has already been created, and | |
Alan Knight
2013/11/20 21:29:20
Missing an "if it"?
Emily Fortuna
2013/11/21 19:29:59
Done.
| |
1059 /// if it does not exist, creates it. | |
1060 static Class _getClassFromClassMirror(ClassMirror mirror) { | |
Alan Knight
2013/11/20 21:29:20
Naming nit. The "get" doesn't add much, and if it'
Emily Fortuna
2013/11/21 19:29:59
Good call. Fixed.
| |
1061 var clazz = entityMap[docName(mirror)]; | |
1062 if (clazz == null) { | |
1063 clazz = new Class(mirror); | |
1064 entityMap[docName(mirror)] = clazz; | |
1065 } | |
1066 return clazz; | |
1067 } | |
1068 | |
996 /// Check if this [Class] is an error or exception. | 1069 /// Check if this [Class] is an error or exception. |
997 bool isError() { | 1070 bool isError() { |
998 if (qualifiedName == 'dart-core.Error' || | 1071 if (qualifiedName == 'dart-core.Error' || |
999 qualifiedName == 'dart-core.Exception') | 1072 qualifiedName == 'dart-core.Exception') |
1000 return true; | 1073 return true; |
1001 for (var interface in interfaces) { | 1074 for (var interface in interfaces) { |
1002 if (interface.isError()) return true; | 1075 if (interface.isError()) return true; |
1003 } | 1076 } |
1004 if (superclass == null) return false; | 1077 if (superclass == null) return false; |
1005 return superclass.isError(); | 1078 return superclass.isError(); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1068 Map<String, Class> classes = {}; | 1141 Map<String, Class> classes = {}; |
1069 Map<String, Typedef> typedefs = {}; | 1142 Map<String, Typedef> typedefs = {}; |
1070 Map<String, Class> errors = {}; | 1143 Map<String, Class> errors = {}; |
1071 | 1144 |
1072 void addClass(ClassMirror classMirror) { | 1145 void addClass(ClassMirror classMirror) { |
1073 if (classMirror.isTypedef) { | 1146 if (classMirror.isTypedef) { |
1074 // This is actually a Dart2jsTypedefMirror, and it does define value, | 1147 // This is actually a Dart2jsTypedefMirror, and it does define value, |
1075 // but we don't have visibility to that type. | 1148 // but we don't have visibility to that type. |
1076 var mirror = classMirror; | 1149 var mirror = classMirror; |
1077 if (_includePrivate || !mirror.isPrivate) { | 1150 if (_includePrivate || !mirror.isPrivate) { |
1078 entityMap[docName(mirror)] = new Typedef(mirror.simpleName, | 1151 entityMap[docName(mirror)] = new Typedef(mirror); |
1079 docName(mirror.value.returnType), | |
1080 (actualTypedef) => _commentToHtml(mirror, actualTypedef), | |
1081 _generics(mirror), _parameters(mirror.value.parameters), | |
1082 _annotations(mirror), docName(mirror), _isHidden(mirror), | |
1083 docName(mirror.owner), mirror); | |
1084 typedefs[mirror.simpleName] = entityMap[docName(mirror)]; | 1152 typedefs[mirror.simpleName] = entityMap[docName(mirror)]; |
1085 } | 1153 } |
1086 } else { | 1154 } else { |
1087 var clazz = _class(classMirror); | 1155 var clazz = Class._getClassFromClassMirror(classMirror); |
1088 | |
1089 // Adding inherited parent variables and methods. | |
1090 clazz.parent().forEach((parent) { | |
1091 if (_isVisible(clazz)) { | |
1092 parent.addSubclass(clazz); | |
1093 } | |
1094 }); | |
1095 | 1156 |
1096 if (clazz.isError()) { | 1157 if (clazz.isError()) { |
1097 errors[classMirror.simpleName] = clazz; | 1158 errors[classMirror.simpleName] = clazz; |
1098 } else if (classMirror.isClass) { | 1159 } else if (classMirror.isClass) { |
1099 classes[classMirror.simpleName] = clazz; | 1160 classes[classMirror.simpleName] = clazz; |
1100 } else { | 1161 } else { |
1101 throw new ArgumentError( | 1162 throw new ArgumentError( |
1102 '${classMirror.simpleName} - no class type match. '); | 1163 '${classMirror.simpleName} - no class type match. '); |
1103 } | 1164 } |
1104 } | 1165 } |
(...skipping 17 matching lines...) Expand all Loading... | |
1122 String returnType; | 1183 String returnType; |
1123 | 1184 |
1124 Map<String, Parameter> parameters; | 1185 Map<String, Parameter> parameters; |
1125 | 1186 |
1126 /// Generic information about the typedef. | 1187 /// Generic information about the typedef. |
1127 Map<String, Generic> generics; | 1188 Map<String, Generic> generics; |
1128 | 1189 |
1129 /// List of the meta annotations on the typedef. | 1190 /// List of the meta annotations on the typedef. |
1130 List<Annotation> annotations; | 1191 List<Annotation> annotations; |
1131 | 1192 |
1132 Typedef(String name, this.returnType, Function commentFunction, this.generics, | 1193 Typedef(mirror) : super(mirror) { |
1133 this.parameters, this.annotations, | 1194 this.returnType = docName(mirror.value.returnType); |
1134 String qualifiedName, bool isPrivate, String owner, Mirror mirror) | 1195 this.generics = _processGenerics(mirror); |
1135 : super(name, commentFunction, isPrivate, owner, mirror); | 1196 this.parameters = _processParameters(mirror.value.parameters); |
1197 this.annotations = _processAnnotations(mirror); | |
1198 } | |
1136 | 1199 |
1137 Map toMap() => { | 1200 Map toMap() => { |
1138 'name': name, | 1201 'name': name, |
1139 'qualifiedName': qualifiedName, | 1202 'qualifiedName': qualifiedName, |
1140 'comment': comment, | 1203 'comment': comment, |
1141 'return': returnType, | 1204 'return': returnType, |
1142 'parameters': recurseMap(parameters), | 1205 'parameters': recurseMap(parameters), |
1143 'annotations': annotations.map((a) => a.toMap()).toList(), | 1206 'annotations': annotations.map((a) => a.toMap()).toList(), |
1144 'generics': recurseMap(generics) | 1207 'generics': recurseMap(generics) |
1145 }; | 1208 }; |
1146 | 1209 |
1147 String get typeName => 'typedef'; | 1210 String get typeName => 'typedef'; |
1148 } | 1211 } |
1149 | 1212 |
1150 /// A class containing properties of a Dart variable. | 1213 /// A class containing properties of a Dart variable. |
1151 class Variable extends Indexable { | 1214 class Variable extends Indexable { |
1152 | 1215 |
1153 bool isFinal; | 1216 bool isFinal; |
1154 bool isStatic; | 1217 bool isStatic; |
1155 bool isConst; | 1218 bool isConst; |
1156 Type type; | 1219 Type type; |
1220 String _variableName; | |
1157 | 1221 |
1158 /// List of the meta annotations on the variable. | 1222 /// List of the meta annotations on the variable. |
1159 List<Annotation> annotations; | 1223 List<Annotation> annotations; |
1160 | 1224 |
1161 Variable(String name, this.isFinal, this.isStatic, this.isConst, this.type, | 1225 Variable(this._variableName, VariableMirror mirror) : super(mirror) { |
1162 Function commentFunction, this.annotations, String qualifiedName, | 1226 this.isFinal = mirror.isFinal; |
1163 bool isPrivate, String owner, Mirror mirror) | 1227 this.isStatic = mirror.isStatic; |
1164 : super(name, commentFunction, isPrivate, owner, mirror) { | 1228 this.isConst = mirror.isConst; |
1229 this.type = _processType(mirror.type); | |
1230 this.annotations = _processAnnotations(mirror); | |
1165 } | 1231 } |
1166 | 1232 |
1233 String get name => this._variableName; | |
Alan Knight
2013/11/20 21:29:20
Why the explicit "this."?
Emily Fortuna
2013/11/21 19:29:59
oops. Refactoring cruft from when it was part of t
| |
1234 | |
1167 /// Generates a map describing the [Variable] object. | 1235 /// Generates a map describing the [Variable] object. |
1168 Map toMap() => { | 1236 Map toMap() => { |
1169 'name': name, | 1237 'name': name, |
1170 'qualifiedName': qualifiedName, | 1238 'qualifiedName': qualifiedName, |
1171 'comment': comment, | 1239 'comment': comment, |
1172 'final': isFinal.toString(), | 1240 'final': isFinal.toString(), |
1173 'static': isStatic.toString(), | 1241 'static': isStatic.toString(), |
1174 'constant': isConst.toString(), | 1242 'constant': isConst.toString(), |
1175 'type': new List.filled(1, type.toMap()), | 1243 'type': new List.filled(1, type.toMap()), |
1176 'annotations': annotations.map((a) => a.toMap()).toList() | 1244 'annotations': annotations.map((a) => a.toMap()).toList() |
(...skipping 25 matching lines...) Expand all Loading... | |
1202 bool isSetter; | 1270 bool isSetter; |
1203 bool isOperator; | 1271 bool isOperator; |
1204 Type returnType; | 1272 Type returnType; |
1205 | 1273 |
1206 /// Qualified name to state where the comment is inherited from. | 1274 /// Qualified name to state where the comment is inherited from. |
1207 String commentInheritedFrom = ""; | 1275 String commentInheritedFrom = ""; |
1208 | 1276 |
1209 /// List of the meta annotations on the method. | 1277 /// List of the meta annotations on the method. |
1210 List<Annotation> annotations; | 1278 List<Annotation> annotations; |
1211 | 1279 |
1212 Method(String name, this.isStatic, this.isAbstract, this.isConst, | 1280 Method(MethodMirror mirror) : super(mirror) { |
1213 this.returnType, Function commentFunction, this.parameters, | 1281 this.isStatic = mirror.isStatic; |
1214 this.annotations, | 1282 this.isAbstract = mirror.isAbstract; |
1215 String qualifiedName, bool isPrivate, String owner, this.isConstructor, | 1283 this.isConst = mirror.isConstConstructor; |
1216 this.isGetter, this.isSetter, this.isOperator, Mirror mirror) | 1284 this.returnType = _processType(mirror.returnType); |
1217 : super(name, commentFunction, isPrivate, owner, mirror) { | 1285 this.parameters = _processParameters(mirror.parameters); |
1286 this.annotations = _processAnnotations(mirror); | |
1287 this.isConstructor = mirror.isConstructor; | |
1288 this.isGetter = mirror.isGetter; | |
1289 this.isSetter = mirror.isSetter; | |
1290 this.isOperator = mirror.isOperator; | |
1218 } | 1291 } |
1219 | 1292 |
1220 /// Makes sure that the method with an inherited equivalent have comments. | 1293 /// Makes sure that the method with an inherited equivalent have comments. |
1221 void ensureCommentFor(Method inheritedMethod) { | 1294 void ensureCommentFor(Method inheritedMethod) { |
1222 if (comment.isNotEmpty) return; | 1295 if (comment.isNotEmpty) return; |
1223 comment = inheritedMethod._commentFunction(mirror); | 1296 comment = inheritedMethod._commentFunction(mirror); |
1224 commentInheritedFrom = inheritedMethod.commentInheritedFrom == '' ? | 1297 commentInheritedFrom = inheritedMethod.commentInheritedFrom == '' ? |
1225 inheritedMethod.qualifiedName : inheritedMethod.commentInheritedFrom; | 1298 inheritedMethod.qualifiedName : inheritedMethod.commentInheritedFrom; |
1226 } | 1299 } |
1227 | 1300 |
(...skipping 28 matching lines...) Expand all Loading... | |
1256 /// A container to categorize methods into the following groups: setters, | 1329 /// A container to categorize methods into the following groups: setters, |
1257 /// getters, constructors, operators, regular methods. | 1330 /// getters, constructors, operators, regular methods. |
1258 class MethodGroup { | 1331 class MethodGroup { |
1259 Map<String, Method> setters = {}; | 1332 Map<String, Method> setters = {}; |
1260 Map<String, Method> getters = {}; | 1333 Map<String, Method> getters = {}; |
1261 Map<String, Method> constructors = {}; | 1334 Map<String, Method> constructors = {}; |
1262 Map<String, Method> operators = {}; | 1335 Map<String, Method> operators = {}; |
1263 Map<String, Method> regularMethods = {}; | 1336 Map<String, Method> regularMethods = {}; |
1264 | 1337 |
1265 void addMethod(MethodMirror mirror) { | 1338 void addMethod(MethodMirror mirror) { |
1266 var method = new Method(mirror.simpleName, mirror.isStatic, | 1339 var method = new Method(mirror); |
1267 mirror.isAbstract, mirror.isConstConstructor, _type(mirror.returnType), | |
1268 (actualMethod) => _commentToHtml(mirror, actualMethod), | |
1269 _parameters(mirror.parameters), | |
1270 _annotations(mirror), docName(mirror), _isHidden(mirror), | |
1271 docName(mirror.owner), mirror.isConstructor, mirror.isGetter, | |
1272 mirror.isSetter, mirror.isOperator, mirror); | |
1273 entityMap[docName(mirror)] = method; | 1340 entityMap[docName(mirror)] = method; |
1274 if (mirror.isSetter) { | 1341 if (mirror.isSetter) { |
1275 setters[mirror.simpleName] = method; | 1342 setters[mirror.simpleName] = method; |
1276 } else if (mirror.isGetter) { | 1343 } else if (mirror.isGetter) { |
1277 getters[mirror.simpleName] = method; | 1344 getters[mirror.simpleName] = method; |
1278 } else if (mirror.isConstructor) { | 1345 } else if (mirror.isConstructor) { |
1279 constructors[mirror.simpleName] = method; | 1346 constructors[mirror.simpleName] = method; |
1280 } else if (mirror.isOperator) { | 1347 } else if (mirror.isOperator) { |
1281 operators[mirror.simpleName] = method; | 1348 operators[mirror.simpleName] = method; |
1282 } else if (mirror.isRegularMethod) { | 1349 } else if (mirror.isRegularMethod) { |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1415 'name': qualifiedName, | 1482 'name': qualifiedName, |
1416 'parameters': parameters | 1483 'parameters': parameters |
1417 }; | 1484 }; |
1418 } | 1485 } |
1419 | 1486 |
1420 /// Given a mirror, returns its qualified name, but following the conventions | 1487 /// Given a mirror, returns its qualified name, but following the conventions |
1421 /// we're using in Dartdoc, which is that library names with dots in them | 1488 /// we're using in Dartdoc, which is that library names with dots in them |
1422 /// have them replaced with hyphens. | 1489 /// have them replaced with hyphens. |
1423 String docName(DeclarationMirror m) { | 1490 String docName(DeclarationMirror m) { |
1424 if (m is LibraryMirror) { | 1491 if (m is LibraryMirror) { |
1425 return (m as LibraryMirror).qualifiedName.replaceAll('.','-'); | 1492 return m.qualifiedName.replaceAll('.','-'); |
1426 } | 1493 } |
1427 var owner = m.owner; | 1494 var owner = m.owner; |
1428 if (owner == null) return m.qualifiedName; | 1495 if (owner == null) return m.qualifiedName; |
1429 // For the unnamed constructor we just return the class name. | 1496 // For the unnamed constructor we just return the class name. |
1430 if (m.simpleName == '') return docName(owner); | 1497 if (m.simpleName == '') return docName(owner); |
1431 return docName(owner) + '.' + m.simpleName; | 1498 return docName(owner) + '.' + m.simpleName; |
1432 } | 1499 } |
1433 | 1500 |
1434 /// Remove statics from the map of inherited items before adding them. | 1501 /// Remove statics from the map of inherited items before adding them. |
1435 Map _filterStatics(Map items) { | 1502 Map _filterStatics(Map items) { |
1436 var result = {}; | 1503 var result = {}; |
1437 items.forEach((name, item) { | 1504 items.forEach((name, item) { |
1438 if (!item.isStatic) { | 1505 if (!item.isStatic) { |
1439 result[name] = item; | 1506 result[name] = item; |
1440 } | 1507 } |
1441 }); | 1508 }); |
1442 return result; | 1509 return result; |
1443 } | 1510 } |
OLD | NEW |