Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(359)

Side by Side Diff: utils/apidoc/apidoc.dart

Issue 10985085: Members and comments inherited in dartdoc. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 }); 147 });
148 }; 148 };
149 } 149 }
150 150
151 /** 151 /**
152 * This class is purely here to scrape handwritten HTML documentation. 152 * This class is purely here to scrape handwritten HTML documentation.
153 * This scraped documentation will later be merged with the generated 153 * This scraped documentation will later be merged with the generated
154 * HTML library. 154 * HTML library.
155 */ 155 */
156 class Htmldoc extends doc.Dartdoc { 156 class Htmldoc extends doc.Dartdoc {
157 String libraryComment; 157 doc.DocComment libraryComment;
158 158
159 /** 159 /**
160 * Map from qualified type names to comments. 160 * Map from qualified type names to comments.
161 */ 161 */
162 Map<String, String> typeComments; 162 Map<String, doc.DocComment> typeComments;
163 163
164 /** 164 /**
165 * Map from qualified member names to comments. 165 * Map from qualified member names to comments.
166 */ 166 */
167 Map<String, String> memberComments; 167 Map<String, doc.DocComment> memberComments;
168 168
169 Htmldoc() { 169 Htmldoc() {
170 typeComments = new Map<String, String>(); 170 typeComments = new Map<String, doc.DocComment>();
171 memberComments = new Map<String, String>(); 171 memberComments = new Map<String, doc.DocComment>();
172 } 172 }
173 173
174 // Suppress any actual writing to file. This is only for analysis. 174 // Suppress any actual writing to file. This is only for analysis.
175 void endFile() { 175 void endFile() {
176 } 176 }
177 177
178 void write(String s) { 178 void write(String s) {
179 } 179 }
180 180
181 String getRecordedLibraryComment(LibraryMirror library) { 181 doc.DocComment getRecordedLibraryComment(LibraryMirror library) {
182 if (library.simpleName == HTML_LIBRARY_NAME) { 182 if (library.simpleName == HTML_LIBRARY_NAME) {
183 return libraryComment; 183 return libraryComment;
184 } 184 }
185 return null; 185 return null;
186 } 186 }
187 187
188 String getRecordedTypeComment(TypeMirror type) { 188 doc.DocComment getRecordedTypeComment(TypeMirror type) {
189 if (typeComments.containsKey(type.qualifiedName)) { 189 if (typeComments.containsKey(type.qualifiedName)) {
190 return typeComments[type.qualifiedName]; 190 return typeComments[type.qualifiedName];
191 } 191 }
192 return null; 192 return null;
193 } 193 }
194 194
195 String getRecordedMemberComment(MemberMirror member) { 195 doc.DocComment getRecordedMemberComment(MemberMirror member) {
196 if (memberComments.containsKey(member.qualifiedName)) { 196 if (memberComments.containsKey(member.qualifiedName)) {
197 return memberComments[member.qualifiedName]; 197 return memberComments[member.qualifiedName];
198 } 198 }
199 return null; 199 return null;
200 } 200 }
201 201
202 // These methods are subclassed and used for internal processing. 202 // These methods are subclassed and used for internal processing.
203 // Do not invoke outside of this class. 203 // Do not invoke outside of this class.
204 String getLibraryComment(LibraryMirror library) { 204 doc.DocComment getLibraryComment(LibraryMirror library) {
205 String comment = super.getLibraryComment(library); 205 doc.DocComment comment = super.getLibraryComment(library);
206 libraryComment = comment; 206 libraryComment = comment;
207 return comment; 207 return comment;
208 } 208 }
209 209
210 String getTypeComment(TypeMirror type) { 210 doc.DocComment getTypeComment(TypeMirror type) {
211 String comment = super.getTypeComment(type); 211 doc.DocComment comment = super.getTypeComment(type);
212 recordTypeComment(type, comment); 212 recordTypeComment(type, comment);
213 return comment; 213 return comment;
214 } 214 }
215 215
216 String getMethodComment(MethodMirror method) { 216 doc.DocComment getMemberComment(MemberMirror member) {
217 String comment = super.getMethodComment(method); 217 doc.DocComment comment = super.getMemberComment(member);
218 recordMemberComment(method, comment); 218 recordMemberComment(member, comment);
219 return comment; 219 return comment;
220 } 220 }
221 221
222 String getFieldComment(FieldMirror field) { 222 void recordTypeComment(TypeMirror type, doc.DocComment comment) {
223 String comment = super.getFieldComment(field); 223 if (comment != null && comment.text.contains('@domName')) {
224 recordMemberComment(field, comment);
225 return comment;
226 }
227
228 void recordTypeComment(TypeMirror type, String comment) {
229 if (comment != null && comment.contains('@domName')) {
230 // This is not a handwritten comment. 224 // This is not a handwritten comment.
231 return; 225 return;
232 } 226 }
233 typeComments[type.qualifiedName] = comment; 227 typeComments[type.qualifiedName] = comment;
234 } 228 }
235 229
236 void recordMemberComment(MemberMirror member, String comment) { 230 void recordMemberComment(MemberMirror member, doc.DocComment comment) {
237 if (comment != null && comment.contains('@domName')) { 231 if (comment != null && comment.text.contains('@domName')) {
238 // This is not a handwritten comment. 232 // This is not a handwritten comment.
239 return; 233 return;
240 } 234 }
241 memberComments[member.qualifiedName] = comment; 235 memberComments[member.qualifiedName] = comment;
242 } 236 }
243 } 237 }
244 238
245 class Apidoc extends doc.Dartdoc { 239 class Apidoc extends doc.Dartdoc {
246 /** Big ball of JSON containing the scraped MDN documentation. */ 240 /** Big ball of JSON containing the scraped MDN documentation. */
247 final Map mdn; 241 final Map mdn;
248 242
249 final Htmldoc htmldoc; 243 final Htmldoc htmldoc;
250 244
251 static const disqusShortname = 'dartapidocs'; 245 static const disqusShortname = 'dartapidocs';
252 246
253 // A set of type names (TypeMirror.simpleName values) to ignore while 247 // A set of type names (TypeMirror.simpleName values) to ignore while
254 // looking up information from MDN data. TODO(eub, jacobr): fix up the MDN 248 // looking up information from MDN data. TODO(eub, jacobr): fix up the MDN
255 // import scripts so they run correctly and generate data that doesn't have 249 // import scripts so they run correctly and generate data that doesn't have
256 // any entries that need to be ignored. 250 // any entries that need to be ignored.
257 static Set<String> _mdnTypeNamesToSkip = null; 251 static Set<String> _mdnTypeNamesToSkip = null;
258 252
259 /** 253 /**
260 * The URL to the page on MDN that content was pulled from for the current 254 * The URL to the page on MDN that content was pulled from for the current
261 * type being documented. Will be `null` if the type doesn't use any MDN 255 * type being documented. Will be `null` if the type doesn't use any MDN
262 * content. 256 * content.
263 */ 257 */
264 String mdnUrl; 258 String mdnUrl = null;
265 259
266 Apidoc(this.mdn, this.htmldoc, Path outputDir, int mode, 260 Apidoc(this.mdn, this.htmldoc, Path outputDir, int mode,
267 bool generateAppCache) { 261 bool generateAppCache) {
268 this.outputDir = outputDir; 262 this.outputDir = outputDir;
269 this.mode = mode; 263 this.mode = mode;
270 this.generateAppCache = generateAppCache; 264 this.generateAppCache = generateAppCache;
271 265
272 // Skip bad entries in the checked-in mdn/database.json: 266 // Skip bad entries in the checked-in mdn/database.json:
273 // * UnknownElement has a top-level Gecko DOM page in German. 267 // * UnknownElement has a top-level Gecko DOM page in German.
274 if (_mdnTypeNamesToSkip == null) 268 if (_mdnTypeNamesToSkip == null)
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 } 363 }
370 364
371 void docLibrary(LibraryMirror library) { 365 void docLibrary(LibraryMirror library) {
372 // TODO(rnystrom): Hackish. The IO libraries reference this but we don't 366 // TODO(rnystrom): Hackish. The IO libraries reference this but we don't
373 // want it in the docs. 367 // want it in the docs.
374 if (library.simpleName == 'dart:nativewrappers') return; 368 if (library.simpleName == 'dart:nativewrappers') return;
375 super.docLibrary(library); 369 super.docLibrary(library);
376 } 370 }
377 371
378 /** Override definition from parent class to strip out annotation tags. */ 372 /** Override definition from parent class to strip out annotation tags. */
379 String commentToHtml(String comment) { 373 doc.DocComment createDocComment(String text,
380 return super.commentToHtml( 374 [InterfaceMirror inheritedFrom]) {
381 comment.replaceAll(const RegExp("@([a-zA-Z]+) ([^;]+)(?:;|\$)"), '')); 375 String strippedText =
376 text.replaceAll(const RegExp("@([a-zA-Z]+) ([^;]+)(?:;|\$)"),
377 '').trim();
378 if (strippedText.isEmpty()) return null;
379 return super.createDocComment(strippedText, inheritedFrom);
382 } 380 }
383 381
384 String getLibraryComment(LibraryMirror library) { 382 doc.DocComment getLibraryComment(LibraryMirror library) {
385 if (library.simpleName == HTML_LIBRARY_NAME) { 383 if (library.simpleName == HTML_LIBRARY_NAME) {
386 return htmldoc.libraryComment; 384 return htmldoc.libraryComment;
387 } 385 }
388 return super.getLibraryComment(library); 386 return super.getLibraryComment(library);
389 } 387 }
390 388
391 String getTypeComment(TypeMirror type) { 389 doc.DocComment getTypeComment(TypeMirror type) {
392 return _mergeDocs( 390 return _mergeDocs(
393 includeMdnTypeComment(type), super.getTypeComment(type), 391 includeMdnTypeComment(type), super.getTypeComment(type),
394 htmldoc.getRecordedTypeComment(type)); 392 htmldoc.getRecordedTypeComment(type));
395 } 393 }
396 394
397 String getMethodComment(MethodMirror method) { 395 doc.DocComment getMemberComment(MemberMirror member) {
398 return _mergeDocs( 396 return _mergeDocs(
399 includeMdnMemberComment(method), super.getMethodComment(method), 397 includeMdnMemberComment(member), super.getMemberComment(member),
400 htmldoc.getRecordedMemberComment(method)); 398 htmldoc.getRecordedMemberComment(member));
401 } 399 }
402 400
403 String getFieldComment(FieldMirror field) { 401 doc.DocComment _mergeDocs(MdnComment mdnComment,
404 return _mergeDocs( 402 doc.DocComment fileComment,
405 includeMdnMemberComment(field), super.getFieldComment(field), 403 doc.DocComment handWrittenComment) {
406 htmldoc.getRecordedMemberComment(field)); 404 // Prefer the hand-written comment first.
407 } 405 if (handWrittenComment !== null) return handWrittenComment;
408 406
409 bool isNonEmpty(String string) => (string != null) && (string.trim() != ''); 407 // Otherwise, prefer comment from the (possibly generated) Dart file.
410 408 if (fileComment !== null) return fileComment;
411 String _mergeDocs(String mdnComment, String fileComment,
412 String handWrittenComment) {
413 // Prefer the hand-written comment first.
414 if (isNonEmpty(handWrittenComment)) return handWrittenComment;
415
416 // Otherwise, prefer comment from the (possibly generated) Dart
417 // file.
418 if (isNonEmpty(fileComment)) return fileComment;
419 409
420 // Finally, fallback on MDN if available. 410 // Finally, fallback on MDN if available.
421 if (isNonEmpty(mdnComment)) { 411 if (mdnComment !== null) {
422 // Wrap it so we can highlight it and so we handle MDN scraped content 412 mdnUrl = mdnComment.mdnUrl;
423 // that lacks a top-level block tag. 413 return mdnComment;
424 return '''
425 <div class="mdn">
426 $mdnComment
427 <div class="mdn-note"><a href="$mdnUrl">from MDN</a></div>
428 </div>
429 ''';
430 } 414 }
431 415
432 // We got nothing! 416 // We got nothing!
433 return ''; 417 return null;
434 } 418 }
435 419
436 void docType(TypeMirror type) { 420 void docType(TypeMirror type) {
437 // Track whether we've inserted MDN content into this page. 421 // Track whether we've inserted MDN content into this page.
438 mdnUrl = null; 422 mdnUrl = null;
439 423
440 super.docType(type); 424 super.docType(type);
441 } 425 }
442 426
443 void writeTypeFooter() { 427 void writeTypeFooter() {
(...skipping 18 matching lines...) Expand all
462 <a href="$MDN">The Mozilla Developer Network</a>. 446 <a href="$MDN">The Mozilla Developer Network</a>.
463 </p> 447 </p>
464 '''); 448 ''');
465 } 449 }
466 } 450 }
467 451
468 /** 452 /**
469 * Gets the MDN-scraped docs for [type], or `null` if this type isn't 453 * Gets the MDN-scraped docs for [type], or `null` if this type isn't
470 * scraped from MDN. 454 * scraped from MDN.
471 */ 455 */
472 includeMdnTypeComment(TypeMirror type) { 456 MdnComment includeMdnTypeComment(TypeMirror type) {
473 if (_mdnTypeNamesToSkip.contains(type.simpleName)) { 457 if (_mdnTypeNamesToSkip.contains(type.simpleName)) {
474 print('Skipping MDN type ${type.simpleName}'); 458 print('Skipping MDN type ${type.simpleName}');
475 return null; 459 return null;
476 } 460 }
477 461
478 var typeString = ''; 462 var typeString = '';
479 if (type.library.simpleName == HTML_LIBRARY_NAME) { 463 if (type.library.simpleName == HTML_LIBRARY_NAME) {
480 // If it's an HTML type, try to map it to a base DOM type so we can find 464 // If it's an HTML type, try to map it to a base DOM type so we can find
481 // the MDN docs. 465 // the MDN docs.
482 final domTypes = _diff.htmlTypesToDom[type.qualifiedName]; 466 final domTypes = _diff.htmlTypesToDom[type.qualifiedName];
483 467
484 // Couldn't find a DOM type. 468 // Couldn't find a DOM type.
485 if ((domTypes == null) || (domTypes.length != 1)) return null; 469 if ((domTypes == null) || (domTypes.length != 1)) return null;
486 470
487 // Use the corresponding DOM type when searching MDN. 471 // Use the corresponding DOM type when searching MDN.
488 // TODO(rnystrom): Shame there isn't a simpler way to get the one item 472 // TODO(rnystrom): Shame there isn't a simpler way to get the one item
489 // out of a singleton Set. 473 // out of a singleton Set.
490 typeString = domTypes.iterator().next(); 474 typeString = domTypes.iterator().next();
491 } else { 475 } else {
492 // Not a DOM type. 476 // Not a DOM type.
493 return null; 477 return null;
494 } 478 }
495 479
496 final mdnType = mdn[typeString]; 480 final mdnType = mdn[typeString];
497 if (mdnType == null) return null; 481 if (mdnType == null) return null;
498 if (mdnType['skipped'] != null) return null; 482 if (mdnType['skipped'] != null) return null;
483 if (mdnType['summary'] == null) return null;
484 if (mdnType['summary'].trim().isEmpty()) return null;
499 485
500 // Remember which MDN page we're using so we can attribute it. 486 // Remember which MDN page we're using so we can attribute it.
501 mdnUrl = mdnType['srcUrl']; 487 return new MdnComment(mdnType['summary'], mdnType['srcUrl']);
502 return mdnType['summary'];
503 } 488 }
504 489
505 /** 490 /**
506 * Gets the MDN-scraped docs for [member], or `null` if this type isn't 491 * Gets the MDN-scraped docs for [member], or `null` if this type isn't
507 * scraped from MDN. 492 * scraped from MDN.
508 */ 493 */
509 includeMdnMemberComment(MemberMirror member) { 494 MdnComment includeMdnMemberComment(MemberMirror member) {
510 var library = findLibrary(member); 495 var library = findLibrary(member);
511 var memberString = ''; 496 var memberString = '';
512 if (library.simpleName == HTML_LIBRARY_NAME) { 497 if (library.simpleName == HTML_LIBRARY_NAME) {
513 // If it's an HTML type, try to map it to a DOM type name so we can find 498 // If it's an HTML type, try to map it to a DOM type name so we can find
514 // the MDN docs. 499 // the MDN docs.
515 final domMembers = _diff.htmlToDom[member.qualifiedName]; 500 final domMembers = _diff.htmlToDom[member.qualifiedName];
516 501
517 // Couldn't find a DOM type. 502 // Couldn't find a DOM type.
518 if ((domMembers == null) || (domMembers.length != 1)) return null; 503 if ((domMembers == null) || (domMembers.length != 1)) return null;
519 504
(...skipping 18 matching lines...) Expand all
538 var nameToFind = pieces[1]; 523 var nameToFind = pieces[1];
539 for (final candidateMember in mdnType['members']) { 524 for (final candidateMember in mdnType['members']) {
540 if (candidateMember['name'] == nameToFind) { 525 if (candidateMember['name'] == nameToFind) {
541 mdnMember = candidateMember; 526 mdnMember = candidateMember;
542 break; 527 break;
543 } 528 }
544 } 529 }
545 } 530 }
546 531
547 if (mdnMember == null) return null; 532 if (mdnMember == null) return null;
533 if (mdnMember['help'] == null) return null;
534 if (mdnMember['help'].trim().isEmpty()) return null;
548 535
549 // Remember which MDN page we're using so we can attribute it. 536 // Remember which MDN page we're using so we can attribute it.
550 mdnUrl = mdnType['srcUrl']; 537 return new MdnComment(mdnMember['help'], mdnType['srcUrl']);
551 return mdnMember['help'];
552 } 538 }
553 539
554 /** 540 /**
555 * Returns a link to [member], relative to a type page that may be in a 541 * Returns a link to [member], relative to a type page that may be in a
556 * different library than [member]. 542 * different library than [member].
557 */ 543 */
558 String _linkMember(MemberMirror member) { 544 String _linkMember(MemberMirror member) {
559 final typeName = member.surroundingDeclaration.simpleName; 545 final typeName = member.surroundingDeclaration.simpleName;
560 var memberName = '$typeName.${member.simpleName}'; 546 var memberName = '$typeName.${member.simpleName}';
561 if (member is MethodMirror && (member.isConstructor || member.isFactory)) { 547 if (member is MethodMirror && (member.isConstructor || member.isFactory)) {
562 final separator = member.constructorName == '' ? '' : '.'; 548 final separator = member.constructorName == '' ? '' : '.';
563 memberName = 'new $typeName$separator${member.constructorName}'; 549 memberName = 'new $typeName$separator${member.constructorName}';
564 } 550 }
565 551
566 return a(memberUrl(member), memberName); 552 return a(memberUrl(member), memberName);
567 } 553 }
568 } 554 }
555
556 class MdnComment implements doc.DocComment {
557 final String mdnComment;
558 final String mdnUrl;
559
560 MdnComment(String this.mdnComment, String this.mdnUrl);
561
562 String get text => mdnComment;
563
564 InterfaceMirror get inheritedFrom => null;
565
566 String get html {
567 // Wrap the mdn comment so we can highlight it and so we handle MDN scraped
568 // content that lacks a top-level block tag.
569 return '''
570 <div class="mdn">
571 $mdnComment
572 <div class="mdn-note"><a href="$mdnUrl">from MDN</a></div>
573 </div>
574 ''';
575 }
576
577 String toString() => mdnComment;
578 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698