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 * This generates the reference documentation for the core libraries that come | 6 * This generates the reference documentation for the core libraries that come |
7 * with dart. It is built on top of dartdoc, which is a general-purpose library | 7 * with dart. It is built on top of dartdoc, which is a general-purpose library |
8 * for generating docs from any Dart code. This library extends that to include | 8 * for generating docs from any Dart code. This library extends that to include |
9 * additional information and styling specific to our standard library. | 9 * additional information and styling specific to our standard library. |
10 * | 10 * |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 initializeWorld(files); | 97 initializeWorld(files); |
98 | 98 |
99 print('Parsing MDN data...'); | 99 print('Parsing MDN data...'); |
100 final mdnFile = new File('${doc.scriptDir}/mdn/database.json'); | 100 final mdnFile = new File('${doc.scriptDir}/mdn/database.json'); |
101 final mdn = JSON.parse(mdnFile.readAsTextSync()); | 101 final mdn = JSON.parse(mdnFile.readAsTextSync()); |
102 | 102 |
103 print('Cross-referencing dart:html...'); | 103 print('Cross-referencing dart:html...'); |
104 HtmlDiff.initialize(); | 104 HtmlDiff.initialize(); |
105 _diff = new HtmlDiff(printWarnings:false); | 105 _diff = new HtmlDiff(printWarnings:false); |
106 _diff.run(); | 106 _diff.run(); |
| 107 |
| 108 // Process handwritten HTML documentation. |
| 109 world.reset(); |
| 110 world.getOrAddLibrary('${doc.scriptDir}/../../lib/html/doc/html.dartdoc'); |
| 111 world.process(); |
| 112 final htmldoc = new Htmldoc(); |
| 113 htmldoc.document(); |
| 114 print('Processing handwritten HTML documentation...'); |
| 115 |
| 116 // Process libraries. |
| 117 |
| 118 // Note, Frog has global internal state. We need to clear away the |
| 119 // HTML documentation classes above first. |
107 world.reset(); | 120 world.reset(); |
108 | 121 |
109 // Add all of the core libraries. | 122 // Add all of the core libraries. |
110 world.getOrAddLibrary('dart:core'); | 123 world.getOrAddLibrary('dart:core'); |
111 world.getOrAddLibrary('dart:coreimpl'); | 124 world.getOrAddLibrary('dart:coreimpl'); |
112 world.getOrAddLibrary('dart:crypto'); | 125 world.getOrAddLibrary('dart:crypto'); |
113 world.getOrAddLibrary('dart:html'); | 126 world.getOrAddLibrary('dart:html'); |
114 world.getOrAddLibrary('dart:io'); | 127 world.getOrAddLibrary('dart:io'); |
115 world.getOrAddLibrary('dart:isolate'); | 128 world.getOrAddLibrary('dart:isolate'); |
116 world.getOrAddLibrary('dart:json'); | 129 world.getOrAddLibrary('dart:json'); |
117 world.getOrAddLibrary('${doc.scriptDir}/../../lib/math/math.dart'); | 130 world.getOrAddLibrary('${doc.scriptDir}/../../lib/math/math.dart'); |
118 world.getOrAddLibrary('${doc.scriptDir}/../../lib/unittest/unittest.dart'); | 131 world.getOrAddLibrary('${doc.scriptDir}/../../lib/unittest/unittest.dart'); |
119 world.getOrAddLibrary('dart:uri'); | 132 world.getOrAddLibrary('dart:uri'); |
120 world.getOrAddLibrary('dart:utf'); | 133 world.getOrAddLibrary('dart:utf'); |
121 world.process(); | 134 world.process(); |
122 | 135 |
123 print('Generating docs...'); | 136 print('Generating docs...'); |
124 final apidoc = new Apidoc(mdn, outputDir, mode, generateAppCache); | 137 final apidoc = new Apidoc(mdn, htmldoc, outputDir, mode, generateAppCache); |
125 | 138 |
126 Futures.wait([scriptCompiled, copiedStatic, copiedApiDocStatic]).then((_) { | 139 Futures.wait([scriptCompiled, copiedStatic, copiedApiDocStatic]).then((_) { |
127 apidoc.document(); | 140 apidoc.document(); |
128 }); | 141 }); |
129 } | 142 } |
130 | 143 |
| 144 /** |
| 145 * This class is purely here to scrape handwritten HTML documentation. |
| 146 * This scraped documentation will later be merged with the generated |
| 147 * HTML library. |
| 148 */ |
| 149 class Htmldoc extends doc.Dartdoc { |
| 150 String libraryComment; |
| 151 Map<String, String> typeComments; |
| 152 Map<String, Map<String, String>> memberComments; |
| 153 |
| 154 Htmldoc() { |
| 155 typeComments = new Map<String, String>(); |
| 156 memberComments = new Map<String, Map<String, String>>(); |
| 157 } |
| 158 |
| 159 // Suppress any actual writing to file. This is only for analysis. |
| 160 void endFile() { |
| 161 } |
| 162 |
| 163 void write(String s) { |
| 164 } |
| 165 |
| 166 String getRecordedLibraryComment(Library library) { |
| 167 if (library.name == 'html') { |
| 168 return libraryComment; |
| 169 } |
| 170 return null; |
| 171 } |
| 172 |
| 173 String getRecordedTypeComment(Type type) { |
| 174 if (type.library.name == 'html') { |
| 175 if (typeComments.containsKey(type.name)) { |
| 176 return typeComments[type.name]; |
| 177 } |
| 178 } |
| 179 return null; |
| 180 } |
| 181 |
| 182 String getRecordedMemberComment(Member member) { |
| 183 if (member.library.name == 'html') { |
| 184 String typeName; |
| 185 if (member.declaringType != null) { |
| 186 typeName = member.declaringType.name; |
| 187 } |
| 188 if (typeName == null) { |
| 189 typeName = ''; |
| 190 } |
| 191 if (memberComments.containsKey(typeName)) { |
| 192 Map<String, String> memberMap = memberComments[typeName]; |
| 193 if (memberMap.containsKey(member.name)) { |
| 194 return memberMap[member.name]; |
| 195 } |
| 196 } |
| 197 } |
| 198 return null; |
| 199 } |
| 200 |
| 201 // These methods are subclassed and used for internal processing. |
| 202 // Do not invoke outside of this class. |
| 203 String getLibraryComment(Library library) { |
| 204 String comment = super.getLibraryComment(library); |
| 205 libraryComment = comment; |
| 206 return comment; |
| 207 } |
| 208 |
| 209 String getTypeComment(Type type) { |
| 210 String comment = super.getTypeComment(type); |
| 211 recordTypeComment(type, comment); |
| 212 return comment; |
| 213 } |
| 214 |
| 215 String getMethodComment(MethodMember method) { |
| 216 String comment = super.getMethodComment(method); |
| 217 recordMemberComment(method, comment); |
| 218 return comment; |
| 219 } |
| 220 |
| 221 String getFieldComment(FieldMember field) { |
| 222 String comment = super.getFieldComment(field); |
| 223 recordMemberComment(field, comment); |
| 224 return comment; |
| 225 } |
| 226 |
| 227 void recordTypeComment(Type type, String comment) { |
| 228 if (comment != null && comment.contains('@domName')) { |
| 229 // This is not a handwritten comment. |
| 230 return; |
| 231 } |
| 232 typeComments[type.name] = comment; |
| 233 } |
| 234 |
| 235 void recordMemberComment(Member member, String comment) { |
| 236 if (comment != null && comment.contains('@domName')) { |
| 237 // This is not a handwritten comment. |
| 238 return; |
| 239 } |
| 240 String typeName = member.declaringType.name; |
| 241 if (typeName == null) |
| 242 typeName = ''; |
| 243 if (!memberComments.containsKey(typeName)) { |
| 244 memberComments[typeName] = new Map<String, String>(); |
| 245 } |
| 246 Map<String, String> memberMap = memberComments[typeName]; |
| 247 memberMap[member.name] = comment; |
| 248 } |
| 249 } |
| 250 |
131 class Apidoc extends doc.Dartdoc { | 251 class Apidoc extends doc.Dartdoc { |
132 /** Big ball of JSON containing the scraped MDN documentation. */ | 252 /** Big ball of JSON containing the scraped MDN documentation. */ |
133 final Map mdn; | 253 final Map mdn; |
134 | 254 |
| 255 final Htmldoc htmldoc; |
| 256 |
135 static final disqusShortname = 'dartapidocs'; | 257 static final disqusShortname = 'dartapidocs'; |
136 | 258 |
137 /** | 259 /** |
138 * The URL to the page on MDN that content was pulled from for the current | 260 * The URL to the page on MDN that content was pulled from for the current |
139 * type being documented. Will be `null` if the type doesn't use any MDN | 261 * type being documented. Will be `null` if the type doesn't use any MDN |
140 * content. | 262 * content. |
141 */ | 263 */ |
142 String mdnUrl; | 264 String mdnUrl; |
143 | 265 |
144 Apidoc(this.mdn, String outputDir, int mode, bool generateAppCache) { | 266 Apidoc(this.mdn, this.htmldoc, String outputDir, int mode, |
| 267 bool generateAppCache) { |
145 this.outputDir = outputDir; | 268 this.outputDir = outputDir; |
146 this.mode = mode; | 269 this.mode = mode; |
147 this.generateAppCache = generateAppCache; | 270 this.generateAppCache = generateAppCache; |
148 | 271 |
149 mainTitle = 'Dart API Reference'; | 272 mainTitle = 'Dart API Reference'; |
150 mainUrl = 'http://dartlang.org'; | 273 mainUrl = 'http://dartlang.org'; |
151 | 274 |
152 final note = 'http://code.google.com/policies.html#restrictions'; | 275 final note = 'http://code.google.com/policies.html#restrictions'; |
153 final cca = 'http://creativecommons.org/licenses/by/3.0/'; | 276 final cca = 'http://creativecommons.org/licenses/by/3.0/'; |
154 final bsd = 'http://code.google.com/google_bsd_license.html'; | 277 final bsd = 'http://code.google.com/google_bsd_license.html'; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 if (library.name == 'dart:nativewrappers') return; | 369 if (library.name == 'dart:nativewrappers') return; |
247 super.docLibrary(library); | 370 super.docLibrary(library); |
248 } | 371 } |
249 | 372 |
250 /** Override definition from parent class to strip out annotation tags. */ | 373 /** Override definition from parent class to strip out annotation tags. */ |
251 String commentToHtml(String comment) { | 374 String commentToHtml(String comment) { |
252 return super.commentToHtml( | 375 return super.commentToHtml( |
253 comment.replaceAll(const RegExp("@([a-zA-Z]+) ([^;]+)(?:;|\$)"), '')); | 376 comment.replaceAll(const RegExp("@([a-zA-Z]+) ([^;]+)(?:;|\$)"), '')); |
254 } | 377 } |
255 | 378 |
| 379 String getLibraryComment(Library library) { |
| 380 if (library.name == 'html') { |
| 381 return htmldoc.libraryComment; |
| 382 } |
| 383 return super.getLibraryComment(library); |
| 384 } |
| 385 |
256 String getTypeComment(Type type) { | 386 String getTypeComment(Type type) { |
257 return _mergeDocs( | 387 return _mergeDocs( |
258 includeMdnTypeComment(type), super.getTypeComment(type)); | 388 includeMdnTypeComment(type), super.getTypeComment(type), |
| 389 htmldoc.getRecordedTypeComment(type)); |
259 } | 390 } |
260 | 391 |
261 String getMethodComment(MethodMember method) { | 392 String getMethodComment(MethodMember method) { |
262 return _mergeDocs( | 393 return _mergeDocs( |
263 includeMdnMemberComment(method), super.getMethodComment(method)); | 394 includeMdnMemberComment(method), super.getMethodComment(method), |
| 395 htmldoc.getRecordedMemberComment(method)); |
264 } | 396 } |
265 | 397 |
266 String getFieldComment(FieldMember field) { | 398 String getFieldComment(FieldMember field) { |
267 return _mergeDocs( | 399 return _mergeDocs( |
268 includeMdnMemberComment(field), super.getFieldComment(field)); | 400 includeMdnMemberComment(field), super.getFieldComment(field), |
| 401 htmldoc.getRecordedMemberComment(field)); |
269 } | 402 } |
270 | 403 |
271 bool isNonEmpty(String string) => (string != null) && (string.trim() != ''); | 404 bool isNonEmpty(String string) => (string != null) && (string.trim() != ''); |
272 | 405 |
273 String _mergeDocs(String mdnComment, String dartComment) { | 406 String _mergeDocs(String mdnComment, String fileComment, |
274 // Prefer hand-written Dart comments over stuff from MDN. | 407 String handWrittenComment) { |
275 if (isNonEmpty(dartComment)) return dartComment; | 408 // Prefer the hand-written comment first. |
| 409 if (isNonEmpty(handWrittenComment)) return handWrittenComment; |
276 | 410 |
| 411 // Otherwise, prefer comment from the (possibly generated) Dart |
| 412 // file. |
| 413 if (isNonEmpty(fileComment)) return fileComment; |
| 414 |
| 415 // Finally, fallback on MDN if available. |
277 if (isNonEmpty(mdnComment)) { | 416 if (isNonEmpty(mdnComment)) { |
278 // Wrap it so we can highlight it and so we handle MDN scraped content | 417 // Wrap it so we can highlight it and so we handle MDN scraped content |
279 // that lacks a top-level block tag. | 418 // that lacks a top-level block tag. |
280 return ''' | 419 return ''' |
281 <div class="mdn"> | 420 <div class="mdn"> |
282 $mdnComment | 421 $mdnComment |
283 <div class="mdn-note"><a href="$mdnUrl">from MDN</a></div> | 422 <div class="mdn-note"><a href="$mdnUrl">from MDN</a></div> |
284 </div> | 423 </div> |
285 '''; | 424 '''; |
286 } | 425 } |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 if (member.isConstructor || member.isFactory) { | 547 if (member.isConstructor || member.isFactory) { |
409 final separator = member.constructorName == '' ? '' : '.'; | 548 final separator = member.constructorName == '' ? '' : '.'; |
410 memberName = 'new $typeName$separator${member.constructorName}'; | 549 memberName = 'new $typeName$separator${member.constructorName}'; |
411 } else if (member.name.startsWith(GET_PREFIX)) { | 550 } else if (member.name.startsWith(GET_PREFIX)) { |
412 memberName = '$typeName.${member.name.substring(GET_PREFIX.length)}'; | 551 memberName = '$typeName.${member.name.substring(GET_PREFIX.length)}'; |
413 } | 552 } |
414 | 553 |
415 return a(memberUrl(member), memberName); | 554 return a(memberUrl(member), memberName); |
416 } | 555 } |
417 } | 556 } |
OLD | NEW |