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

Side by Side Diff: client/html/scripts/html_diff.dart

Issue 8871001: Thoroughly document html_diff and html_doc. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 9 years 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 | « no previous file | client/html/scripts/html_doc.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 * A script to assist in documenting the difference between the dart:html API 6 * A script to assist in documenting the difference between the dart:html API
7 * and the old DOM API. 7 * and the old DOM API.
8 */ 8 */
9 #library('html_diff'); 9 #library('html_diff');
10 10
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 for (var member in type.members.getValues()) { 42 for (var member in type.members.getValues()) {
43 if (!member.isPrivate && member.name != 'typeName' && 43 if (!member.isPrivate && member.name != 'typeName' &&
44 !diff.domToHtml.containsKey(member) && 44 !diff.domToHtml.containsKey(member) &&
45 (member is MethodMember || member is PropertyMember)) { 45 (member is MethodMember || member is PropertyMember)) {
46 print('No dart:html wrapper for ${type.name}.${member.name}'); 46 print('No dart:html wrapper for ${type.name}.${member.name}');
47 } 47 }
48 } 48 }
49 } 49 }
50 } 50 }
51 51
52 // TODO(nweiz): document this 52 /**
53 * A class for computing a many-to-many mapping between the types and members in
54 * `dart:dom` and `dart:html`. This mapping is based on two indicators:
55 *
56 * 1. Auto-detected wrappers. Most `dart:html` types correspond
57 * straightforwardly to a single `dart:dom` type, and have the same name.
58 * In addition, most `dart:htmlimpl` methods just call a single `dart:dom`
59 * method. This class detects these simple correspondences automatically.
60 *
61 * 2. Manual annotations. When it's not clear which `dart:dom` items a given
62 * `dart:html` item corresponds to, the `dart:htmlimpl` item can be
63 * annotated in the documentation comments using the `@domName` annotation.
64 *
65 * The `@domName` annotations for types and members are of the form `@domName
66 * NAME(, NAME)*`, where the `NAME`s refer to the `dart:dom` types/members that
67 * correspond to the annotated `dart:htmlimpl` type/member. `NAME`s on member
68 * annotations can refer to either fully-qualified member names (e.g.
69 * `Document.createElement`) or unqualified member names (e.g. `createElement`).
70 * Unqualified member names are assumed to refer to members of one of the
71 * corresponding `dart:dom` types.
72 */
53 class HtmlDiff { 73 class HtmlDiff {
74 /** A map from `dart:dom` members to corresponding `dart:html` members. */
54 final Map<Member, Set<Member>> domToHtml; 75 final Map<Member, Set<Member>> domToHtml;
76
77 /** A map from `dart:html` members to corresponding `dart:dom` members. */
55 final Map<Member, Set<Member>> htmlToDom; 78 final Map<Member, Set<Member>> htmlToDom;
79
80 /** A map from `dart:dom` types to corresponding `dart:html` types. */
56 final Map<Type, Set<Type>> domTypesToHtml; 81 final Map<Type, Set<Type>> domTypesToHtml;
82
83 /** A map from `dart:html` types to corresponding `dart:dom` types. */
57 final Map<Type, Set<Type>> htmlTypesToDom; 84 final Map<Type, Set<Type>> htmlTypesToDom;
58 85
86 /**
87 * Perform static initialization of [world]. This should be run before
88 * calling [HtmlDiff.run].
89 */
59 static void initialize() { 90 static void initialize() {
60 world.processDartScript('dart:htmlimpl'); 91 world.processDartScript('dart:htmlimpl');
61 world.resolveAll(); 92 world.resolveAll();
62 } 93 }
63 94
64 HtmlDiff() : 95 HtmlDiff() :
65 domToHtml = new Map<Member, Set<Member>>(), 96 domToHtml = new Map<Member, Set<Member>>(),
66 htmlToDom = new Map<Member, Set<Member>>(), 97 htmlToDom = new Map<Member, Set<Member>>(),
67 domTypesToHtml = new Map<Type, Set<Type>>(), 98 domTypesToHtml = new Map<Type, Set<Type>>(),
68 htmlTypesToDom = new Map<Type, Set<Type>>(); 99 htmlTypesToDom = new Map<Type, Set<Type>>();
69 100
101 /**
102 * Computes the `dart:dom` to `dart:html` mapping, and places it in
103 * [domToHtml], [htmlToDom], [domTypesToHtml], and [htmlTypesToDom]. Before
104 * this is run, Frog should be initialized (via [parseOptions] and
105 * [initializeWorld]) and [HtmlDiff.initialize] should be called.
106 */
70 void run() { 107 void run() {
71 final htmlLib = world.libraries['dart:htmlimpl']; 108 final htmlLib = world.libraries['dart:htmlimpl'];
72 for (var implType in htmlLib.types.getValues()) { 109 for (var implType in htmlLib.types.getValues()) {
73 final domTypes = htmlToDomTypes(implType); 110 final domTypes = htmlToDomTypes(implType);
74 final htmlType = htmlImplToHtmlType(implType); 111 final htmlType = htmlImplToHtmlType(implType);
75 if (htmlType == null) continue; 112 if (htmlType == null) continue;
76 113
77 htmlTypesToDom.putIfAbsent(htmlType, () => new Set()).addAll(domTypes); 114 htmlTypesToDom.putIfAbsent(htmlType, () => new Set()).addAll(domTypes);
78 domTypes.forEach((t) => 115 domTypes.forEach((t) =>
79 domTypesToHtml.putIfAbsent(t, () => new Set()).add(htmlType)); 116 domTypesToHtml.putIfAbsent(t, () => new Set()).add(htmlType));
80 117
81 final members = new List.from(implType.members.getValues()); 118 final members = new List.from(implType.members.getValues());
82 members.addAll(implType.constructors.getValues()); 119 members.addAll(implType.constructors.getValues());
83 implType.factories.forEach((f) => members.add(f)); 120 implType.factories.forEach((f) => members.add(f));
84 members.forEach((m) => _addMemberDiff(m, domTypes)); 121 members.forEach((m) => _addMemberDiff(m, domTypes));
85 } 122 }
86 } 123 }
87 124
125 /**
126 * Returns whether or not [domMember] (from `dart:dom`) and [htmlMember] (from
127 * `dart:html`) have the same name from the user's perspective. The names are
128 * the same if the type names and the member names are the same, but allowance
129 * is made for `dart:dom` names that start with "HTML" or "WebKit", and for
130 * `dart:html` properties that have the same name as fields in `dart:dom`.
131 */
88 bool sameName(Member domMember, Member htmlMember) { 132 bool sameName(Member domMember, Member htmlMember) {
89 var domTypeName = domMember.declaringType.name; 133 var domTypeName = domMember.declaringType.name;
90 if (domTypeName == 'DOMWindow') domTypeName = 'Window'; 134 if (domTypeName == 'DOMWindow') domTypeName = 'Window';
91 domTypeName = domTypeName.replaceFirst(new RegExp('^(HTML|WebKit)'), ''); 135 domTypeName = domTypeName.replaceFirst(new RegExp('^(HTML|WebKit)'), '');
92 var htmlTypeName = htmlMember.declaringType.name; 136 var htmlTypeName = htmlMember.declaringType.name;
93 137
94 var domName = domMember.name; 138 var domName = domMember.name;
95 var htmlName = htmlMember.name; 139 var htmlName = htmlMember.name;
96 if (htmlName.startsWith('get:') || htmlName.startsWith('set:')) { 140 if (htmlName.startsWith('get:') || htmlName.startsWith('set:')) {
97 htmlName = htmlName.substring(4); 141 htmlName = htmlName.substring(4);
98 } 142 }
99 143
100 return domTypeName == htmlTypeName && domName == htmlName; 144 return domTypeName == htmlTypeName && domName == htmlName;
101 } 145 }
102 146
147 /**
148 * Records the `dart:dom` to `dart:html` mapping for [implMember] (from
149 * `dart:htmlimpl`). [domTypes] are the `dart:dom` [Type]s that correspond to
150 * [implMember]'s defining [Type].
151 */
103 void _addMemberDiff(Member implMember, List<Type> domTypes) { 152 void _addMemberDiff(Member implMember, List<Type> domTypes) {
104 if (implMember.isProperty) { 153 if (implMember.isProperty) {
105 if (implMember.canGet) _addMemberDiff(implMember.getter, domTypes); 154 if (implMember.canGet) _addMemberDiff(implMember.getter, domTypes);
106 if (implMember.canSet) _addMemberDiff(implMember.setter, domTypes); 155 if (implMember.canSet) _addMemberDiff(implMember.setter, domTypes);
107 } 156 }
108 157
109 var domMembers = htmlToDomMembers(implMember, domTypes); 158 var domMembers = htmlToDomMembers(implMember, domTypes);
110 var htmlMember = htmlImplToHtmlMember(implMember); 159 var htmlMember = htmlImplToHtmlMember(implMember);
111 if (htmlMember == null && !domMembers.isEmpty()) { 160 if (htmlMember == null && !domMembers.isEmpty()) {
112 print('Warning: dart:htmlimpl member ${implMember.declaringType.name}.' + 161 print('Warning: dart:htmlimpl member ${implMember.declaringType.name}.' +
113 '${implMember.name} has no corresponding dart:html member.'); 162 '${implMember.name} has no corresponding dart:html member.');
114 } 163 }
115 164
116 if (htmlMember == null) return; 165 if (htmlMember == null) return;
117 if (!domMembers.isEmpty()) htmlToDom[htmlMember] = domMembers; 166 if (!domMembers.isEmpty()) htmlToDom[htmlMember] = domMembers;
118 domMembers.forEach((m) => 167 domMembers.forEach((m) =>
119 domToHtml.putIfAbsent(m, () => new Set()).add(htmlMember)); 168 domToHtml.putIfAbsent(m, () => new Set()).add(htmlMember));
120 } 169 }
121 170
171 /**
172 * Returns the `dart:html` [Type] that corresponds to [implType] from
173 * `dart:htmlimpl`, or `null` if there is no such correspondence.
174 */
122 Type htmlImplToHtmlType(Type implType) { 175 Type htmlImplToHtmlType(Type implType) {
123 if (implType == null || implType.isTop || implType.interfaces.isEmpty() || 176 if (implType == null || implType.isTop || implType.interfaces.isEmpty() ||
124 implType.interfaces[0].library.name != 'html') { 177 implType.interfaces[0].library.name != 'html') {
125 return null; 178 return null;
126 } 179 }
127 180
128 return implType.interfaces[0]; 181 return implType.interfaces[0];
129 } 182 }
130 183
184 /**
185 * Returns the `dart:html` [Member] that corresponds to [implMember] from
186 * `dart:htmlimpl`, or `null` if there is no such correspondence.
187 */
131 Member htmlImplToHtmlMember(Member implMember) { 188 Member htmlImplToHtmlMember(Member implMember) {
132 var htmlType = htmlImplToHtmlType(implMember.declaringType); 189 var htmlType = htmlImplToHtmlType(implMember.declaringType);
133 if (htmlType == null) return null; 190 if (htmlType == null) return null;
134 191
135 bool getter, setter; 192 bool getter, setter;
136 if (implMember.isConstructor || implMember.isFactory) { 193 if (implMember.isConstructor || implMember.isFactory) {
137 var constructor = htmlType.constructors[implMember.name]; 194 var constructor = htmlType.constructors[implMember.name];
138 if (constructor != null) return constructor; 195 if (constructor != null) return constructor;
139 return htmlType.factories[implMember.name]; 196 return htmlType.factories[implMember.name];
140 } else if ((getter = implMember.name.startsWith('get:')) || 197 } else if ((getter = implMember.name.startsWith('get:')) ||
141 (setter = implMember.name.startsWith('set:'))) { 198 (setter = implMember.name.startsWith('set:'))) {
142 // Use getMember to follow interface inheritance chains. If it's a 199 // Use getMember to follow interface inheritance chains. If it's a
143 // ConcreteMember, though, it's an implementation of some data structure 200 // ConcreteMember, though, it's an implementation of some data structure
144 // and we don't care about it. 201 // and we don't care about it.
145 var htmlProperty = htmlType.getMember(implMember.name.substring(4)); 202 var htmlProperty = htmlType.getMember(implMember.name.substring(4));
146 if (htmlProperty != null && htmlProperty is! ConcreteMember) { 203 if (htmlProperty != null && htmlProperty is! ConcreteMember) {
147 return getter ? htmlProperty.getter : htmlProperty.setter; 204 return getter ? htmlProperty.getter : htmlProperty.setter;
148 } else { 205 } else {
149 return null; 206 return null;
150 } 207 }
151 } else { 208 } else {
152 return htmlType.getMember(implMember.name); 209 return htmlType.getMember(implMember.name);
153 } 210 }
154 } 211 }
155 212
213 /**
214 * Returns the `dart:dom` [Type]s that correspond to [htmlType] from
215 * `dart:htmlimpl`. This can be the empty list if no correspondence is found.
216 */
156 List<Type> htmlToDomTypes(Type htmlType) { 217 List<Type> htmlToDomTypes(Type htmlType) {
157 if (htmlType.name == null) return []; 218 if (htmlType.name == null) return [];
158 final tags = _getTags(findComment(htmlType.span)); 219 final tags = _getTags(findComment(htmlType.span));
159 220
160 if (tags.containsKey('domName')) { 221 if (tags.containsKey('domName')) {
161 var domNames = map(tags['domName'].split(','), (s) => s.trim()); 222 var domNames = map(tags['domName'].split(','), (s) => s.trim());
162 if (domNames.length == 1 && domNames[0] == 'none') return []; 223 if (domNames.length == 1 && domNames[0] == 'none') return [];
163 return map(domNames, (domName) { 224 return map(domNames, (domName) {
164 // DOMWindow is Chrome-specific, so we don't use it in our annotations. 225 // DOMWindow is Chrome-specific, so we don't use it in our annotations.
165 if (domName == 'Window') domName = 'DOMWindow'; 226 if (domName == 'Window') domName = 'DOMWindow';
(...skipping 11 matching lines...) Expand all
177 if (domType == null) domType = world.dom.types['WebKit$domName']; 238 if (domType == null) domType = world.dom.types['WebKit$domName'];
178 if (domType == null) { 239 if (domType == null) {
179 print('Warning: no dart:dom type matches dart:htmlimpl ' + 240 print('Warning: no dart:dom type matches dart:htmlimpl ' +
180 htmlType.name); 241 htmlType.name);
181 return []; 242 return [];
182 } 243 }
183 return [domType]; 244 return [domType];
184 } 245 }
185 } 246 }
186 247
248 /**
249 * Returns the `dart:dom` [Member]s that correspond to [htmlMember] from
250 * `dart:htmlimpl`. This can be the empty set if no correspondence is found.
251 * [domTypes] are the `dart:dom` [Type]s that correspond to [implMember]'s
252 * defining [Type].
253 */
187 Set<Member> htmlToDomMembers(Member htmlMember, List<Type> domTypes) { 254 Set<Member> htmlToDomMembers(Member htmlMember, List<Type> domTypes) {
188 if (htmlMember.isPrivate || htmlMember is! MethodMember) return new Set(); 255 if (htmlMember.isPrivate || htmlMember is! MethodMember) return new Set();
189 final tags = _getTags(findComment(htmlMember.span)); 256 final tags = _getTags(findComment(htmlMember.span));
190 if (tags.containsKey('domName')) { 257 if (tags.containsKey('domName')) {
191 final domNames = map(tags['domName'].split(','), (s) => s.trim()); 258 final domNames = map(tags['domName'].split(','), (s) => s.trim());
192 if (domNames.length == 1 && domNames[0] == 'none') return new Set(); 259 if (domNames.length == 1 && domNames[0] == 'none') return new Set();
193 final members = new Set(); 260 final members = new Set();
194 domNames.forEach((name) { 261 domNames.forEach((name) {
195 var nameMembers = _membersFromName(name, domTypes); 262 var nameMembers = _membersFromName(name, domTypes);
196 if (nameMembers.isEmpty()) { 263 if (nameMembers.isEmpty()) {
(...skipping 19 matching lines...) Expand all
216 } 283 }
217 284
218 if (htmlMember.isFactory && htmlMember.name == '' && 285 if (htmlMember.isFactory && htmlMember.name == '' &&
219 domTypes.length == 1 && domTypes[0].name.endsWith('Event')) { 286 domTypes.length == 1 && domTypes[0].name.endsWith('Event')) {
220 return _membersFromName('init${domTypes[0].name}', domTypes); 287 return _membersFromName('init${domTypes[0].name}', domTypes);
221 } 288 }
222 289
223 return _getDomMembers(htmlMember.definition.body, domTypes); 290 return _getDomMembers(htmlMember.definition.body, domTypes);
224 } 291 }
225 292
293 /**
294 * Returns the `dart:dom` [Member]s that are indicated by [name]. [name] can
295 * be either an unqualified member name (e.g. `createElement`), in which case
296 * it's treated as the name of a member of one of [defaultTypes], or a
297 * fully-qualified member name (e.g. `Document.createElement`), in which case
298 * it's looked up in `dart:dom` and [defaultTypes] is ignored.
299 */
226 Set<Member> _membersFromName(String name, List<Type> defaultTypes) { 300 Set<Member> _membersFromName(String name, List<Type> defaultTypes) {
227 if (!name.contains('.', 0)) { 301 if (!name.contains('.', 0)) {
228 if (defaultTypes.isEmpty()) { 302 if (defaultTypes.isEmpty()) {
229 print('Warning: no default type for ${name}'); 303 print('Warning: no default type for ${name}');
230 return new Set(); 304 return new Set();
231 } 305 }
232 final members = new Set<Member>(); 306 final members = new Set<Member>();
233 defaultTypes.forEach((t) { 307 defaultTypes.forEach((t) {
234 if (t.members.containsKey(name)) members.add(t.members[name]); 308 if (t.members.containsKey(name)) members.add(t.members[name]);
235 }); 309 });
236 return members; 310 return members;
237 } 311 }
238 312
239 final splitName = name.split('.'); 313 final splitName = name.split('.');
240 if (splitName.length != 2) { 314 if (splitName.length != 2) {
241 print('Warning: invalid member name ${name}'); 315 print('Warning: invalid member name ${name}');
242 return new Set(); 316 return new Set();
243 } 317 }
244 var typeName = splitName[0]; 318 var typeName = splitName[0];
245 if (typeName == 'Window') typeName = 'DOMWindow'; 319 if (typeName == 'Window') typeName = 'DOMWindow';
246 final type = world.dom.types[typeName]; 320 final type = world.dom.types[typeName];
247 if (type == null) return new Set(); 321 if (type == null) return new Set();
248 final member = type.members[splitName[1]]; 322 final member = type.members[splitName[1]];
249 if (member == null) return new Set(); 323 if (member == null) return new Set();
250 return new Set.from([member]); 324 return new Set.from([member]);
251 } 325 }
252 326
327 /**
328 * Returns the `dart:dom` [Member]s that are referred to in [stmt]. This only
329 * extracts references from relatively simple statements; methods containing
330 * more complex wrappers should be manually annotated with `@domName`.
331 *
332 * [domTypes] are the `dart:dom` [Type]s that correspond to the current
333 * [Member]'s defining [Type].
334 */
253 Set<Member> _getDomMembers(Statement stmt, List<Type> domTypes) { 335 Set<Member> _getDomMembers(Statement stmt, List<Type> domTypes) {
254 if (stmt is BlockStatement) { 336 if (stmt is BlockStatement) {
255 final body = stmt.body.filter((s) => !_ignorableStatement(s)); 337 final body = stmt.body.filter((s) => !_ignorableStatement(s));
256 if (body.length != 1) return new Set(); 338 if (body.length != 1) return new Set();
257 return _getDomMembers(stmt.body[0], domTypes); 339 return _getDomMembers(stmt.body[0], domTypes);
258 } else if (stmt is ReturnStatement) { 340 } else if (stmt is ReturnStatement) {
259 return _domMembersFromExpression(stmt.value, domTypes); 341 return _domMembersFromExpression(stmt.value, domTypes);
260 } else if (stmt is ExpressionStatement) { 342 } else if (stmt is ExpressionStatement) {
261 return _domMembersFromExpression(stmt.body, domTypes); 343 return _domMembersFromExpression(stmt.body, domTypes);
262 } else if (stmt is TryStatement) { 344 } else if (stmt is TryStatement) {
263 return _getDomMembers(stmt.body, domTypes); 345 return _getDomMembers(stmt.body, domTypes);
264 } else if (stmt is IfStatement) { 346 } else if (stmt is IfStatement) {
265 final members = _getDomMembers(stmt.trueBranch, domTypes); 347 final members = _getDomMembers(stmt.trueBranch, domTypes);
266 members.addAll(_getDomMembers(stmt.falseBranch, domTypes)); 348 members.addAll(_getDomMembers(stmt.falseBranch, domTypes));
267 return members; 349 return members;
268 } else { 350 } else {
269 return new Set(); 351 return new Set();
270 } 352 }
271 } 353 }
272 354
273 /** 355 /**
274 * Whether a statement can be ignored for the purpose of determining the DOM 356 * Whether [stmt] can be ignored for the purpose of determining the DOM name
275 * name of the enclosing method. The Webkit-to-Dart conversion process leaves 357 * of the enclosing method. The Webkit-to-Dart conversion process leaves
276 * behind various throws and returns that we want to ignore. 358 * behind various `throw`s and `return`s that we want to ignore.
277 */ 359 */
278 bool _ignorableStatement(Statement stmt) { 360 bool _ignorableStatement(Statement stmt) {
279 if (stmt is BlockStatement) { 361 if (stmt is BlockStatement) {
280 return Collections.every(stmt.body, (s) => _ignorableStatement(s)); 362 return Collections.every(stmt.body, (s) => _ignorableStatement(s));
281 } else if (stmt is TryStatement) { 363 } else if (stmt is TryStatement) {
282 return _ignorableStatement(stmt.body); 364 return _ignorableStatement(stmt.body);
283 } else if (stmt is IfStatement) { 365 } else if (stmt is IfStatement) {
284 return _ignorableStatement(stmt.trueBranch) && 366 return _ignorableStatement(stmt.trueBranch) &&
285 _ignorableStatement(stmt.falseBranch); 367 _ignorableStatement(stmt.falseBranch);
286 } else if (stmt is ReturnStatement) { 368 } else if (stmt is ReturnStatement) {
287 return stmt.value == null || stmt.value is ThisExpression; 369 return stmt.value == null || stmt.value is ThisExpression;
288 } else { 370 } else {
289 return stmt is ThrowStatement; 371 return stmt is ThrowStatement;
290 } 372 }
291 } 373 }
292 374
375 /**
376 * Returns the `dart:dom` [Member]s that are referred to in [expr]. This only
377 * extracts references from relatively simple expressions; methods containing
378 * more complex wrappers should be manually annotated with `@domName`.
379 *
380 * [domTypes] are the `dart:dom` [Type]s that correspond to the current
381 * [Member]'s defining [Type].
382 */
293 Set<Member> _domMembersFromExpression(Expression expr, List<Type> domTypes) { 383 Set<Member> _domMembersFromExpression(Expression expr, List<Type> domTypes) {
294 if (expr is BinaryExpression && expr.op.kind == TokenKind.ASSIGN) { 384 if (expr is BinaryExpression && expr.op.kind == TokenKind.ASSIGN) {
295 return _domMembersFromExpression(expr.x, domTypes); 385 return _domMembersFromExpression(expr.x, domTypes);
Siggi Cherem (dart-lang) 2011/12/07 23:22:18 I meant to ask you in the prev CL - I was at first
nweiz 2011/12/07 23:36:27 That's right. The vast majority of the time, when
296 } else if (expr is CallExpression) { 386 } else if (expr is CallExpression) {
297 if (expr.target is DotExpression && expr.target.self is VarExpression && 387 if (expr.target is DotExpression && expr.target.self is VarExpression &&
298 expr.target.self.name.name == 'LevelDom' && 388 expr.target.self.name.name == 'LevelDom' &&
299 (expr.target.name.name.startsWith('wrap') || 389 (expr.target.name.name.startsWith('wrap') ||
300 expr.target.name.name == 'unwrap')) { 390 expr.target.name.name == 'unwrap')) {
301 return _domMembersFromExpression(expr.arguments[0].value, domTypes); 391 return _domMembersFromExpression(expr.arguments[0].value, domTypes);
302 } 392 }
303 return _domMembersFromExpression(expr.target, domTypes); 393 return _domMembersFromExpression(expr.target, domTypes);
304 } else if (expr is DotExpression) { 394 } else if (expr is DotExpression) {
305 if (expr.self is NewExpression && expr.name.name == '_wrap' && 395 if (expr.self is NewExpression && expr.name.name == '_wrap' &&
306 expr.self.arguments.length == 1) { 396 expr.self.arguments.length == 1) {
307 return _domMembersFromExpression(expr.self.arguments[0].value, 397 return _domMembersFromExpression(expr.self.arguments[0].value,
308 domTypes); 398 domTypes);
309 } else if (expr.self is VarExpression && expr.self.name.name == '_ptr') { 399 } else if (expr.self is VarExpression && expr.self.name.name == '_ptr') {
310 return _membersFromName(expr.name.name, domTypes); 400 return _membersFromName(expr.name.name, domTypes);
311 } 401 }
312 final bases = _domMembersFromExpression(expr.self, domTypes); 402 final bases = _domMembersFromExpression(expr.self, domTypes);
313 return new Set.from(map(bases, (base) { 403 return new Set.from(map(bases, (base) {
314 if (base == null || base.returnType == null) return null; 404 if (base == null || base.returnType == null) return null;
315 return base.returnType.members[expr.name.name]; 405 return base.returnType.members[expr.name.name];
316 }).filter((m) => m != null)); 406 }).filter((m) => m != null));
317 } else if (expr is NewExpression && expr.arguments.length == 1) { 407 } else if (expr is NewExpression && expr.arguments.length == 1) {
318 return _domMembersFromExpression(expr.arguments[0].value, domTypes); 408 return _domMembersFromExpression(expr.arguments[0].value, domTypes);
319 } else { 409 } else {
320 return new Set(); 410 return new Set();
321 } 411 }
322 } 412 }
323 413
414 /**
415 * Extracts a [Map] from tag names to values from [comment], which is parsed
416 * from a Dart source file via dartdoc. Tags are of the form `@NAME VALUE`,
417 * where `NAME` is alphabetic and `VALUE` can contain any character other than
418 * `;`. Multiple tags can be separated by semicolons.
419 *
420 * At time of writing, the only tag that's used is `@domName`.
421 */
324 Map<String, String> _getTags(String comment) { 422 Map<String, String> _getTags(String comment) {
325 if (comment == null) return const <String>{}; 423 if (comment == null) return const <String>{};
326 final re = new RegExp("@([a-zA-Z]+) ([^;]+)(?:;|\$)"); 424 final re = new RegExp("@([a-zA-Z]+) ([^;]+)(?:;|\$)");
327 final tags = <String>{}; 425 final tags = <String>{};
328 for (var m in re.allMatches(comment.trim())) { 426 for (var m in re.allMatches(comment.trim())) {
329 tags[m[1]] = m[2]; 427 tags[m[1]] = m[2];
330 } 428 }
331 return tags; 429 return tags;
332 } 430 }
333 } 431 }
OLDNEW
« no previous file with comments | « no previous file | client/html/scripts/html_doc.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698