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

Side by Side Diff: pkg/docgen/lib/src/library_helpers.dart

Issue 209563002: pkg/docgen: the big refactor (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: silly Created 6 years, 9 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
« no previous file with comments | « pkg/docgen/lib/src/generator.dart ('k') | pkg/docgen/lib/src/model_helpers.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
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.
4
5 library docgen.library_helpers;
6
7 import 'package:logging/logging.dart';
8 import 'package:markdown/markdown.dart' as markdown;
9
10 import '../../../../sdk/lib/_internal/compiler/implementation/mirrors/source_mir rors.dart';
11 import '../../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_ut il.dart'
12 as dart2js_util;
13
14 import 'models.dart';
15
16 typedef DeclarationMirror LookupFunction(DeclarationSourceMirror declaration,
17 String name);
18
19 /// Support for [:foo:]-style code comments to the markdown parser.
20 final List<markdown.InlineSyntax> MARKDOWN_SYNTAXES =
21 [new markdown.CodeSyntax(r'\[:\s?((?:.|\n)*?)\s?:\]')];
22
23 bool get includePrivateMembers {
24 if (_includePrivate == null) {
25 throw new StateError('includePrivate has not been set');
26 }
27 return _includePrivate;
28 }
29
30 void set includePrivateMembers(bool value) {
31 if (_includePrivate != null) {
32 throw new StateError('includePrivate has already been set');
33 }
34 if (value == null) throw new ArgumentError('includePrivate cannot be null');
35 _includePrivate = value;
36 }
37
38 bool _includePrivate;
39
40 /// Return true if this item and all of its owners are all visible.
41 bool isFullChainVisible(Indexable item) {
42 return includePrivateMembers || (!item.isPrivate && (item.owner != null ?
43 isFullChainVisible(item.owner) : true));
44 }
45
46 /// Logger for printing out progress of documentation generation.
47 final Logger logger = new Logger('Docgen');
48
49 /// The dart:core library, which contains all types that are always available
50 /// without import.
51 Library _coreLibrary;
52
53 /// Set of libraries declared in the SDK, so libraries that can be accessed
54 /// when running dart by default.
55 Iterable<LibraryMirror> get sdkLibraries => _sdkLibraries;
56 Iterable<LibraryMirror> _sdkLibraries;
57
58 /// Index of all the dart2js mirrors examined to corresponding MirrorBased
59 /// docgen objects.
60 ///
61 /// Used for lookup because of the dart2js mirrors exports
62 /// issue. The second level map is indexed by owner docName for faster lookup.
63 /// Why two levels of lookup? Speed, man. Speed.
64 final Map<String, Map<String, Set<Indexable>>> mirrorToDocgen = new Map<String,
65 Map<String, Set<Indexable>>>();
66
67 ////// Top level resolution functions
68 /// Converts all [foo] references in comments to <a>libraryName.foo</a>.
69 markdown.Node globalFixReference(String name) {
70 // Attempt the look up the whole name up in the scope.
71 String elementName = findElementInScopeWithPrefix(name, '');
72 if (elementName != null) {
73 return new markdown.Element.text('a', elementName);
74 }
75 return fixComplexReference(name);
76 }
77
78 /// This is a more complex reference. Try to break up if its of the form A<B>
79 /// where A is an alphanumeric string and B is an A, a list of B ("B, B, B"),
80 /// or of the form A<B>. Note: unlike other the other markdown-style links,
81 /// all text inside the square brackets is treated as part of the link (aka
82 /// the * is interpreted literally as a *, not as a indicator for bold <em>.
83 ///
84 /// Example: [foo&lt;_bar_>] will produce
85 /// <a>resolvedFoo</a>&lt;<a>resolved_bar_</a>> rather than an italicized
86 /// version of resolvedBar.
87 markdown.Node fixComplexReference(String name) {
88 // Parse into multiple elements we can try to resolve.
89 var tokens = _tokenizeComplexReference(name);
90
91 // Produce an html representation of our elements. Group unresolved and
92 // plain text are grouped into "link" elements so they display as code.
93 final textElements = [' ', ',', '>', _LESS_THAN];
94 var accumulatedHtml = '';
95
96 for (var token in tokens) {
97 bool added = false;
98 if (!textElements.contains(token)) {
99 String elementName = findElementInScopeWithPrefix(token, '');
100 if (elementName != null) {
101 accumulatedHtml += markdown.renderToHtml([new markdown.Element.text('a',
102 elementName)]);
103 added = true;
104 }
105 }
106 if (!added) {
107 accumulatedHtml += token;
108 }
109 }
110 return new markdown.Text(accumulatedHtml);
111 }
112
113 String findElementInScopeWithPrefix(String name, String packagePrefix) {
114 var lookupFunc = determineLookupFunc(name);
115 // Look in the dart core library scope.
116 var coreScope = _coreLibrary == null ? null : lookupFunc(_coreLibrary.mirror,
117 name);
118 if (coreScope != null) return packagePrefix + _coreLibrary.docName;
119
120 // If it's a reference that starts with a another library name, then it
121 // looks for a match of that library name in the other sdk libraries.
122 if (name.contains('.')) {
123 var index = name.indexOf('.');
124 var libraryName = name.substring(0, index);
125 var remainingName = name.substring(index + 1);
126 foundLibraryName(library) => library.uri.pathSegments[0] == libraryName;
127
128 if (_sdkLibraries.any(foundLibraryName)) {
129 var library = _sdkLibraries.singleWhere(foundLibraryName);
130 // Look to see if it's a fully qualified library name.
131 var scope = determineLookupFunc(remainingName)(library, remainingName);
132 if (scope != null) {
133 var result = getDocgenObject(scope);
134 if (result is DummyMirror) {
135 return packagePrefix + result.docName;
136 } else {
137 return result.packagePrefix + result.docName;
138 }
139 }
140 }
141 }
142 return null;
143 }
144
145 /// Given a Dart2jsMirror, find the corresponding Docgen [MirrorBased] object.
146 ///
147 /// We have this global lookup function to avoid re-implementing looking up
148 /// the scoping rules for comment resolution here (it is currently done in
149 /// mirrors). If no corresponding MirrorBased object is found, we return a
150 /// [DummyMirror] that simply returns the original mirror's qualifiedName
151 /// while behaving like a MirrorBased object.
152 Indexable getDocgenObject(DeclarationMirror mirror, [Indexable owner]) {
153 Map<String, Set<Indexable>> docgenObj =
154 mirrorToDocgen[dart2js_util.qualifiedNameOf(mirror)];
155 if (docgenObj == null) {
156 return new DummyMirror(mirror, owner);
157 }
158
159 var setToExamine = new Set();
160 if (owner != null) {
161 var firstSet = docgenObj[owner.docName];
162 if (firstSet != null) setToExamine.addAll(firstSet);
163 if (_coreLibrary != null && docgenObj[_coreLibrary.docName] != null) {
164 setToExamine.addAll(docgenObj[_coreLibrary.docName]);
165 }
166 } else {
167 for (var value in docgenObj.values) {
168 setToExamine.addAll(value);
169 }
170 }
171
172 Set<Indexable> results = new Set<Indexable>();
173 for (Indexable indexable in setToExamine) {
174 if (indexable.mirror.qualifiedName == mirror.qualifiedName &&
175 indexable.isValidMirror(mirror)) {
176 results.add(indexable);
177 }
178 }
179
180 if (results.length > 0) {
181 // This might occur if we didn't specify an "owner."
182 return results.first;
183 }
184 return new DummyMirror(mirror, owner);
185 }
186
187 void initializeTopLevelLibraries(MirrorSystem mirrorSystem) {
188 _sdkLibraries = mirrorSystem.libraries.values.where(
189 (each) => each.uri.scheme == 'dart');
190 _coreLibrary = new Library(_sdkLibraries.singleWhere((lib) =>
191 lib.uri.toString().startsWith('dart:core')));
192 }
193
194 /// For a given name, determine if we need to resolve it as a qualified name
195 /// or a simple name in the source mirors.
196 LookupFunction determineLookupFunc(String name) => name.contains('.') ?
197 dart2js_util.lookupQualifiedInScope :
198 (mirror, name) => mirror.lookupInScope(name);
199
200 /// Chunk the provided name into individual parts to be resolved. We take a
201 /// simplistic approach to chunking, though, we break at " ", ",", "&lt;"
202 /// and ">". All other characters are grouped into the name to be resolved.
203 /// As a result, these characters will all be treated as part of the item to
204 /// be resolved (aka the * is interpreted literally as a *, not as an
205 /// indicator for bold <em>.
206 List<String> _tokenizeComplexReference(String name) {
207 var tokens = [];
208 var append = false;
209 var index = 0;
210 while (index < name.length) {
211 if (name.indexOf(_LESS_THAN, index) == index) {
212 tokens.add(_LESS_THAN);
213 append = false;
214 index += _LESS_THAN.length;
215 } else if (name[index] == ' ' || name[index] == ',' || name[index] == '>') {
216 tokens.add(name[index]);
217 append = false;
218 index++;
219 } else {
220 if (append) {
221 tokens[tokens.length - 1] = tokens.last + name[index];
222 } else {
223 tokens.add(name[index]);
224 append = true;
225 }
226 index++;
227 }
228 }
229 return tokens;
230 }
231
232 // HTML escaped version of '<' character.
233 const _LESS_THAN = '&lt;';
OLDNEW
« no previous file with comments | « pkg/docgen/lib/src/generator.dart ('k') | pkg/docgen/lib/src/model_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698