| 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 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 513 if (mdnType['summary'] == null || mdnType['summary'] == "") return ''; | 513 if (mdnType['summary'] == null || mdnType['summary'] == "") return ''; |
| 514 if (mdnType['srcUrl'] == null) return ''; | 514 if (mdnType['srcUrl'] == null) return ''; |
| 515 return _htmlMdn(mdnType['summary'], mdnType['srcUrl']); | 515 return _htmlMdn(mdnType['summary'], mdnType['srcUrl']); |
| 516 } | 516 } |
| 517 | 517 |
| 518 String _htmlMdn(String content, String url) { | 518 String _htmlMdn(String content, String url) { |
| 519 return '<div class="mdn">' + content.trim() + '<p class="mdn-note">' | 519 return '<div class="mdn">' + content.trim() + '<p class="mdn-note">' |
| 520 '<a href="' + url.trim() + '">from Mdn</a></p></div>'; | 520 '<a href="' + url.trim() + '">from Mdn</a></p></div>'; |
| 521 } | 521 } |
| 522 | 522 |
| 523 /// Look for the specified name starting with the current member, and | |
| 524 /// progressively working outward to the current library scope. | |
| 525 String findElementInScope(String name, LibraryMirror currentLibrary, | |
| 526 ClassMirror currentClass, MemberMirror currentMember) { | |
| 527 var memberScope = currentMember == null ? | |
| 528 null : currentMember.lookupInScope(name); | |
| 529 if (memberScope != null) { | |
| 530 return docName(memberScope); | |
| 531 } else { | |
| 532 var classScope = currentClass == null ? | |
| 533 null : currentClass.lookupInScope(name); | |
| 534 if (classScope != null) { | |
| 535 return docName(classScope); | |
| 536 } else { | |
| 537 var libraryScope = currentLibrary == null ? | |
| 538 null : currentLibrary.lookupInScope(name); | |
| 539 if (libraryScope != null) { | |
| 540 return docName(libraryScope); | |
| 541 } | |
| 542 } | |
| 543 } | |
| 544 return null; | |
| 545 } | |
| 546 | |
| 547 // HTML escaped version of '<' character. | |
| 548 final _LESS_THAN = '<'; | |
| 549 | |
| 550 /// Chunk the provided name into individual parts to be resolved. We take a | |
| 551 /// simplistic approach to chunking, though, we break at " ", ",", "<" | |
| 552 /// and ">". All other characters are grouped into the name to be resolved. | |
| 553 /// As a result, these characters will all be treated as part of the item to be | |
| 554 /// resolved (aka the * is interpreted literally as a *, not as an indicator for | |
| 555 /// bold <em>. | |
| 556 List<String> _tokenizeComplexReference(String name) { | |
| 557 var tokens = []; | |
| 558 var append = false; | |
| 559 var index = 0; | |
| 560 while(index < name.length) { | |
| 561 if (name.indexOf(_LESS_THAN, index) == index) { | |
| 562 tokens.add(_LESS_THAN); | |
| 563 append = false; | |
| 564 index += _LESS_THAN.length; | |
| 565 } else if (name[index] == ' ' || name[index] == ',' || | |
| 566 name[index] == '>') { | |
| 567 tokens.add(name[index]); | |
| 568 append = false; | |
| 569 index++; | |
| 570 } else { | |
| 571 if (append) { | |
| 572 tokens[tokens.length - 1] = tokens.last + name[index]; | |
| 573 } else { | |
| 574 tokens.add(name[index]); | |
| 575 append = true; | |
| 576 } | |
| 577 index++; | |
| 578 } | |
| 579 } | |
| 580 return tokens; | |
| 581 } | |
| 582 | |
| 583 /// This is a more complex reference. Try to break up if its of the form A<B> | |
| 584 /// where A is an alphanumeric string and B is an A, a list of B ("B, B, B"), | |
| 585 /// or of the form A<B>. Note: unlike other the other markdown-style links, all | |
| 586 /// text inside the square brackets is treated as part of the link (aka the * is | |
| 587 /// interpreted literally as a *, not as a indicator for bold <em>. | |
| 588 /// | |
| 589 /// Example: [foo<_bar_>] will produce | |
| 590 /// <a>resolvedFoo</a><<a>resolved_bar_</a>> rather than an italicized | |
| 591 /// version of resolvedBar. | |
| 592 markdown.Node _fixComplexReference(String name, LibraryMirror currentLibrary, | |
| 593 ClassMirror currentClass, MemberMirror currentMember) { | |
| 594 // Parse into multiple elements we can try to resolve. | |
| 595 var tokens = _tokenizeComplexReference(name); | |
| 596 | |
| 597 // Produce an html representation of our elements. Group unresolved and plain | |
| 598 // text are grouped into "link" elements so they display as code. | |
| 599 final textElements = [' ', ',', '>', _LESS_THAN]; | |
| 600 var accumulatedHtml = ''; | |
| 601 | |
| 602 for (var token in tokens) { | |
| 603 bool added = false; | |
| 604 if (!textElements.contains(token)) { | |
| 605 String elementName = findElementInScope(token, currentLibrary, | |
| 606 currentClass, currentMember); | |
| 607 if (elementName != null) { | |
| 608 accumulatedHtml += markdown.renderToHtml([new markdown.Element.text( | |
| 609 'a', elementName)]); | |
| 610 added = true; | |
| 611 } | |
| 612 } | |
| 613 if (!added) { | |
| 614 accumulatedHtml += token; | |
| 615 } | |
| 616 } | |
| 617 return new markdown.Text(accumulatedHtml); | |
| 618 } | |
| 619 | |
| 620 /// Converts all [foo] references in comments to <a>libraryName.foo</a>. | 523 /// Converts all [foo] references in comments to <a>libraryName.foo</a>. |
| 621 markdown.Node fixReference(String name, LibraryMirror currentLibrary, | 524 markdown.Node fixReference(String name, LibraryMirror currentLibrary, |
| 622 ClassMirror currentClass, MemberMirror currentMember) { | 525 ClassMirror currentClass, MemberMirror currentMember) { |
| 623 // Attempt the look up the whole name up in the scope. | 526 var reference; |
| 624 String elementName = | 527 var memberScope = currentMember == null ? |
| 625 findElementInScope(name, currentLibrary, currentClass, currentMember); | 528 null : currentMember.lookupInScope(name); |
| 626 if (elementName != null) { | 529 if (memberScope != null) { |
| 627 return new markdown.Element.text('a', elementName); | 530 reference = docName(memberScope); |
| 531 } else { |
| 532 var classScope = currentClass == null ? |
| 533 null : currentClass.lookupInScope(name); |
| 534 if (classScope != null) { |
| 535 reference = docName(classScope); |
| 536 } else { |
| 537 var libraryScope = currentLibrary == null ? |
| 538 null : currentLibrary.lookupInScope(name); |
| 539 reference = libraryScope != null ? docName(libraryScope) : name; |
| 540 } |
| 628 } | 541 } |
| 629 return _fixComplexReference(name, currentLibrary, currentClass, currentMember)
; | 542 return new markdown.Element.text('a', reference); |
| 630 } | 543 } |
| 631 | 544 |
| 632 /// Returns a map of [Variable] objects constructed from [mirrorMap]. | 545 /// Returns a map of [Variable] objects constructed from [mirrorMap]. |
| 633 Map<String, Variable> _variables(Map<String, VariableMirror> mirrorMap) { | 546 Map<String, Variable> _variables(Map<String, VariableMirror> mirrorMap) { |
| 634 var data = {}; | 547 var data = {}; |
| 635 // TODO(janicejl): When map to map feature is created, replace the below with | 548 // TODO(janicejl): When map to map feature is created, replace the below with |
| 636 // a filter. Issue(#9590). | 549 // a filter. Issue(#9590). |
| 637 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { | 550 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { |
| 638 _currentMember = mirror; | 551 _currentMember = mirror; |
| 639 if (_includePrivate || !_isHidden(mirror)) { | 552 if (_includePrivate || !_isHidden(mirror)) { |
| (...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 String docName(DeclarationMirror m) { | 1252 String docName(DeclarationMirror m) { |
| 1340 if (m is LibraryMirror) { | 1253 if (m is LibraryMirror) { |
| 1341 return (m as LibraryMirror).qualifiedName.replaceAll('.','-'); | 1254 return (m as LibraryMirror).qualifiedName.replaceAll('.','-'); |
| 1342 } | 1255 } |
| 1343 var owner = m.owner; | 1256 var owner = m.owner; |
| 1344 if (owner == null) return m.qualifiedName; | 1257 if (owner == null) return m.qualifiedName; |
| 1345 // For the unnamed constructor we just return the class name. | 1258 // For the unnamed constructor we just return the class name. |
| 1346 if (m.simpleName == '') return docName(owner); | 1259 if (m.simpleName == '') return docName(owner); |
| 1347 return docName(owner) + '.' + m.simpleName; | 1260 return docName(owner) + '.' + m.simpleName; |
| 1348 } | 1261 } |
| OLD | NEW |