Chromium Code Reviews| Index: pkg/docgen/lib/docgen.dart |
| diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart |
| index 239d08a76056b204a6280ae97ef76727ac68e39f..360d052e39b2ec18b14d8782b2b12071136ab18c 100644 |
| --- a/pkg/docgen/lib/docgen.dart |
| +++ b/pkg/docgen/lib/docgen.dart |
| @@ -509,26 +509,108 @@ String _htmlMdn(String content, String url) { |
| '<a href="' + url.trim() + '">from Mdn</a></p></div>'; |
| } |
| -/// Converts all [foo] references in comments to <a>libraryName.foo</a>. |
| -markdown.Node fixReference(String name, LibraryMirror currentLibrary, |
| +/// Look for the specified name starting with the current member, and |
| +/// progressively working outward to the current library scope. |
| +String findElementInScope(String name, LibraryMirror currentLibrary, |
| ClassMirror currentClass, MemberMirror currentMember) { |
| - var reference; |
| var memberScope = currentMember == null ? |
| null : currentMember.lookupInScope(name); |
| if (memberScope != null) { |
| - reference = docName(memberScope); |
| + return docName(memberScope); |
| } else { |
| var classScope = currentClass == null ? |
| null : currentClass.lookupInScope(name); |
| if (classScope != null) { |
| - reference = docName(classScope); |
| + return docName(classScope); |
| } else { |
| var libraryScope = currentLibrary == null ? |
| null : currentLibrary.lookupInScope(name); |
| - reference = libraryScope != null ? docName(libraryScope) : name; |
| + if (libraryScope != null) { |
| + return docName(libraryScope); |
| + } |
| + } |
| + } |
| + return null; |
| +} |
| + |
| +// HTML escaped version of '<' character. |
| +final _LESS_THAN = '<'; |
| + |
| +/// Chunk the provided name into individual parts to be resolved. We take a |
| +/// simplistic approach to chunking, though, we break at " ", ",", "<" |
| +/// and ">". All other characters are grouped into the name to be resolved. |
| +/// As a result, these characters will all be treated as part of the item to be |
| +/// resolved (aka the * is interpreted literally as a *, not as an indicator for |
| +/// bold <em>. |
|
Alan Knight
2013/11/06 23:54:18
Maybe provide an example of an input and output, j
|
| +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
|
| + var tokens = []; |
| + var append = false; |
| + var curIndex = 0; |
|
Alan Knight
2013/11/06 23:54:18
and this could probably just be "index"
|
| + while(curIndex < curName.length) { |
| + if (curName.indexOf(_LESS_THAN, curIndex) == curIndex) { |
| + tokens.add(_LESS_THAN); |
| + append = false; |
| + curIndex += _LESS_THAN.length; |
| + } else if (curName[curIndex] == ' ' || curName[curIndex] == ',' || |
| + curName[curIndex] == '>') { |
| + tokens.add(curName[curIndex]); |
| + append = false; |
| + curIndex++; |
| + } else { |
| + if (append) { |
| + tokens[tokens.length - 1] = tokens.last + curName[curIndex]; |
| + } else { |
| + tokens.add(curName[curIndex]); |
| + append = true; |
| + } |
| + curIndex++; |
| } |
| } |
| - return new markdown.Element.text('a', reference); |
| + return tokens; |
| +} |
| + |
| +/// This is a more complex reference. Try to break up if its of the form A<B> |
| +/// where A is an alphanumeric string and B is an A, a list of B ("B, B, B"), |
| +/// or of the form A<B>. Note: unlike other the other markdown-style links, all |
| +/// text inside the square brackets is treated as part of the link (aka the * is |
| +/// interpreted literally as a *, not as a indicator for bold <em>. |
| +markdown.Node fixComplexReference(String name, LibraryMirror currentLibrary, |
| + ClassMirror currentClass, MemberMirror currentMember) { |
| + // Parse into multiple elements we can try to resolve. |
| + var tokens = _tokenizeComplexReference(name); |
| + |
| + // Produce an html representation of our elements. Group unresolved and plain |
| + // text are grouped into "link" elements so they display as code. |
| + final textElements = [' ', ',', '>', _LESS_THAN]; |
| + var accumulatedHtml = ''; |
| + for (var token in tokens) { |
| + bool added = false; |
| + if (!textElements.contains(token)) { |
| + String elementName = findElementInScope(token, currentLibrary, |
| + currentClass, currentMember); |
| + if (elementName != null) { |
| + accumulatedHtml += markdown.renderToHtml([new markdown.Element.text( |
| + 'a', elementName)]); |
| + added = true; |
| + } |
| + } |
| + if (!added) { |
| + accumulatedHtml += token; |
| + } |
| + } |
| + return new markdown.Text(accumulatedHtml); |
| +} |
| + |
| +/// Converts all [foo] references in comments to <a>libraryName.foo</a>. |
| +markdown.Node fixReference(String name, LibraryMirror currentLibrary, |
| + ClassMirror currentClass, MemberMirror currentMember) { |
| + // Attempt the look up the whole name up in the scope. |
| + String elementName = |
| + findElementInScope(name, currentLibrary, currentClass, currentMember); |
| + if (elementName != null) { |
| + return new markdown.Element.text('a', elementName); |
| + } |
| + return fixComplexReference(name, currentLibrary, currentClass, currentMember); |
| } |
| /// Returns a map of [Variable] objects constructed from [mirrorMap]. |