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

Side by Side Diff: client/html/scripts/html-diff.dart

Issue 8548019: Add a script for determining which DOM methods correspond to which HTML methods. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Use "Window" instead of "DOMWindow". Created 9 years, 1 month 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
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /**
6 * A script to assist in documenting the difference between the dart:html API
7 * and the old DOM API.
8 */
9 #library('renames');
10
11 #import('../../../frog/lang.dart');
12 #import('../../../frog/file_system_node.dart');
13 #import('../../../frog/file_system.dart');
14 #import('../../../utils/dartdoc/dartdoc.dart');
15
16 void main() {
17 HtmlDiff.initWorld('../../frog', new NodeFileSystem());
18 initializeDartDoc();
19 var diff = new HtmlDiff();
20 diff.run();
21
22 diff.domToDart.forEach((domMember, htmlMember) {
23 if (domMember.name != htmlMember.name) {
24 var domTypeName = domMember.declaringType.name;
25 var htmlTypeName = htmlMember.declaringType.name.
26 replaceFirst('WrappingImplementation', '');
27 var htmlName = '$htmlTypeName.${htmlMember.name}';
28 if (htmlMember.isConstructor || htmlMember.isFactory) {
29 final separator = htmlMember.name == '' ? '' : '.';
30 htmlName = 'new $htmlTypeName$separator${htmlMember.name}';
31 }
32 print('$domTypeName.${domMember.name} -> ${htmlName}');
33 }
34 });
35
36 for (var type in world.dom.types.getValues()) {
37 if (type.name == null) continue;
38 if (type.definition is FunctionTypeDefinition) continue;
39 for (var member in type.members.getValues()) {
40 if (!member.isPrivate && member.name != 'typeName' &&
41 !diff.domToDart.containsKey(member) &&
42 (member is MethodMember || member is PropertyMember)) {
43 print('No dart:html wrapper for ${type.name}.${member.name}');
44 }
45 }
46 }
47 }
48
49 class HtmlDiff {
50 final Map<Member, Member> domToDart;
51
52 static void initWorld(String frogDir, FileSystem files) {
53 parseOptions(frogDir, [] /* args */, files);
54 initializeWorld(files);
55 world.processScript('dart:html');
56 world.resolveAll();
57 }
58
59 HtmlDiff() : domToDart = <Member, Member>{};
60
61 void run() {
62 final htmlLib = world.libraries['dart:html'];
63 for (var htmlType in htmlLib.types.getValues()) {
64 final domType = htmlToDomType(htmlType);
65 final members = new List.from(htmlType.members.getValues());
66 members.addAll(htmlType.constructors.getValues());
67 htmlType.factories.forEach((f) => members.add(f));
68 for (var member in members) {
69 htmlToDomMembers(member, domType).forEach((m) => domToDart[m] = member);
70 }
71 }
72 }
73
74 Type htmlToDomType(Type htmlType) {
75 if (htmlType.name == null) return;
76 final tags = _getTags(findComment(htmlType.span));
77
78 if (tags.containsKey('domName')) {
79 final domName = tags['domName'];
80 if (domName == 'none') return;
81 // DOMWindow is Chrome-specific, so we don't use it in our annotations.
82 if (domName == 'Window') domName = 'DOMWindow';
83 final domType = world.dom.types[domName];
84 if (domType == null) print('Warning: no dart:dom type named $domName');
85 return domType;
86 } else {
87 if (!htmlType.name.endsWith('WrappingImplementation')) return;
88 final domName = htmlType.name.replaceFirst('WrappingImplementation', '');
89 var domType = world.dom.types[domName];
90 if (domType == null && domName.endsWith('Element')) {
91 domType = world.dom.types['HTML$domName'];
92 }
93 if (domType == null) domType = world.dom.types['WebKit$domName'];
94 if (domType == null) {
95 print('Warning: no dart:dom type matches dart:html ${htmlType.name}');
96 }
97 return domType;
98 }
99 }
100
101 Set<Member> htmlToDomMembers(Member htmlMember, Type domType) {
102 if (htmlMember.isPrivate) return new Set();
103 if (htmlMember is MethodMember) {
104 final tags = _getTags(findComment(htmlMember.span));
105 if (tags.containsKey('domName')) {
106 final domName = tags['domName'];
107 if (domName == 'none') return new Set();
108 return _membersFromName(domName, domType, world.dom);
109 }
110 if (domType == null) return new Set();
111 if (htmlMember.definition == null) return new Set();
112 if (htmlMember.name == 'get\$on') {
113 final members = _members(domType.members['addEventListener']);
114 members.addAll(_members(domType.members['dispatchEvent']));
115 members.addAll(_members(domType.members['removeEventListener']));
116 return members;
117 }
118 if (htmlMember.isFactory && htmlMember.name == '' &&
119 domType.name.endsWith('Event')) {
120 return _members(domType.members['init${domType.name}']);
121 }
122 return _members(_getDomMember(htmlMember.definition.body, domType));
123 } else if (htmlMember is PropertyMember) {
124 final members = new Set();
125 if (htmlMember.getter != null) {
126 members.addAll(htmlToDomMembers(htmlMember.getter, domType));
127 }
128 if (htmlMember.setter != null) {
129 members.addAll(htmlToDomMembers(htmlMember.setter, domType));
130 }
131 return members;
132 } else {
133 return new Set();
134 }
135 }
136
137 Set<Member> _membersFromName(String name, Type defaultType, Library library) {
138 if (!name.contains('.', 0)) {
139 if (defaultType == null) {
140 print('Warning: no default type for ${name}');
141 return new Set();
142 }
143 final member = defaultType.members[name];
144 if (member == null) {
145 print('Warning: no member ${defaultType.name}.${name}');
146 }
147 return _members(member);
148 }
149
150 final splitName = name.split('.');
151 if (splitName.length != 2) {
152 print('Warning: invalid member name ${name}');
153 return new Set();
154 }
155 final type = library.types[splitName[0]];
156 if (type == null) {
157 print('Warning: no ${library.name} type named ${splitName[0]}');
158 return new Set();
159 }
160 final member = type.members[splitName[1]];
161 if (member == null) {
162 print('Warning: no member named $name');
163 }
164 return _members(member);
165 }
166
167 Set<Member> _members(Member m) => m == null ? new Set() : new Set.from([m]);
168
169 Member _getDomMember(Statement stmt, Type domType) {
170 if (stmt is BlockStatement) {
171 final body = stmt.body.filter((s) => !_ignorableStatement(s));
172 if (body.length != 1) return;
173 return _getDomMember(stmt.body[0], domType);
174 } else if (stmt is ReturnStatement) {
175 return _domMemberFromExpression(stmt.value, domType);
176 } else if (stmt is ExpressionStatement) {
177 return _domMemberFromExpression(stmt.body, domType);
178 } else if (stmt is TryStatement) {
179 return _getDomMember(stmt.body, domType);
180 } else if (stmt is IfStatement) {
181 final trueMember = _getDomMember(stmt.trueBranch, domType);
182 final falseMember = _getDomMember(stmt.falseBranch, domType);
183 if (stmt.falseBranch == null || trueMember == falseMember) {
184 return trueMember;
185 }
186 }
187 }
188
189 /**
190 * Whether a statement can be ignored for the purpose of determining the DOM
191 * name of the enclosing method. The Webkit-to-Dart conversion process leaves
192 * behind various throws and returns that we want to ignore.
193 */
194 bool _ignorableStatement(Statement stmt) {
195 if (stmt is BlockStatement) {
196 return Collections.every(stmt.body, (s) => _ignorableStatement(s));
197 } else if (stmt is TryStatement) {
198 return _ignorableStatement(stmt.body);
199 } else if (stmt is IfStatement) {
200 return _ignorableStatement(stmt.trueBranch) &&
201 _ignorableStatement(stmt.falseBranch);
202 } else if (stmt is ReturnStatement) {
203 return stmt.value == null || stmt.value is ThisExpression;
204 } else {
205 return stmt is ThrowStatement;
206 }
207 }
208
209 Member _domMemberFromExpression(Expression expr, Type domType) {
210 if (expr is BinaryExpression && expr.op.kind == TokenKind.ASSIGN) {
211 return _domMemberFromExpression(expr.x, domType);
212 } else if (expr is CallExpression) {
213 if (expr.target is DotExpression && expr.target.self is VarExpression &&
214 expr.target.self.name.name == 'LevelDom' &&
215 (expr.target.name.name.startsWith('wrap') ||
216 expr.target.name.name == 'unwrap')) {
217 return _domMemberFromExpression(expr.arguments[0].value, domType);
218 }
219 return _domMemberFromExpression(expr.target, domType);
220 } else if (expr is DotExpression) {
221 if (expr.self is NewExpression && expr.name.name == '_wrap' &&
222 expr.self.arguments.length == 1) {
223 return _domMemberFromExpression(expr.self.arguments[0].value, domType);
224 } else if (expr.self is VarExpression && expr.self.name.name == '_ptr') {
225 return domType.members[expr.name.name];
226 }
227 final base = _domMemberFromExpression(expr.self, domType);
228 if (base != null && base.returnType != null) {
229 return base.returnType.members[expr.name.name];
230 }
231 } else if (expr is NewExpression && expr.arguments.length == 1) {
232 return _domMemberFromExpression(expr.arguments[0].value, domType);
233 } else {
234 return null;
235 }
236 }
237
238 Map<String, String> _getTags(String comment) {
239 if (comment == null) return const <String, String>{};
240 final re = new RegExp("@([a-zA-Z]+) ([^;]+)(?:;|\$)");
241 final tags = <String, String>{};
242 for (var m in re.allMatches(comment.trim())) {
243 tags[m[1]] = m[2];
244 }
245 return tags;
246 }
247 }
OLDNEW
« no previous file with comments | « client/html/release/html.dart ('k') | client/html/src/DocumentFragmentWrappingImplementation.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698