| 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 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 Class _class(ClassMirror mirror) { | 395 Class _class(ClassMirror mirror) { |
| 396 var clazz = entityMap[mirror.qualifiedName]; | 396 var clazz = entityMap[mirror.qualifiedName]; |
| 397 if (clazz == null) { | 397 if (clazz == null) { |
| 398 var superclass = mirror.superclass != null ? | 398 var superclass = mirror.superclass != null ? |
| 399 _class(mirror.superclass) : null; | 399 _class(mirror.superclass) : null; |
| 400 var interfaces = | 400 var interfaces = |
| 401 mirror.superinterfaces.map((interface) => _class(interface)); | 401 mirror.superinterfaces.map((interface) => _class(interface)); |
| 402 clazz = new Class(mirror.simpleName, superclass, _commentToHtml(mirror), | 402 clazz = new Class(mirror.simpleName, superclass, _commentToHtml(mirror), |
| 403 interfaces.toList(), _variables(mirror.variables), | 403 interfaces.toList(), _variables(mirror.variables), |
| 404 _methods(mirror.methods), _annotations(mirror), _generics(mirror), | 404 _methods(mirror.methods), _annotations(mirror), _generics(mirror), |
| 405 mirror.qualifiedName, _isHidden(mirror), mirror.owner.qualifiedName); | 405 mirror.qualifiedName, _isHidden(mirror), mirror.owner.qualifiedName, |
| 406 mirror.isAbstract); |
| 406 if (superclass != null) | 407 if (superclass != null) |
| 407 clazz.addInherited(superclass); | 408 clazz.addInherited(superclass); |
| 408 interfaces.forEach((interface) { | 409 interfaces.forEach((interface) { |
| 409 clazz.addInherited(interface); | 410 clazz.addInherited(interface); |
| 410 }); | 411 }); |
| 411 entityMap[mirror.qualifiedName] = clazz; | 412 entityMap[mirror.qualifiedName] = clazz; |
| 412 } | 413 } |
| 413 return clazz; | 414 return clazz; |
| 414 } | 415 } |
| 415 | 416 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 inputMap.forEach((key, value) { | 494 inputMap.forEach((key, value) { |
| 494 if (value is Map) { | 495 if (value is Map) { |
| 495 outputMap[key] = recurseMap(value); | 496 outputMap[key] = recurseMap(value); |
| 496 } else { | 497 } else { |
| 497 outputMap[key] = value.toMap(); | 498 outputMap[key] = value.toMap(); |
| 498 } | 499 } |
| 499 }); | 500 }); |
| 500 return outputMap; | 501 return outputMap; |
| 501 } | 502 } |
| 502 | 503 |
| 503 bool isError(String qualifiedName) { | |
| 504 return qualifiedName.toLowerCase().contains('error') || | |
| 505 qualifiedName.toLowerCase().contains('exception'); | |
| 506 } | |
| 507 | |
| 508 /** | 504 /** |
| 509 * A class representing all programming constructs, like library or class. | 505 * A class representing all programming constructs, like library or class. |
| 510 */ | 506 */ |
| 511 class Indexable { | 507 class Indexable { |
| 512 String name; | 508 String name; |
| 513 String qualifiedName; | 509 String qualifiedName; |
| 514 bool isPrivate; | 510 bool isPrivate; |
| 515 | 511 |
| 516 /// Documentation comment with converted markdown. | 512 /// Documentation comment with converted markdown. |
| 517 String comment; | 513 String comment; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 /// Methods in the class. | 569 /// Methods in the class. |
| 574 MethodGroup methods; | 570 MethodGroup methods; |
| 575 | 571 |
| 576 /// Inherited methods in the class. | 572 /// Inherited methods in the class. |
| 577 MethodGroup inheritedMethods = new MethodGroup(); | 573 MethodGroup inheritedMethods = new MethodGroup(); |
| 578 | 574 |
| 579 /// Generic infomation about the class. | 575 /// Generic infomation about the class. |
| 580 Map<String, Generic> generics; | 576 Map<String, Generic> generics; |
| 581 | 577 |
| 582 Class superclass; | 578 Class superclass; |
| 579 bool isAbstract; |
| 583 | 580 |
| 584 /// List of the meta annotations on the class. | 581 /// List of the meta annotations on the class. |
| 585 List<String> annotations; | 582 List<String> annotations; |
| 586 | 583 |
| 587 Class(String name, this.superclass, String comment, this.interfaces, | 584 Class(String name, this.superclass, String comment, this.interfaces, |
| 588 this.variables, this.methods, this.annotations, this.generics, | 585 this.variables, this.methods, this.annotations, this.generics, |
| 589 String qualifiedName, bool isPrivate, String owner) : super(name, comment, | 586 String qualifiedName, bool isPrivate, String owner, this.isAbstract) |
| 590 qualifiedName, isPrivate, owner) {} | 587 : super(name, comment, qualifiedName, isPrivate, owner); |
| 591 | 588 |
| 592 /** | 589 /** |
| 593 * Returns a list of all the parent classes. | 590 * Returns a list of all the parent classes. |
| 594 */ | 591 */ |
| 595 List<Class> parent() { | 592 List<Class> parent() { |
| 596 var parent = superclass == null ? [] : [superclass]; | 593 var parent = superclass == null ? [] : [superclass]; |
| 597 parent.addAll(interfaces); | 594 parent.addAll(interfaces); |
| 598 return parent; | 595 return parent; |
| 599 } | 596 } |
| 600 | 597 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 620 void addSubclass(Class subclass) { | 617 void addSubclass(Class subclass) { |
| 621 if (!_includePrivate && isPrivate) { | 618 if (!_includePrivate && isPrivate) { |
| 622 if (superclass != null) superclass.addSubclass(subclass); | 619 if (superclass != null) superclass.addSubclass(subclass); |
| 623 interfaces.forEach((interface) { | 620 interfaces.forEach((interface) { |
| 624 interface.addSubclass(subclass); | 621 interface.addSubclass(subclass); |
| 625 }); | 622 }); |
| 626 } else { | 623 } else { |
| 627 subclasses.add(subclass.qualifiedName); | 624 subclasses.add(subclass.qualifiedName); |
| 628 } | 625 } |
| 629 } | 626 } |
| 627 |
| 628 /** |
| 629 * Check if this [Class] is an error or exception. |
| 630 */ |
| 631 bool isError() { |
| 632 if (qualifiedName == 'dart.core.Error' || |
| 633 qualifiedName == 'dart.core.Exception') |
| 634 return true; |
| 635 for (var interface in interfaces) { |
| 636 if (interface.isError()) return true; |
| 637 } |
| 638 if (superclass == null) return false; |
| 639 return superclass.isError(); |
| 640 } |
| 630 | 641 |
| 631 /** | 642 /** |
| 632 * Check that the class exists in the owner library. | 643 * Check that the class exists in the owner library. |
| 633 * | 644 * |
| 634 * If it does not exist in the owner library, it is a mixin applciation and | 645 * If it does not exist in the owner library, it is a mixin applciation and |
| 635 * should be removed. | 646 * should be removed. |
| 636 */ | 647 */ |
| 637 void makeValid() { | 648 void makeValid() { |
| 638 var library = entityMap[owner]; | 649 var library = entityMap[owner]; |
| 639 if (library != null && !library.classes.containsKey(name)) { | 650 if (library != null && !library.classes.containsKey(name)) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 665 if (superclass == null) return 'dart.core.Object'; | 676 if (superclass == null) return 'dart.core.Object'; |
| 666 if (_isVisible(superclass)) return superclass.qualifiedName; | 677 if (_isVisible(superclass)) return superclass.qualifiedName; |
| 667 return superclass.validSuperclass(); | 678 return superclass.validSuperclass(); |
| 668 } | 679 } |
| 669 | 680 |
| 670 /// Generates a map describing the [Class] object. | 681 /// Generates a map describing the [Class] object. |
| 671 Map toMap() => { | 682 Map toMap() => { |
| 672 'name': name, | 683 'name': name, |
| 673 'qualifiedName': qualifiedName, | 684 'qualifiedName': qualifiedName, |
| 674 'comment': comment, | 685 'comment': comment, |
| 686 'isAbstract' : isAbstract, |
| 675 'superclass': validSuperclass(), | 687 'superclass': validSuperclass(), |
| 676 'implements': interfaces.where(_isVisible) | 688 'implements': interfaces.where(_isVisible) |
| 677 .map((e) => e.qualifiedName).toList(), | 689 .map((e) => e.qualifiedName).toList(), |
| 678 'subclass': subclasses.toList(), | 690 'subclass': subclasses.toList(), |
| 679 'variables': recurseMap(variables), | 691 'variables': recurseMap(variables), |
| 680 'inheritedVariables': recurseMap(inheritedVariables), | 692 'inheritedVariables': recurseMap(inheritedVariables), |
| 681 'methods': methods.toMap(), | 693 'methods': methods.toMap(), |
| 682 'inheritedMethods': inheritedMethods.toMap(), | 694 'inheritedMethods': inheritedMethods.toMap(), |
| 683 'annotations': annotations.map((a) => a.toMap()).toList(), | 695 'annotations': annotations.map((a) => a.toMap()).toList(), |
| 684 'generics': recurseMap(generics) | 696 'generics': recurseMap(generics) |
| 685 }; | 697 }; |
| 686 } | 698 } |
| 687 | 699 |
| 688 /** | 700 /** |
| 689 * A container to categorize classes into the following groups: abstract | 701 * A container to categorize classes into the following groups: abstract |
| 690 * classes, regular classes, typedefs, and errors. | 702 * classes, regular classes, typedefs, and errors. |
| 691 */ | 703 */ |
| 692 class ClassGroup { | 704 class ClassGroup { |
| 693 Map<String, Class> abstractClasses = {}; | 705 Map<String, Class> classes = {}; |
| 694 Map<String, Class> regularClasses = {}; | |
| 695 Map<String, Typedef> typedefs = {}; | 706 Map<String, Typedef> typedefs = {}; |
| 696 Map<String, Class> errors = {}; | 707 Map<String, Class> errors = {}; |
| 697 | 708 |
| 698 void addClass(ClassMirror mirror) { | 709 void addClass(ClassMirror mirror) { |
| 699 _currentClass = mirror; | 710 _currentClass = mirror; |
| 700 var clazz = _class(mirror); | 711 var clazz = _class(mirror); |
| 701 | 712 |
| 702 // Adding inherited parent variables and methods. | 713 // Adding inherited parent variables and methods. |
| 703 clazz.parent().forEach((parent) { | 714 clazz.parent().forEach((parent) { |
| 704 if (_isVisible(clazz)) { | 715 if (_isVisible(clazz)) { |
| 705 parent.addSubclass(clazz); | 716 parent.addSubclass(clazz); |
| 706 } | 717 } |
| 707 }); | 718 }); |
| 708 | 719 |
| 709 clazz.ensureComments(); | 720 clazz.ensureComments(); |
| 710 | 721 |
| 711 if (isError(mirror.qualifiedName)) { | 722 if (clazz.isError()) { |
| 712 errors[mirror.simpleName] = clazz; | 723 errors[mirror.simpleName] = clazz; |
| 713 } else if (mirror.isTypedef) { | 724 } else if (mirror.isTypedef) { |
| 714 if (_includePrivate || !mirror.isPrivate) { | 725 if (_includePrivate || !mirror.isPrivate) { |
| 715 entityMap[mirror.qualifiedName] = new Typedef(mirror.simpleName, | 726 entityMap[mirror.qualifiedName] = new Typedef(mirror.simpleName, |
| 716 mirror.value.returnType.qualifiedName, _commentToHtml(mirror), | 727 mirror.value.returnType.qualifiedName, _commentToHtml(mirror), |
| 717 _generics(mirror), _parameters(mirror.value.parameters), | 728 _generics(mirror), _parameters(mirror.value.parameters), |
| 718 _annotations(mirror), mirror.qualifiedName, _isHidden(mirror), | 729 _annotations(mirror), mirror.qualifiedName, _isHidden(mirror), |
| 719 mirror.owner.qualifiedName); | 730 mirror.owner.qualifiedName); |
| 720 typedefs[mirror.simpleName] = entityMap[mirror.qualifiedName]; | 731 typedefs[mirror.simpleName] = entityMap[mirror.qualifiedName]; |
| 721 } | 732 } |
| 722 } else if (mirror.isAbstract) { | |
| 723 abstractClasses[mirror.simpleName] = clazz; | |
| 724 } else if (mirror.isClass) { | 733 } else if (mirror.isClass) { |
| 725 regularClasses[mirror.simpleName] = clazz; | 734 classes[mirror.simpleName] = clazz; |
| 726 } else { | 735 } else { |
| 727 throw new ArgumentError('${mirror.simpleName} - no class type match. '); | 736 throw new ArgumentError('${mirror.simpleName} - no class type match. '); |
| 728 } | 737 } |
| 729 } | 738 } |
| 730 | 739 |
| 731 /** | 740 /** |
| 732 * Checks if the given name is a key for any of the Class Maps. | 741 * Checks if the given name is a key for any of the Class Maps. |
| 733 */ | 742 */ |
| 734 bool containsKey(String name) { | 743 bool containsKey(String name) { |
| 735 return abstractClasses.containsKey(name) || | 744 return classes.containsKey(name) || errors.containsKey(name); |
| 736 regularClasses.containsKey(name) || | |
| 737 errors.containsKey(name); | |
| 738 } | 745 } |
| 739 | 746 |
| 747 /** |
| 748 * Creates a [Map] with [Class] names and a preview comment. |
| 749 */ |
| 750 Map classMap(Class clazz) { |
| 751 var finalMap = { 'name' : clazz.qualifiedName }; |
| 752 if (clazz.comment != '') { |
| 753 var index = clazz.comment.indexOf('</p>'); |
| 754 finalMap['preview'] = '${clazz.comment.substring(0, index)}</p>'; |
| 755 } |
| 756 return finalMap; |
| 757 } |
| 758 |
| 740 Map toMap() => { | 759 Map toMap() => { |
| 741 'abstract': abstractClasses.values.where(_isVisible) | 760 'class': classes.values.where(_isVisible) |
| 742 .map((e) => e.qualifiedName).toList(), | 761 .map((e) => classMap(e)).toList(), |
| 743 'class': regularClasses.values.where(_isVisible) | |
| 744 .map((e) => e.qualifiedName).toList(), | |
| 745 'typedef': recurseMap(typedefs), | 762 'typedef': recurseMap(typedefs), |
| 746 'error': errors.values.where(_isVisible) | 763 'error': errors.values.where(_isVisible) |
| 747 .map((e) => e.qualifiedName).toList() | 764 .map((e) => classMap(e)).toList() |
| 748 }; | 765 }; |
| 749 } | 766 } |
| 750 | 767 |
| 751 class Typedef extends Indexable { | 768 class Typedef extends Indexable { |
| 752 String returnType; | 769 String returnType; |
| 753 | 770 |
| 754 Map<String, Parameter> parameters; | 771 Map<String, Parameter> parameters; |
| 755 | 772 |
| 756 /// Generic information about the typedef. | 773 /// Generic information about the typedef. |
| 757 Map<String, Generic> generics; | 774 Map<String, Generic> generics; |
| 758 | 775 |
| 759 /// List of the meta annotations on the typedef. | 776 /// List of the meta annotations on the typedef. |
| 760 List<String> annotations; | 777 List<String> annotations; |
| 761 | 778 |
| 762 Typedef(String name, this.returnType, String comment, this.generics, | 779 Typedef(String name, this.returnType, String comment, this.generics, |
| 763 this.parameters, this.annotations, | 780 this.parameters, this.annotations, |
| 764 String qualifiedName, bool isPrivate, String owner) : super(name, comment, | 781 String qualifiedName, bool isPrivate, String owner) |
| 765 qualifiedName, isPrivate, owner) {} | 782 : super(name, comment, qualifiedName, isPrivate, owner); |
| 766 | 783 |
| 767 Map toMap() => { | 784 Map toMap() => { |
| 768 'name': name, | 785 'name': name, |
| 769 'qualifiedName': qualifiedName, | 786 'qualifiedName': qualifiedName, |
| 770 'comment': comment, | 787 'comment': comment, |
| 771 'return': returnType, | 788 'return': returnType, |
| 772 'parameters': recurseMap(parameters), | 789 'parameters': recurseMap(parameters), |
| 773 'annotations': annotations.map((a) => a.toMap()).toList(), | 790 'annotations': annotations.map((a) => a.toMap()).toList(), |
| 774 'generics': recurseMap(generics) | 791 'generics': recurseMap(generics) |
| 775 }; | 792 }; |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1022 String qualifiedName; | 1039 String qualifiedName; |
| 1023 List<String> parameters; | 1040 List<String> parameters; |
| 1024 | 1041 |
| 1025 Annotation(this.qualifiedName, this.parameters); | 1042 Annotation(this.qualifiedName, this.parameters); |
| 1026 | 1043 |
| 1027 Map toMap() => { | 1044 Map toMap() => { |
| 1028 'name': qualifiedName, | 1045 'name': qualifiedName, |
| 1029 'parameters': parameters | 1046 'parameters': parameters |
| 1030 }; | 1047 }; |
| 1031 } | 1048 } |
| OLD | NEW |