Chromium Code Reviews| 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 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 502 if (mdnType['summary'] == null || mdnType['summary'] == "") return ''; | 502 if (mdnType['summary'] == null || mdnType['summary'] == "") return ''; |
| 503 if (mdnType['srcUrl'] == null) return ''; | 503 if (mdnType['srcUrl'] == null) return ''; |
| 504 return _htmlMdn(mdnType['summary'], mdnType['srcUrl']); | 504 return _htmlMdn(mdnType['summary'], mdnType['srcUrl']); |
| 505 } | 505 } |
| 506 | 506 |
| 507 String _htmlMdn(String content, String url) { | 507 String _htmlMdn(String content, String url) { |
| 508 return '<div class="mdn">' + content.trim() + '<p class="mdn-note">' | 508 return '<div class="mdn">' + content.trim() + '<p class="mdn-note">' |
| 509 '<a href="' + url.trim() + '">from Mdn</a></p></div>'; | 509 '<a href="' + url.trim() + '">from Mdn</a></p></div>'; |
| 510 } | 510 } |
| 511 | 511 |
| 512 /// Look for the specified name starting with the current member, and | |
| 513 /// progressively working outward to the current library scope. | |
| 514 String findElementInScope(String name, LibraryMirror currentLibrary, | |
| 515 ClassMirror currentClass, MemberMirror currentMember) { | |
| 516 var memberScope = currentMember == null ? | |
| 517 null : currentMember.lookupInScope(name); | |
| 518 if (memberScope != null) { | |
| 519 return docName(memberScope); | |
| 520 } else { | |
| 521 var classScope = currentClass == null ? | |
| 522 null : currentClass.lookupInScope(name); | |
| 523 if (classScope != null) { | |
| 524 return docName(classScope); | |
| 525 } else { | |
| 526 var libraryScope = currentLibrary == null ? | |
| 527 null : currentLibrary.lookupInScope(name); | |
| 528 if (libraryScope != null) { | |
| 529 return docName(libraryScope); | |
| 530 } | |
| 531 } | |
| 532 } | |
| 533 return null; | |
| 534 } | |
| 535 | |
| 536 // HTML escaped version of '<' character. | |
| 537 final _LESS_THAN = '<'; | |
| 538 | |
| 539 /// Chunk the provided name into individual parts to be resolved. We take a | |
| 540 /// simplistic approach to chunking, though, we break at " ", ",", "<" | |
| 541 /// and ">". All other characters are grouped into the name to be resolved. | |
| 542 /// As a result, these characters will all be treated as part of the item to be | |
| 543 /// resolved (aka the * is interpreted literally as a *, not as an indicator for | |
| 544 /// bold <em>. | |
|
Alan Knight
2013/11/06 23:54:18
Maybe provide an example of an input and output, j
| |
| 545 List<String> _tokenizeComplexReference(String curName) { | |
|
Alan Knight
2013/11/06 23:54:18
nit: If we're not re-assigning to it, isn't it jus
| |
| 546 var tokens = []; | |
| 547 var append = false; | |
| 548 var curIndex = 0; | |
|
Alan Knight
2013/11/06 23:54:18
and this could probably just be "index"
| |
| 549 while(curIndex < curName.length) { | |
| 550 if (curName.indexOf(_LESS_THAN, curIndex) == curIndex) { | |
| 551 tokens.add(_LESS_THAN); | |
| 552 append = false; | |
| 553 curIndex += _LESS_THAN.length; | |
| 554 } else if (curName[curIndex] == ' ' || curName[curIndex] == ',' || | |
| 555 curName[curIndex] == '>') { | |
| 556 tokens.add(curName[curIndex]); | |
| 557 append = false; | |
| 558 curIndex++; | |
| 559 } else { | |
| 560 if (append) { | |
| 561 tokens[tokens.length - 1] = tokens.last + curName[curIndex]; | |
| 562 } else { | |
| 563 tokens.add(curName[curIndex]); | |
| 564 append = true; | |
| 565 } | |
| 566 curIndex++; | |
| 567 } | |
| 568 } | |
| 569 return tokens; | |
| 570 } | |
| 571 | |
| 572 /// This is a more complex reference. Try to break up if its of the form A<B> | |
| 573 /// where A is an alphanumeric string and B is an A, a list of B ("B, B, B"), | |
| 574 /// or of the form A<B>. Note: unlike other the other markdown-style links, all | |
| 575 /// text inside the square brackets is treated as part of the link (aka the * is | |
| 576 /// interpreted literally as a *, not as a indicator for bold <em>. | |
| 577 markdown.Node fixComplexReference(String name, LibraryMirror currentLibrary, | |
| 578 ClassMirror currentClass, MemberMirror currentMember) { | |
| 579 // Parse into multiple elements we can try to resolve. | |
| 580 var tokens = _tokenizeComplexReference(name); | |
| 581 | |
| 582 // Produce an html representation of our elements. Group unresolved and plain | |
| 583 // text are grouped into "link" elements so they display as code. | |
| 584 final textElements = [' ', ',', '>', _LESS_THAN]; | |
| 585 var accumulatedHtml = ''; | |
| 586 for (var token in tokens) { | |
| 587 bool added = false; | |
| 588 if (!textElements.contains(token)) { | |
| 589 String elementName = findElementInScope(token, currentLibrary, | |
| 590 currentClass, currentMember); | |
| 591 if (elementName != null) { | |
| 592 accumulatedHtml += markdown.renderToHtml([new markdown.Element.text( | |
| 593 'a', elementName)]); | |
| 594 added = true; | |
| 595 } | |
| 596 } | |
| 597 if (!added) { | |
| 598 accumulatedHtml += token; | |
| 599 } | |
| 600 } | |
| 601 return new markdown.Text(accumulatedHtml); | |
| 602 } | |
| 603 | |
| 512 /// Converts all [foo] references in comments to <a>libraryName.foo</a>. | 604 /// Converts all [foo] references in comments to <a>libraryName.foo</a>. |
| 513 markdown.Node fixReference(String name, LibraryMirror currentLibrary, | 605 markdown.Node fixReference(String name, LibraryMirror currentLibrary, |
| 514 ClassMirror currentClass, MemberMirror currentMember) { | 606 ClassMirror currentClass, MemberMirror currentMember) { |
| 515 var reference; | 607 // Attempt the look up the whole name up in the scope. |
| 516 var memberScope = currentMember == null ? | 608 String elementName = |
| 517 null : currentMember.lookupInScope(name); | 609 findElementInScope(name, currentLibrary, currentClass, currentMember); |
| 518 if (memberScope != null) { | 610 if (elementName != null) { |
| 519 reference = docName(memberScope); | 611 return new markdown.Element.text('a', elementName); |
| 520 } else { | |
| 521 var classScope = currentClass == null ? | |
| 522 null : currentClass.lookupInScope(name); | |
| 523 if (classScope != null) { | |
| 524 reference = docName(classScope); | |
| 525 } else { | |
| 526 var libraryScope = currentLibrary == null ? | |
| 527 null : currentLibrary.lookupInScope(name); | |
| 528 reference = libraryScope != null ? docName(libraryScope) : name; | |
| 529 } | |
| 530 } | 612 } |
| 531 return new markdown.Element.text('a', reference); | 613 return fixComplexReference(name, currentLibrary, currentClass, currentMember); |
| 532 } | 614 } |
| 533 | 615 |
| 534 /// Returns a map of [Variable] objects constructed from [mirrorMap]. | 616 /// Returns a map of [Variable] objects constructed from [mirrorMap]. |
| 535 Map<String, Variable> _variables(Map<String, VariableMirror> mirrorMap) { | 617 Map<String, Variable> _variables(Map<String, VariableMirror> mirrorMap) { |
| 536 var data = {}; | 618 var data = {}; |
| 537 // TODO(janicejl): When map to map feature is created, replace the below with | 619 // TODO(janicejl): When map to map feature is created, replace the below with |
| 538 // a filter. Issue(#9590). | 620 // a filter. Issue(#9590). |
| 539 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { | 621 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { |
| 540 _currentMember = mirror; | 622 _currentMember = mirror; |
| 541 if (_includePrivate || !_isHidden(mirror)) { | 623 if (_includePrivate || !_isHidden(mirror)) { |
| (...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1238 String docName(DeclarationMirror m) { | 1320 String docName(DeclarationMirror m) { |
| 1239 if (m is LibraryMirror) { | 1321 if (m is LibraryMirror) { |
| 1240 return (m as LibraryMirror).qualifiedName.replaceAll('.','-'); | 1322 return (m as LibraryMirror).qualifiedName.replaceAll('.','-'); |
| 1241 } | 1323 } |
| 1242 var owner = m.owner; | 1324 var owner = m.owner; |
| 1243 if (owner == null) return m.qualifiedName; | 1325 if (owner == null) return m.qualifiedName; |
| 1244 // For the unnamed constructor we just return the class name. | 1326 // For the unnamed constructor we just return the class name. |
| 1245 if (m.simpleName == '') return docName(owner); | 1327 if (m.simpleName == '') return docName(owner); |
| 1246 return docName(owner) + '.' + m.simpleName; | 1328 return docName(owner) + '.' + m.simpleName; |
| 1247 } | 1329 } |
| OLD | NEW |