| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 * To generate docs for a library, run this script with the path to an | 6 * To generate docs for a library, run this script with the path to an |
| 7 * entrypoint .dart file, like: | 7 * entrypoint .dart file, like: |
| 8 * | 8 * |
| 9 * $ dart dartdoc.dart foo.dart | 9 * $ dart dartdoc.dart foo.dart |
| 10 * | 10 * |
| (...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 _currentType = null; | 716 _currentType = null; |
| 717 | 717 |
| 718 startFile(libraryUrl(library)); | 718 startFile(libraryUrl(library)); |
| 719 writeHeader('${library.simpleName} Library', | 719 writeHeader('${library.simpleName} Library', |
| 720 [library.simpleName, libraryUrl(library)]); | 720 [library.simpleName, libraryUrl(library)]); |
| 721 writeln('<h2><strong>${library.simpleName}</strong> library</h2>'); | 721 writeln('<h2><strong>${library.simpleName}</strong> library</h2>'); |
| 722 | 722 |
| 723 // Look for a comment for the entire library. | 723 // Look for a comment for the entire library. |
| 724 final comment = getLibraryComment(library); | 724 final comment = getLibraryComment(library); |
| 725 if (comment != null) { | 725 if (comment != null) { |
| 726 writeln('<div class="doc">$comment</div>'); | 726 writeln('<div class="doc">${comment.html}</div>'); |
| 727 } | 727 } |
| 728 | 728 |
| 729 // Document the top-level members. | 729 // Document the top-level members. |
| 730 docMembers(library); | 730 docMembers(library); |
| 731 | 731 |
| 732 // Document the types. | 732 // Document the types. |
| 733 final classes = <InterfaceMirror>[]; | 733 final classes = <InterfaceMirror>[]; |
| 734 final interfaces = <InterfaceMirror>[]; | 734 final interfaces = <InterfaceMirror>[]; |
| 735 final typedefs = <TypedefMirror>[]; | 735 final typedefs = <TypedefMirror>[]; |
| 736 final exceptions = <InterfaceMirror>[]; | 736 final exceptions = <InterfaceMirror>[]; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 762 for (final type in library.types.getValues()) { | 762 for (final type in library.types.getValues()) { |
| 763 if (type.isPrivate) continue; | 763 if (type.isPrivate) continue; |
| 764 | 764 |
| 765 docType(type); | 765 docType(type); |
| 766 } | 766 } |
| 767 } | 767 } |
| 768 | 768 |
| 769 void docTypes(List types, String header) { | 769 void docTypes(List types, String header) { |
| 770 if (types.length == 0) return; | 770 if (types.length == 0) return; |
| 771 | 771 |
| 772 writeln('<div>'); |
| 772 writeln('<h3>$header</h3>'); | 773 writeln('<h3>$header</h3>'); |
| 773 | 774 |
| 774 for (final type in types) { | 775 for (final type in types) { |
| 775 writeln( | 776 writeln( |
| 776 ''' | 777 ''' |
| 777 <div class="type"> | 778 <div class="type"> |
| 778 <h4> | 779 <h4> |
| 779 ${a(typeUrl(type), "<strong>${typeName(type)}</strong>")} | 780 ${a(typeUrl(type), "<strong>${typeName(type)}</strong>")} |
| 780 </h4> | 781 </h4> |
| 781 </div> | 782 </div> |
| 782 '''); | 783 '''); |
| 783 } | 784 } |
| 785 writeln('</div>'); |
| 784 } | 786 } |
| 785 | 787 |
| 786 void docType(InterfaceMirror type) { | 788 void docType(InterfaceMirror type) { |
| 787 if (verbose) { | 789 if (verbose) { |
| 788 print('- ${type.simpleName}'); | 790 print('- ${type.simpleName}'); |
| 789 } | 791 } |
| 790 _totalTypes++; | 792 _totalTypes++; |
| 791 _currentType = type; | 793 _currentType = type; |
| 792 | 794 |
| 793 startFile(typeUrl(type)); | 795 startFile(typeUrl(type)); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 807 '${typeName(type)} ${kind}'; | 809 '${typeName(type)} ${kind}'; |
| 808 writeHeader('$typeTitle / ${type.library.simpleName} Library', | 810 writeHeader('$typeTitle / ${type.library.simpleName} Library', |
| 809 [type.library.simpleName, libraryUrl(type.library), | 811 [type.library.simpleName, libraryUrl(type.library), |
| 810 typeName(type), typeUrl(type)]); | 812 typeName(type), typeUrl(type)]); |
| 811 writeln( | 813 writeln( |
| 812 ''' | 814 ''' |
| 813 <h2><strong>${typeName(type, showBounds: true)}</strong> | 815 <h2><strong>${typeName(type, showBounds: true)}</strong> |
| 814 $kind | 816 $kind |
| 815 </h2> | 817 </h2> |
| 816 '''); | 818 '''); |
| 819 writeln('<button id="show-inherited" class="show-inherited">' |
| 820 'Hide inherited</button>'); |
| 817 | 821 |
| 818 docCode(type.location, getTypeComment(type)); | 822 docCode(type, type.location, getTypeComment(type)); |
| 819 docInheritance(type); | 823 docInheritance(type); |
| 820 docTypedef(type); | 824 docTypedef(type); |
| 825 |
| 821 docConstructors(type); | 826 docConstructors(type); |
| 822 docMembers(type); | 827 docMembers(type); |
| 823 | 828 |
| 824 writeTypeFooter(); | 829 writeTypeFooter(); |
| 825 writeFooter(); | 830 writeFooter(); |
| 826 endFile(); | 831 endFile(); |
| 827 } | 832 } |
| 828 | 833 |
| 829 /** Override this to write additional content at the end of a type's page. */ | 834 /** Override this to write additional content at the end of a type's page. */ |
| 830 void writeTypeFooter() { | 835 void writeTypeFooter() { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 942 /** | 947 /** |
| 943 * Documents the definition of [type] if it is a typedef. | 948 * Documents the definition of [type] if it is a typedef. |
| 944 */ | 949 */ |
| 945 void docTypedef(TypeMirror type) { | 950 void docTypedef(TypeMirror type) { |
| 946 if (type is! TypedefMirror) { | 951 if (type is! TypedefMirror) { |
| 947 return; | 952 return; |
| 948 } | 953 } |
| 949 writeln('<div class="method"><h4 id="${type.simpleName}">'); | 954 writeln('<div class="method"><h4 id="${type.simpleName}">'); |
| 950 | 955 |
| 951 if (includeSource) { | 956 if (includeSource) { |
| 952 writeln('<span class="show-code">Code</span>'); | 957 writeln('<button class="show-code">Code</button>'); |
| 953 } | 958 } |
| 954 | 959 |
| 955 write('typedef '); | 960 write('typedef '); |
| 956 annotateType(type, type.definition, type.simpleName); | 961 annotateType(type, type.definition, type.simpleName); |
| 957 | 962 |
| 958 write(''' <a class="anchor-link" href="#${type.simpleName}" | 963 write(''' <a class="anchor-link" href="#${type.simpleName}" |
| 959 title="Permalink to ${type.simpleName}">#</a>'''); | 964 title="Permalink to ${type.simpleName}">#</a>'''); |
| 960 writeln('</h4>'); | 965 writeln('</h4>'); |
| 961 | 966 |
| 962 docCode(type.location, null, showCode: true); | 967 docCode(type, type.location, null, showCode: true); |
| 963 | 968 |
| 964 writeln('</div>'); | 969 writeln('</div>'); |
| 965 } | 970 } |
| 966 | 971 |
| 967 /** Document the constructors for [Type], if any. */ | 972 /** Document the constructors for [Type], if any. */ |
| 968 void docConstructors(InterfaceMirror type) { | 973 void docConstructors(InterfaceMirror type) { |
| 969 final constructors = <MethodMirror>[]; | 974 final constructors = <MethodMirror>[]; |
| 970 for (var constructor in type.constructors.getValues()) { | 975 for (var constructor in type.constructors.getValues()) { |
| 971 if (!constructor.isPrivate) { | 976 if (!constructor.isPrivate) { |
| 972 constructors.add(constructor); | 977 constructors.add(constructor); |
| 973 } | 978 } |
| 974 } | 979 } |
| 975 | 980 |
| 976 if (constructors.length > 0) { | 981 if (constructors.length > 0) { |
| 982 writeln('<div>'); |
| 977 writeln('<h3>Constructors</h3>'); | 983 writeln('<h3>Constructors</h3>'); |
| 978 constructors.sort((x, y) => x.constructorName.toUpperCase().compareTo( | 984 constructors.sort((x, y) => x.constructorName.toUpperCase().compareTo( |
| 979 y.constructorName.toUpperCase())); | 985 y.constructorName.toUpperCase())); |
| 980 | 986 |
| 981 for (final constructor in constructors) { | 987 for (final constructor in constructors) { |
| 982 docMethod(type, constructor); | 988 docMethod(type, constructor); |
| 983 } | 989 } |
| 990 writeln('</div>'); |
| 984 } | 991 } |
| 985 } | 992 } |
| 986 | 993 |
| 987 void docMembers(ObjectMirror host) { | 994 void docMembers(ObjectMirror host) { |
| 988 // Collect the different kinds of members. | 995 // Collect the different kinds of members. |
| 989 final staticMethods = []; | 996 final staticMethods = []; |
| 990 final staticFields = []; | 997 final staticFields = []; |
| 998 final memberMap = new Map<String,MemberMirror>(); |
| 991 final instanceMethods = []; | 999 final instanceMethods = []; |
| 992 final instanceFields = []; | 1000 final instanceFields = []; |
| 993 | 1001 |
| 994 for (MemberMirror member in orderByName(host.declaredMembers.getValues())) { | 1002 host.declaredMembers.forEach((_, MemberMirror member) { |
| 995 if (member.isPrivate) continue; | 1003 if (member.isPrivate) return; |
| 1004 if (member.isStatic) { |
| 1005 if (member.isMethod) { |
| 1006 staticMethods.add(member); |
| 1007 } else if (member.isField) { |
| 1008 staticFields.add(member); |
| 1009 } |
| 1010 } |
| 1011 }); |
| 996 | 1012 |
| 997 final methods = member.isStatic ? staticMethods : instanceMethods; | 1013 if (host is InterfaceMirror) { |
| 998 final fields = member.isStatic ? staticFields : instanceFields; | 1014 var iterable = new HierarchyIterable(host, includeType: true); |
| 1015 for (InterfaceMirror type in iterable) { |
| 1016 type.declaredMembers.forEach((_, MemberMirror member) { |
| 1017 if (member.isPrivate) return; |
| 1018 if (!member.isStatic) { |
| 1019 memberMap.putIfAbsent(member.simpleName, () => member); |
| 1020 } |
| 1021 }); |
| 1022 } |
| 1023 } |
| 999 | 1024 |
| 1025 memberMap.forEach((_, MemberMirror member) { |
| 1000 if (member.isMethod) { | 1026 if (member.isMethod) { |
| 1001 methods.add(member); | 1027 instanceMethods.add(member); |
| 1002 } else if (member.isField) { | 1028 } else if (member.isField) { |
| 1003 fields.add(member); | 1029 instanceFields.add(member); |
| 1004 } | 1030 } |
| 1031 }); |
| 1032 |
| 1033 if (staticFields.length > 0) { |
| 1034 final title = host is LibraryMirror ? 'Variables' : 'Static Fields'; |
| 1035 writeln('<div>'); |
| 1036 writeln('<h3>$title</h3>'); |
| 1037 for (final field in orderByName(staticFields)) { |
| 1038 docField(host, field); |
| 1039 } |
| 1040 writeln('</div>'); |
| 1005 } | 1041 } |
| 1006 | 1042 |
| 1007 if (staticMethods.length > 0) { | 1043 if (staticMethods.length > 0) { |
| 1008 final title = host is LibraryMirror ? 'Functions' : 'Static Methods'; | 1044 final title = host is LibraryMirror ? 'Functions' : 'Static Methods'; |
| 1045 writeln('<div>'); |
| 1009 writeln('<h3>$title</h3>'); | 1046 writeln('<h3>$title</h3>'); |
| 1010 for (final method in orderByName(staticMethods)) { | 1047 for (final method in orderByName(staticMethods)) { |
| 1011 docMethod(host, method); | 1048 docMethod(host, method); |
| 1012 } | 1049 } |
| 1050 writeln('</div>'); |
| 1013 } | 1051 } |
| 1014 | 1052 |
| 1015 if (staticFields.length > 0) { | 1053 if (instanceFields.length > 0) { |
| 1016 final title = host is LibraryMirror ? 'Variables' : 'Static Fields'; | 1054 writeln('<div>'); |
| 1017 writeln('<h3>$title</h3>'); | 1055 writeln('<h3>Fields</h3>'); |
| 1018 for (final field in orderByName(staticFields)) { | 1056 for (final field in orderByName(instanceFields)) { |
| 1019 docField(host, field); | 1057 docField(host, field); |
| 1020 } | 1058 } |
| 1059 writeln('</div>'); |
| 1021 } | 1060 } |
| 1022 | 1061 |
| 1023 if (instanceMethods.length > 0) { | 1062 if (instanceMethods.length > 0) { |
| 1063 writeln('<div>'); |
| 1024 writeln('<h3>Methods</h3>'); | 1064 writeln('<h3>Methods</h3>'); |
| 1025 for (final method in orderByName(instanceMethods)) { | 1065 for (final method in orderByName(instanceMethods)) { |
| 1026 docMethod(host, method); | 1066 docMethod(host, method); |
| 1027 } | 1067 } |
| 1028 } | 1068 writeln('</div>'); |
| 1029 | |
| 1030 if (instanceFields.length > 0) { | |
| 1031 writeln('<h3>Fields</h3>'); | |
| 1032 for (final field in orderByName(instanceFields)) { | |
| 1033 docField(host, field); | |
| 1034 } | |
| 1035 } | 1069 } |
| 1036 } | 1070 } |
| 1037 | 1071 |
| 1038 /** | 1072 /** |
| 1039 * Documents the [method] in type [type]. Handles all kinds of methods | 1073 * Documents the [method] in type [type]. Handles all kinds of methods |
| 1040 * including getters, setters, and constructors. | 1074 * including getters, setters, and constructors. |
| 1041 */ | 1075 */ |
| 1042 void docMethod(ObjectMirror host, MethodMirror method) { | 1076 void docMethod(ObjectMirror host, MethodMirror method) { |
| 1043 _totalMembers++; | 1077 _totalMembers++; |
| 1044 _currentMember = method; | 1078 _currentMember = method; |
| 1045 | 1079 |
| 1046 bool showCode = includeSource && !method.isAbstract; | 1080 bool showCode = includeSource && !method.isAbstract; |
| 1081 bool inherited = host != method.surroundingDeclaration; |
| 1047 | 1082 |
| 1048 writeln('<div class="method"><h4 id="${memberAnchor(method)}">'); | 1083 writeln('<div class="method${inherited ? ' inherited': ''}">' |
| 1084 '<h4 id="${memberAnchor(method)}">'); |
| 1049 | 1085 |
| 1050 if (showCode) { | 1086 if (showCode) { |
| 1051 writeln('<span class="show-code">Code</span>'); | 1087 writeln('<button class="show-code">Code</button>'); |
| 1052 } | 1088 } |
| 1053 | 1089 |
| 1054 if (method.isConstructor) { | 1090 if (method.isConstructor) { |
| 1055 if (method.isFactory) { | 1091 if (method.isFactory) { |
| 1056 write('factory '); | 1092 write('factory '); |
| 1057 } else { | 1093 } else { |
| 1058 write(method.isConst ? 'const ' : 'new '); | 1094 write(method.isConst ? 'const ' : 'new '); |
| 1059 } | 1095 } |
| 1060 } else if (method.isAbstract) { | 1096 } else if (method.isAbstract) { |
| 1061 write('abstract '); | 1097 write('abstract '); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1077 | 1113 |
| 1078 write('<strong>$name</strong>'); | 1114 write('<strong>$name</strong>'); |
| 1079 | 1115 |
| 1080 docParamList(host, method.parameters); | 1116 docParamList(host, method.parameters); |
| 1081 | 1117 |
| 1082 var prefix = host is LibraryMirror ? '' : '${typeName(host)}.'; | 1118 var prefix = host is LibraryMirror ? '' : '${typeName(host)}.'; |
| 1083 write(''' <a class="anchor-link" href="#${memberAnchor(method)}" | 1119 write(''' <a class="anchor-link" href="#${memberAnchor(method)}" |
| 1084 title="Permalink to $prefix$name">#</a>'''); | 1120 title="Permalink to $prefix$name">#</a>'''); |
| 1085 writeln('</h4>'); | 1121 writeln('</h4>'); |
| 1086 | 1122 |
| 1087 docCode(method.location, getMethodComment(method), showCode: showCode); | 1123 if (inherited) { |
| 1124 write('<div class="inherited-from">inherited from '); |
| 1125 annotateType(host, method.surroundingDeclaration); |
| 1126 write('</div>'); |
| 1127 } |
| 1128 |
| 1129 docCode(host, method.location, getMemberComment(method), showCode: showCode)
; |
| 1088 | 1130 |
| 1089 writeln('</div>'); | 1131 writeln('</div>'); |
| 1090 } | 1132 } |
| 1091 | 1133 |
| 1092 /** Documents the field [field] of type [type]. */ | 1134 /** Documents the field [field] of type [type]. */ |
| 1093 void docField(ObjectMirror host, FieldMirror field) { | 1135 void docField(ObjectMirror host, FieldMirror field) { |
| 1094 _totalMembers++; | 1136 _totalMembers++; |
| 1095 _currentMember = field; | 1137 _currentMember = field; |
| 1096 | 1138 |
| 1097 writeln('<div class="field"><h4 id="${memberAnchor(field)}">'); | 1139 bool inherited = host != field.surroundingDeclaration; |
| 1140 |
| 1141 writeln('<div class="field${inherited ? ' inherited' : ''}">' |
| 1142 '<h4 id="${memberAnchor(field)}">'); |
| 1098 | 1143 |
| 1099 if (includeSource) { | 1144 if (includeSource) { |
| 1100 writeln('<span class="show-code">Code</span>'); | 1145 writeln('<button class="show-code">Code</button>'); |
| 1101 } | 1146 } |
| 1102 | 1147 |
| 1103 if (field.isFinal) { | 1148 if (field.isFinal) { |
| 1104 write('final '); | 1149 write('final '); |
| 1105 } else if (field.type.isDynamic) { | 1150 } else if (field.type.isDynamic) { |
| 1106 write('var '); | 1151 write('var '); |
| 1107 } | 1152 } |
| 1108 | 1153 |
| 1109 annotateType(host, field.type); | 1154 annotateType(host, field.type); |
| 1110 var prefix = host is LibraryMirror ? '' : '${typeName(host)}.'; | 1155 var prefix = host is LibraryMirror ? '' : '${typeName(host)}.'; |
| 1111 write( | 1156 write( |
| 1112 ''' | 1157 ''' |
| 1113 <strong>${field.simpleName}</strong> <a class="anchor-link" | 1158 <strong>${field.simpleName}</strong> <a class="anchor-link" |
| 1114 href="#${memberAnchor(field)}" | 1159 href="#${memberAnchor(field)}" |
| 1115 title="Permalink to $prefix${field.simpleName}">#</a> | 1160 title="Permalink to $prefix${field.simpleName}">#</a> |
| 1116 </h4> | 1161 </h4> |
| 1117 '''); | 1162 '''); |
| 1118 | 1163 |
| 1119 docCode(field.location, getFieldComment(field), showCode: true); | 1164 if (inherited) { |
| 1165 write('<div class="inherited-from">inherited from '); |
| 1166 annotateType(host, field.surroundingDeclaration); |
| 1167 write('</div>'); |
| 1168 } |
| 1169 |
| 1170 docCode(host, field.location, getMemberComment(field), showCode: true); |
| 1171 |
| 1120 writeln('</div>'); | 1172 writeln('</div>'); |
| 1121 } | 1173 } |
| 1122 | 1174 |
| 1123 void docParamList(ObjectMirror enclosingType, | 1175 void docParamList(ObjectMirror enclosingType, |
| 1124 List<ParameterMirror> parameters) { | 1176 List<ParameterMirror> parameters) { |
| 1125 write('('); | 1177 write('('); |
| 1126 bool first = true; | 1178 bool first = true; |
| 1127 bool inOptionals = false; | 1179 bool inOptionals = false; |
| 1128 for (final parameter in parameters) { | 1180 for (final parameter in parameters) { |
| 1129 if (!first) write(', '); | 1181 if (!first) write(', '); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1145 } | 1197 } |
| 1146 | 1198 |
| 1147 if (inOptionals) write(']'); | 1199 if (inOptionals) write(']'); |
| 1148 write(')'); | 1200 write(')'); |
| 1149 } | 1201 } |
| 1150 | 1202 |
| 1151 /** | 1203 /** |
| 1152 * Documents the code contained within [span] with [comment]. If [showCode] | 1204 * Documents the code contained within [span] with [comment]. If [showCode] |
| 1153 * is `true` (and [includeSource] is set), also includes the source code. | 1205 * is `true` (and [includeSource] is set), also includes the source code. |
| 1154 */ | 1206 */ |
| 1155 void docCode(Location location, String comment, [bool showCode = false]) { | 1207 void docCode(ObjectMirror host, Location location, DocComment comment, |
| 1208 [bool showCode = false]) { |
| 1156 writeln('<div class="doc">'); | 1209 writeln('<div class="doc">'); |
| 1157 if (comment != null) { | 1210 if (comment != null) { |
| 1158 writeln(comment); | 1211 if (comment.inheritedFrom !== null) { |
| 1212 writeln('<div class="inherited">'); |
| 1213 writeln(comment.html); |
| 1214 write('<div class="docs-inherited-from">docs inherited from '); |
| 1215 annotateType(host, comment.inheritedFrom); |
| 1216 write('</div>'); |
| 1217 writeln('</div>'); |
| 1218 } else { |
| 1219 writeln(comment.html); |
| 1220 } |
| 1159 } | 1221 } |
| 1160 | 1222 |
| 1161 if (includeSource && showCode) { | 1223 if (includeSource && showCode) { |
| 1162 writeln('<pre class="source">'); | 1224 writeln('<pre class="source">'); |
| 1163 writeln(md.escapeHtml(unindentCode(location))); | 1225 writeln(md.escapeHtml(unindentCode(location))); |
| 1164 writeln('</pre>'); | 1226 writeln('</pre>'); |
| 1165 } | 1227 } |
| 1166 | 1228 |
| 1167 writeln('</div>'); | 1229 writeln('</div>'); |
| 1168 } | 1230 } |
| 1169 | 1231 |
| 1232 DocComment createDocComment(String text, [InterfaceMirror inheritedFrom]) => |
| 1233 new DocComment(text, inheritedFrom); |
| 1234 |
| 1170 | 1235 |
| 1171 /** Get the doc comment associated with the given library. */ | 1236 /** Get the doc comment associated with the given library. */ |
| 1172 String getLibraryComment(LibraryMirror library) { | 1237 DocComment getLibraryComment(LibraryMirror library) { |
| 1173 // Look for a comment for the entire library. | 1238 // Look for a comment for the entire library. |
| 1174 final comment = _comments.findLibrary(library.location.source); | 1239 final comment = _comments.findLibrary(library.location.source); |
| 1175 if (comment != null) { | 1240 if (comment == null) return null; |
| 1176 return md.markdownToHtml(comment); | 1241 return createDocComment(comment); |
| 1177 } | |
| 1178 return null; | |
| 1179 } | 1242 } |
| 1180 | 1243 |
| 1181 /** Get the doc comment associated with the given type. */ | 1244 /** Get the doc comment associated with the given type. */ |
| 1182 String getTypeComment(TypeMirror type) { | 1245 DocComment getTypeComment(TypeMirror type) { |
| 1183 String comment = _comments.find(type.location); | 1246 String comment = _comments.find(type.location); |
| 1184 if (comment == null) return null; | 1247 if (comment == null) return null; |
| 1185 return commentToHtml(comment); | 1248 return createDocComment(comment); |
| 1186 } | 1249 } |
| 1187 | 1250 |
| 1188 /** Get the doc comment associated with the given method. */ | 1251 /** |
| 1189 String getMethodComment(MethodMirror method) { | 1252 * Get the doc comment associated with the given member. |
| 1190 String comment = _comments.find(method.location); | 1253 * |
| 1254 * If no comment was found on the member, the hierarchy is traversed to find |
| 1255 * an inherited comment, favouring comments inherited from classes over |
| 1256 * comments inherited from interfaces. |
| 1257 */ |
| 1258 DocComment getMemberComment(MemberMirror member) { |
| 1259 String comment = _comments.find(member.location); |
| 1260 InterfaceMirror inheritedFrom = null; |
| 1261 if (comment == null) { |
| 1262 if (member.surroundingDeclaration is InterfaceMirror) { |
| 1263 var iterable = |
| 1264 new HierarchyIterable(member.surroundingDeclaration, |
| 1265 includeType: false); |
| 1266 for (InterfaceMirror type in iterable) { |
| 1267 var inheritedMember = type.declaredMembers[member.simpleName]; |
| 1268 if (inheritedMember is MemberMirror) { |
| 1269 comment = _comments.find(inheritedMember.location); |
| 1270 if (comment != null) { |
| 1271 inheritedFrom = type; |
| 1272 break; |
| 1273 } |
| 1274 } |
| 1275 } |
| 1276 } |
| 1277 } |
| 1191 if (comment == null) return null; | 1278 if (comment == null) return null; |
| 1192 return commentToHtml(comment); | 1279 return createDocComment(comment, inheritedFrom); |
| 1193 } | 1280 } |
| 1194 | 1281 |
| 1195 /** Get the doc comment associated with the given field. */ | |
| 1196 String getFieldComment(FieldMirror field) { | |
| 1197 String comment = _comments.find(field.location); | |
| 1198 if (comment == null) return null; | |
| 1199 return commentToHtml(comment); | |
| 1200 } | |
| 1201 | |
| 1202 String commentToHtml(String comment) => md.markdownToHtml(comment); | |
| 1203 | |
| 1204 /** | 1282 /** |
| 1205 * Converts [fullPath] which is understood to be a full path from the root of | 1283 * Converts [fullPath] which is understood to be a full path from the root of |
| 1206 * the generated docs to one relative to the current file. | 1284 * the generated docs to one relative to the current file. |
| 1207 */ | 1285 */ |
| 1208 String relativePath(String fullPath) { | 1286 String relativePath(String fullPath) { |
| 1209 // Don't make it relative if it's an absolute path. | 1287 // Don't make it relative if it's an absolute path. |
| 1210 if (isAbsolute(fullPath)) return fullPath; | 1288 if (isAbsolute(fullPath)) return fullPath; |
| 1211 | 1289 |
| 1212 // TODO(rnystrom): Walks all the way up to root each time. Shouldn't do | 1290 // TODO(rnystrom): Walks all the way up to root each time. Shouldn't do |
| 1213 // this if the paths overlap. | 1291 // this if the paths overlap. |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1454 if (currentLibrary != null) { | 1532 if (currentLibrary != null) { |
| 1455 // See if it's a constructor | 1533 // See if it's a constructor |
| 1456 final constructorLink = (() { | 1534 final constructorLink = (() { |
| 1457 final match = | 1535 final match = |
| 1458 new RegExp(r'new ([\w$]+)(?:\.([\w$]+))?').firstMatch(name); | 1536 new RegExp(r'new ([\w$]+)(?:\.([\w$]+))?').firstMatch(name); |
| 1459 if (match == null) return; | 1537 if (match == null) return; |
| 1460 String typeName = match[1]; | 1538 String typeName = match[1]; |
| 1461 InterfaceMirror foundtype = currentLibrary.types[typeName]; | 1539 InterfaceMirror foundtype = currentLibrary.types[typeName]; |
| 1462 if (foundtype == null) return; | 1540 if (foundtype == null) return; |
| 1463 String constructorName = | 1541 String constructorName = |
| 1464 match[2] == null ? typeName : '$typeName.${match[2]}'; | 1542 (match[2] == null) ? typeName : '$typeName.${match[2]}'; |
| 1465 final constructor = | 1543 final constructor = |
| 1466 foundtype.constructors[constructorName]; | 1544 foundtype.constructors[constructorName]; |
| 1467 if (constructor == null) return; | 1545 if (constructor == null) return; |
| 1468 return makeLink(memberUrl(constructor)); | 1546 return makeLink(memberUrl(constructor)); |
| 1469 })(); | 1547 })(); |
| 1470 if (constructorLink != null) return constructorLink; | 1548 if (constructorLink != null) return constructorLink; |
| 1471 | 1549 |
| 1472 // See if it's a member of another type | 1550 // See if it's a member of another type |
| 1473 final foreignMemberLink = (() { | 1551 final foreignMemberLink = (() { |
| 1474 final match = new RegExp(r'([\w$]+)\.([\w$]+)').firstMatch(name); | 1552 final match = new RegExp(r'([\w$]+)\.([\w$]+)').firstMatch(name); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1544 | 1622 |
| 1545 /** | 1623 /** |
| 1546 * Used to report an unexpected error in the DartDoc tool or the | 1624 * Used to report an unexpected error in the DartDoc tool or the |
| 1547 * underlying data | 1625 * underlying data |
| 1548 */ | 1626 */ |
| 1549 class InternalError { | 1627 class InternalError { |
| 1550 final String message; | 1628 final String message; |
| 1551 const InternalError(this.message); | 1629 const InternalError(this.message); |
| 1552 String toString() => "InternalError: '$message'"; | 1630 String toString() => "InternalError: '$message'"; |
| 1553 } | 1631 } |
| 1632 |
| 1633 class DocComment { |
| 1634 final String text; |
| 1635 |
| 1636 /** |
| 1637 * Non-null if the comment is inherited from another declaration. |
| 1638 */ |
| 1639 final InterfaceMirror inheritedFrom; |
| 1640 |
| 1641 DocComment(this.text, [this.inheritedFrom = null]) { |
| 1642 assert(text != null && !text.trim().isEmpty()); |
| 1643 } |
| 1644 |
| 1645 String get html => md.markdownToHtml(text); |
| 1646 |
| 1647 String toString() => text; |
| 1648 } |
| OLD | NEW |