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

Side by Side Diff: client/dom/scripts/generator.py

Issue 9403004: Wrapperless dart:html generator (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Final version to check in. changes generator script but doesn't check in an active version of the … Created 8 years, 10 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 | « client/dom/scripts/database.py ('k') | client/dom/scripts/idlnode.py » ('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 #!/usr/bin/python
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
3 # for details. All rights reserved. Use of this source code is governed by a
4 # BSD-style license that can be found in the LICENSE file.
5
6 """This module provides shared functionality for systems to generate
7 Dart APIs from the IDL database."""
8
9 import re
10
11 # IDL->Dart primitive types conversion.
12 _idl_to_dart_type_conversions = {
13 'any': 'Object',
14 'any[]': 'List',
15 'custom': 'Dynamic',
16 'boolean': 'bool',
17 'DOMObject': 'Object',
18 'DOMString': 'String',
19 'DOMStringList': 'List<String>',
20 'DOMTimeStamp': 'int',
21 'Date': 'Date',
22 # Map to num to enable callers to pass in Dart int, rational
23 # types. Our implementations will need to convert these to
24 # doubles or floats as needed.
25 'double': 'num',
26 'float': 'num',
27 'int': 'int',
28 # Map to extra precision - int is a bignum in Dart.
29 'long': 'int',
30 'long long': 'int',
31 'object': 'Object',
32 # Map to extra precision - int is a bignum in Dart.
33 'short': 'int',
34 'string': 'String',
35 'void': 'void',
36 'Array': 'List',
37 'sequence': 'List',
38 # TODO(sra): Come up with some meaningful name so that where this appears in
39 # the documentation, the user is made aware that only a limited subset of
40 # serializable types are actually permitted.
41 'SerializedScriptValue': 'Dynamic',
42 # TODO(vsm): Automatically recognize types defined in src.
43 'TimeoutHandler': 'TimeoutHandler',
44 'RequestAnimationFrameCallback': 'RequestAnimationFrameCallback',
45
46 # TODO(sra): Flags is really a dictionary: {create:bool, exclusive:bool}
47 # http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#the-flags-interfa ce
48 'WebKitFlags': 'Object',
49 }
50
51 _dart_to_idl_type_conversions = dict((v,k) for k, v in
52 _idl_to_dart_type_conversions.iteritems())
53
54 #
55 # Identifiers that are used in the IDL than need to be treated specially because
56 # *some* JavaScript processors forbid them as properties.
57 #
58 _javascript_keywords = ['delete', 'continue']
59
60 #
61 # Interface version of the DOM needs to delegate typed array constructors to a
62 # factory provider.
63 #
64 interface_factories = {
65 'Float32Array': '_TypedArrayFactoryProvider',
66 'Float64Array': '_TypedArrayFactoryProvider',
67 'Int8Array': '_TypedArrayFactoryProvider',
68 'Int16Array': '_TypedArrayFactoryProvider',
69 'Int32Array': '_TypedArrayFactoryProvider',
70 'Uint8Array': '_TypedArrayFactoryProvider',
71 'Uint16Array': '_TypedArrayFactoryProvider',
72 'Uint32Array': '_TypedArrayFactoryProvider',
73 'Uint8ClampedArray': '_TypedArrayFactoryProvider',
74 }
75
76 #
77 # Custom methods that must be implemented by hand.
78 #
79 _custom_methods = set([
80 ('DOMWindow', 'setInterval'),
81 ('DOMWindow', 'setTimeout'),
82 ('WorkerContext', 'setInterval'),
83 ('WorkerContext', 'setTimeout'),
84 ('CanvasRenderingContext2D', 'setFillStyle'),
85 ('CanvasRenderingContext2D', 'setStrokeStyle'),
86 ('CanvasRenderingContext2D', 'setFillStyle'),
87 ])
88
89 #
90 # Custom getters that must be implemented by hand.
91 #
92 _custom_getters = set([
93 ('DOMWindow', 'localStorage'),
94 ])
95
96 #
97 # Custom native specs for the Frog dom.
98 #
99 _frog_dom_custom_native_specs = {
100 # Decorate the singleton Console object, if present (workers do not have a
101 # console).
102 'Console': "=(typeof console == 'undefined' ? {} : console)",
103
104 # DOMWindow aliased with global scope.
105 'DOMWindow': '@*DOMWindow',
106 }
107
108 #
109 # Simple method substitution when one method had different names on different
110 # browsers, but are otherwise identical. The alternates are tried in order and
111 # the first one defined is used.
112 #
113 # This can be probably be removed when Chrome renames initWebKitWheelEvent to
114 # initWheelEvent.
115 #
116 _alternate_methods = {
117 ('WheelEvent', 'initWheelEvent'): ['initWebKitWheelEvent', 'initWheelEvent']
118 }
119
120 def ConvertPrimitiveType(type_name):
121 if type_name.startswith('unsigned '):
122 type_name = type_name[len('unsigned '):]
123
124 if type_name in _idl_to_dart_type_conversions:
125 # Primitive type conversion
126 return _idl_to_dart_type_conversions[type_name]
127 return None
128
129 def IsPrimitiveType(type_name):
130 return (ConvertPrimitiveType(type_name) is not None or
131 type_name in _dart_to_idl_type_conversions)
132
133 def MaybeListElementTypeName(type_name):
134 """Returns the List element type T from string of form "List<T>", or None."""
135 match = re.match(r'List<(\w*)>$', type_name)
136 if match:
137 return match.group(1)
138 return None
139
140 def MaybeListElementType(interface):
141 """Returns the List element type T, or None in interface does not implement
142 List<T>.
143 """
144 for parent in interface.parents:
145 element_type = MaybeListElementTypeName(parent.type.id)
146 if element_type:
147 return element_type
148 return None
149
150 def MaybeTypedArrayElementType(interface):
151 """Returns the typed array element type, or None in interface is not a
152 TypedArray.
153 """
154 # Typed arrays implement ArrayBufferView and List<T>.
155 for parent in interface.parents:
156 if parent.type.id == 'ArrayBufferView':
157 return MaybeListElementType(interface)
158 if parent.type.id == 'Uint8Array':
159 return 'int'
160 return None
161
162 def MakeNativeSpec(javascript_binding_name):
163 if javascript_binding_name in _frog_dom_custom_native_specs:
164 return _frog_dom_custom_native_specs[javascript_binding_name]
165 else:
166 # Make the class 'hidden' so it is dynamically patched at runtime. This
167 # is useful not only for browser compat, but to allow code that links
168 # against dart:dom to load in a worker isolate.
169 return '*' + javascript_binding_name
170
171
172 def MatchSourceFilter(filter, thing):
173 if not filter:
174 return True
175 else:
176 return any(token in thing.annotations for token in filter)
177
178 def AnalyzeOperation(interface, operations):
179 """Makes operation calling convention decision for a set of overloads.
180
181 Returns: An OperationInfo object.
182 """
183
184 # Zip together arguments from each overload by position, then convert
185 # to a dart argument.
186
187 # Given a list of overloaded arguments, choose a suitable name.
188 def OverloadedName(args):
189 return '_OR_'.join(sorted(set(arg.id for arg in args)))
190
191 # Given a list of overloaded arguments, choose a suitable type.
192 def OverloadedType(args):
193 typeIds = sorted(set(arg.type.id for arg in args))
194 if len(typeIds) == 1:
195 return typeIds[0]
196 else:
197 return TypeName(typeIds, interface)
198
199 # Given a list of overloaded arguments, render a dart argument.
200 def DartArg(args):
201 filtered = filter(None, args)
202 optional = any(not arg or arg.is_optional for arg in args)
203 type = OverloadedType(filtered)
204 name = OverloadedName(filtered)
205 if optional:
206 return (name, type, 'null')
207 else:
208 return (name, type, None)
209
210 args = map(lambda *args: DartArg(args),
211 *(op.arguments for op in operations))
212
213 info = OperationInfo()
214 info.overloads = operations
215 info.declared_name = operations[0].id
216 info.name = operations[0].ext_attrs.get('DartName', info.declared_name)
217 info.js_name = info.declared_name
218 info.type_name = operations[0].type.id # TODO: widen.
219 info.arg_infos = args
220 return info
221
222 def RecognizeCallback(interface):
223 """Returns the info for the callback method if the interface smells like a
224 callback.
225 """
226 if 'Callback' not in interface.ext_attrs: return None
227 handlers = [op for op in interface.operations if op.id == 'handleEvent']
228 if not handlers: return None
229 if not (handlers == interface.operations): return None
230 return AnalyzeOperation(interface, handlers)
231
232 def IsDartListType(type):
233 return type == 'List' or type.startswith('List<')
234
235 def IsDartCollectionType(type):
236 return IsDartListType(type)
237
238 def FindMatchingAttribute(interface, attr1):
239 matches = [attr2 for attr2 in interface.attributes
240 if attr1.id == attr2.id
241 and attr1.is_fc_getter == attr2.is_fc_getter
242 and attr1.is_fc_setter == attr2.is_fc_setter]
243 if matches:
244 assert len(matches) == 1
245 return matches[0]
246 return None
247
248 class OperationInfo(object):
249 """Holder for various derived information from a set of overloaded operations.
250
251 Attributes:
252 overloads: A list of IDL operation overloads with the same name.
253 name: A string, the simple name of the operation.
254 type_name: A string, the name of the return type of the operation.
255 arg_infos: A list of (name, type, default_value) tuples.
256 default_value is None for mandatory arguments.
257 """
258
259 def ParametersInterfaceDeclaration(self):
260 """Returns a formatted string declaring the parameters for the interface."""
261 return self._FormatArgs(self.arg_infos, True)
262
263 def ParametersImplementationDeclaration(self, rename_type=None):
264 """Returns a formatted string declaring the parameters for the
265 implementation.
266
267 Args:
268 rename_type: A function that allows the types to be renamed.
269 """
270 args = self.arg_infos
271 if rename_type:
272 args = [(name, rename_type(type), default)
273 for (name, type, default) in args]
274 return self._FormatArgs(args, False)
275
276 def ParametersAsArgumentList(self):
277 """Returns a formatted string declaring the parameters names as an argument
278 list.
279 """
280 return ', '.join(map(lambda arg_info: arg_info[0], self.arg_infos))
281
282 def _FormatArgs(self, args, is_interface):
283 def FormatArg(arg_info):
284 """Returns an argument declaration fragment for an argument info tuple."""
285 (name, type, default) = arg_info
286 if default:
287 return '%s %s = %s' % (type, name, default)
288 else:
289 return '%s %s' % (type, name)
290
291 required = []
292 optional = []
293 for (name, type, default) in args:
294 if default:
295 if is_interface:
296 optional.append((name, type, None)) # Default values illegal.
297 else:
298 optional.append((name, type, default))
299 else:
300 if optional:
301 raise Exception('Optional arguments cannot precede required ones: '
302 + str(args))
303 required.append((name, type, None))
304 argtexts = map(FormatArg, required)
305 if optional:
306 argtexts.append('[' + ', '.join(map(FormatArg, optional)) + ']')
307 return ', '.join(argtexts)
308
309
310 def AttributeOutputOrder(a, b):
311 """Canonical output ordering for attributes."""
312 # Getters before setters:
313 if a.id < b.id: return -1
314 if a.id > b.id: return 1
315 if a.is_fc_setter < b.is_fc_setter: return -1
316 if a.is_fc_setter > b.is_fc_setter: return 1
317 return 0
318
319 def ConstantOutputOrder(a, b):
320 """Canonical output ordering for constants."""
321 if a.id < b.id: return -1
322 if a.id > b.id: return 1
323 return 0
324
325
326 def _FormatNameList(names):
327 """Returns JavaScript array literal expression with one name per line."""
328 #names = sorted(names)
329 if len(names) <= 1:
330 expression_string = str(names) # e.g. ['length']
331 else:
332 expression_string = ',\n '.join(str(names).split(','))
333 expression_string = expression_string.replace('[', '[\n ')
334 return expression_string
335
336
337 def IndentText(text, indent):
338 """Format lines of text with indent."""
339 def FormatLine(line):
340 if line.strip():
341 return '%s%s\n' % (indent, line)
342 else:
343 return '\n'
344 return ''.join(FormatLine(line) for line in text.split('\n'))
345
346 # Given a sorted sequence of type identifiers, return an appropriate type
347 # name
348 def TypeName(typeIds, interface):
349 # Dynamically type this field for now.
350 return 'var'
351
OLDNEW
« no previous file with comments | « client/dom/scripts/database.py ('k') | client/dom/scripts/idlnode.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698