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

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: Code review changes 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 htmlName = 'new $htmlTypeName${htmlMember.name == '' ? '' : '.'}' +
30 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 continue;
Jacob 2011/11/21 19:47:23 nit: only use the continue keyword when needed. S
nweiz 2011/11/21 23:01:32 Done.
44 }
45 print('No dart:html wrapper for ${type.name}.${member.name}');
46 }
47 }
48 }
49
50 class HtmlDiff {
51 final Map<Member, Member> domToDart;
52
53 static void initWorld(String frogDir, FileSystem files) {
54 parseOptions(frogDir, [] /* args */, files);
55 initializeWorld(files);
56 world.processScript('dart:html');
57 world.resolveAll();
58 }
59
60 HtmlDiff() : domToDart = <Member, Member>{};
61
62 void run() {
63 final htmlLib = world.libraries['dart:html'];
64 for (var htmlType in htmlLib.types.getValues()) {
65 final domType = htmlToDomType(htmlType);
66 final members = new List.from(htmlType.members.getValues());
67 members.addAll(htmlType.constructors.getValues());
68 htmlType.factories.forEach((f) => members.add(f));
69 for (var member in members) {
70 htmlToDomMembers(member, domType).forEach((m) => domToDart[m] = member);
71 }
72 }
73 }
74
75 Type htmlToDomType(Type htmlType) {
76 if (htmlType.name == null) return;
77 final tags = _getTags(findComment(htmlType.span));
78
79 if (tags.containsKey('domName')) {
80 final domName = tags['domName'];
81 if (domName == 'none') return;
82 final domType = world.dom.types[domName];
83 if (domType == null) print('Warning: no dart:dom type named $domName');
84 return domType;
85 } else {
86 if (!htmlType.name.endsWith('WrappingImplementation')) return;
87 final domName = htmlType.name.replaceFirst('WrappingImplementation', '');
88 var domType = world.dom.types[domName];
89 if (domType == null && domName.endsWith('Element')) {
90 domType = world.dom.types['HTML$domName'];
91 }
92 if (domType == null) domType = world.dom.types['WebKit$domName'];
93 if (domType == null) {
94 print('Warning: no dart:dom type matches dart:html ${htmlType.name}');
95 }
96 return domType;
97 }
98 }
99
100 Set<Member> htmlToDomMembers(Member htmlMember, Type domType) {
101 if (htmlMember.isPrivate) return new Set();
102 if (htmlMember is MethodMember) {
103 final tags = _getTags(findComment(htmlMember.span));
104 if (tags.containsKey('domName')) {
105 final domName = tags['domName'];
106 if (domName == 'none') return new Set();
107 return _membersFromName(domName, domType, world.dom);
108 }
109 if (domType == null) return new Set();
110 if (htmlMember.definition == null) return new Set();
111 if (htmlMember.name == 'get\$on') {
112 final members = _members(domType.members['addEventListener']);
113 members.addAll(_members(domType.members['dispatchEvent']));
114 members.addAll(_members(domType.members['removeEventListener']));
115 return members;
116 }
117 if (htmlMember.isFactory && htmlMember.name == '' &&
118 domType.name.endsWith('Event')) {
119 return _members(domType.members['init${domType.name}']);
120 }
121 return _members(_getDomMember(htmlMember.definition.body, domType));
122 } else if (htmlMember is PropertyMember) {
123 final members = new Set();
124 if (htmlMember.getter != null) {
125 members.addAll(htmlToDomMembers(htmlMember.getter, domType));
126 }
127 if (htmlMember.setter != null) {
128 members.addAll(htmlToDomMembers(htmlMember.setter, domType));
129 }
130 return members;
131 } else {
132 return new Set();
133 }
134 }
135
136 Set<Member> _membersFromName(String name, Type defaultType, Library library) {
137 if (!name.contains('.', 0)) {
138 if (defaultType == null) {
139 print('Warning: no default type for ${name}');
140 return new Set();
141 }
142 final member = defaultType.members[name];
143 if (member == null) {
144 print('Warning: no member ${defaultType.name}.${name}');
145 }
146 return _members(member);
147 }
148
149 final splitName = name.split('.');
150 if (splitName.length != 2) {
151 print('Warning: invalid member name ${name}');
152 return new Set();
153 }
154 final type = library.types[splitName[0]];
155 if (type == null) {
156 print('Warning: no ${library.name} type named ${splitName[0]}');
157 return new Set();
158 }
159 final member = type.members[splitName[1]];
160 if (member == null) {
161 print('Warning: no member named $name');
162 }
163 return _members(member);
164 }
165
166 Set<Member> _members(Member m) => m == null ? new Set() : new Set.from([m]);
167
168 Member _getDomMember(Statement stmt, Type domType) {
169 if (stmt is BlockStatement) {
170 final body = stmt.body.filter((s) => !_ignorableStatement(s));
171 if (body.length != 1) return;
172 return _getDomMember(stmt.body[0], domType);
173 } else if (stmt is ReturnStatement) {
174 return _domMemberFromExpression(stmt.value, domType);
175 } else if (stmt is ExpressionStatement) {
176 return _domMemberFromExpression(stmt.body, domType);
177 } else if (stmt is TryStatement) {
178 return _getDomMember(stmt.body, domType);
179 } else if (stmt is IfStatement) {
180 final trueMember = _getDomMember(stmt.trueBranch, domType);
181 final falseMember = _getDomMember(stmt.falseBranch, domType);
182 if (stmt.falseBranch == null || trueMember == falseMember) {
183 return trueMember;
184 }
185 }
186 }
187
188 /**
189 * Whether a statement can be ignored for the purpose of determining the DOM
190 * name of the enclosing method. The Webkit-to-Dart conversion process leaves
191 * behind various throws and returns that we want to ignore.
192 */
193 bool _ignorableStatement(Statement stmt) {
194 if (stmt is BlockStatement) {
195 return Collections.every(stmt.body, (s) => _ignorableStatement(s));
196 } else if (stmt is TryStatement) {
197 return _ignorableStatement(stmt.body);
198 } else if (stmt is IfStatement) {
199 return _ignorableStatement(stmt.trueBranch) &&
200 _ignorableStatement(stmt.falseBranch);
201 } else if (stmt is ReturnStatement) {
202 return stmt.value == null || stmt.value is ThisExpression;
203 } else {
204 return stmt is ThrowStatement;
205 }
206 }
207
208 Member _domMemberFromExpression(Expression expr, Type domType) {
209 if (expr is BinaryExpression && expr.op.kind == TokenKind.ASSIGN) {
210 return _domMemberFromExpression(expr.x, domType);
211 } else if (expr is CallExpression) {
212 if (expr.target is DotExpression && expr.target.self is VarExpression &&
213 expr.target.self.name.name == 'LevelDom' &&
214 (expr.target.name.name.startsWith('wrap') ||
215 expr.target.name.name == 'unwrap')) {
216 return _domMemberFromExpression(expr.arguments[0].value, domType);
217 }
218 return _domMemberFromExpression(expr.target, domType);
219 } else if (expr is DotExpression) {
220 if (expr.self is NewExpression && expr.name.name == '_wrap' &&
221 expr.self.arguments.length == 1) {
222 return _domMemberFromExpression(expr.self.arguments[0].value, domType);
223 } else if (expr.self is VarExpression && expr.self.name.name == '_ptr') {
224 return domType.members[expr.name.name];
225 }
226 final base = _domMemberFromExpression(expr.self, domType);
227 if (base != null && base.returnType != null) {
228 return base.returnType.members[expr.name.name];
229 }
230 } else if (expr is NewExpression && expr.arguments.length == 1) {
231 return _domMemberFromExpression(expr.arguments[0].value, domType);
232 } else {
233 return null;
234 }
235 }
236
237 Map<String, String> _getTags(String comment) {
238 if (comment == null) return const <String, String>{};
239 final re = new RegExp("@([a-zA-Z]+) ([^;]+)(?:;|\$)");
240 final tags = <String, String>{};
241 for (var m in re.allMatches(comment.trim())) {
242 tags[m[1]] = m[2];
243 }
244 return tags;
245 }
246 }
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