OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 4 # BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 """This module provides shared functionality for systems to generate | 6 """This module provides shared functionality for systems to generate |
7 Dart APIs from the IDL database.""" | 7 Dart APIs from the IDL database.""" |
8 | 8 |
9 import re | 9 import re |
10 | 10 |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 # against dart:dom to load in a worker isolate. | 218 # against dart:dom to load in a worker isolate. |
219 return '*' + javascript_binding_name | 219 return '*' + javascript_binding_name |
220 | 220 |
221 | 221 |
222 def MatchSourceFilter(filter, thing): | 222 def MatchSourceFilter(filter, thing): |
223 if not filter: | 223 if not filter: |
224 return True | 224 return True |
225 else: | 225 else: |
226 return any(token in thing.annotations for token in filter) | 226 return any(token in thing.annotations for token in filter) |
227 | 227 |
228 def AnalyzeOperation(interface, operations): | |
229 """Makes operation calling convention decision for a set of overloads. | |
230 | 228 |
231 Returns: An OperationInfo object. | 229 # Given a list of overloaded arguments, render a dart argument. |
232 """ | 230 def _DartArg(args, interface): |
233 | |
234 # Zip together arguments from each overload by position, then convert | |
235 # to a dart argument. | |
236 | |
237 # Given a list of overloaded arguments, choose a suitable name. | 231 # Given a list of overloaded arguments, choose a suitable name. |
238 def OverloadedName(args): | 232 def OverloadedName(args): |
239 return '_OR_'.join(sorted(set(arg.id for arg in args))) | 233 return '_OR_'.join(sorted(set(arg.id for arg in args))) |
240 | 234 |
241 # Given a list of overloaded arguments, choose a suitable type. | 235 # Given a list of overloaded arguments, choose a suitable type. |
242 def OverloadedType(args): | 236 def OverloadedType(args): |
243 typeIds = sorted(set(arg.type.id for arg in args)) | 237 typeIds = sorted(set(arg.type.id for arg in args)) |
244 if len(typeIds) == 1: | 238 if len(typeIds) == 1: |
245 return typeIds[0] | 239 return typeIds[0] |
246 else: | 240 else: |
247 return TypeName(typeIds, interface) | 241 return TypeName(typeIds, interface) |
248 | 242 |
249 # Given a list of overloaded arguments, render a dart argument. | 243 filtered = filter(None, args) |
250 def DartArg(args): | 244 optional = any(not arg or arg.is_optional for arg in args) |
251 filtered = filter(None, args) | 245 type = OverloadedType(filtered) |
252 optional = any(not arg or arg.is_optional for arg in args) | 246 name = OverloadedName(filtered) |
253 type = OverloadedType(filtered) | 247 if optional: |
254 name = OverloadedName(filtered) | 248 return (name, type, 'null') |
255 if optional: | 249 else: |
256 return (name, type, 'null') | 250 return (name, type, None) |
257 else: | |
258 return (name, type, None) | |
259 | 251 |
260 args = map(lambda *args: DartArg(args), | 252 |
| 253 def AnalyzeOperation(interface, operations): |
| 254 """Makes operation calling convention decision for a set of overloads. |
| 255 |
| 256 Returns: An OperationInfo object. |
| 257 """ |
| 258 |
| 259 # Zip together arguments from each overload by position, then convert |
| 260 # to a dart argument. |
| 261 args = map(lambda *args: _DartArg(args, interface), |
261 *(op.arguments for op in operations)) | 262 *(op.arguments for op in operations)) |
262 | 263 |
263 info = OperationInfo() | 264 info = OperationInfo() |
264 info.overloads = operations | 265 info.overloads = operations |
265 info.declared_name = operations[0].id | 266 info.declared_name = operations[0].id |
266 info.name = operations[0].ext_attrs.get('DartName', info.declared_name) | 267 info.name = operations[0].ext_attrs.get('DartName', info.declared_name) |
267 info.js_name = info.declared_name | 268 info.js_name = info.declared_name |
268 info.type_name = operations[0].type.id # TODO: widen. | 269 info.type_name = operations[0].type.id # TODO: widen. |
269 info.arg_infos = args | 270 info.arg_infos = args |
270 return info | 271 return info |
271 | 272 |
| 273 |
| 274 def AnalyzeConstructor(interface): |
| 275 """Returns an OperationInfo object for the constructor. |
| 276 |
| 277 Returns None if the interface has no Constructor. |
| 278 """ |
| 279 def GetArgs(func_value): |
| 280 return map(lambda arg: _DartArg([arg], interface), func_value.arguments) |
| 281 |
| 282 if 'Constructor' in interface.ext_attrs: |
| 283 name = None |
| 284 func_value = interface.ext_attrs.get('Constructor') |
| 285 if func_value: |
| 286 # [Constructor(param,...)] |
| 287 args = GetArgs(func_value) |
| 288 else: # [Constructor] |
| 289 args = [] |
| 290 else: |
| 291 func_value = interface.ext_attrs.get('NamedConstructor') |
| 292 if func_value: |
| 293 name = func_value.id |
| 294 args = GetArgs(func_value) |
| 295 else: |
| 296 return None |
| 297 |
| 298 info = OperationInfo() |
| 299 info.overloads = None # [func_value] |
| 300 info.declared_name = name |
| 301 info.name = name |
| 302 info.js_name = name |
| 303 info.type_name = interface.id |
| 304 info.arg_infos = args |
| 305 return info |
| 306 |
| 307 |
272 def RecognizeCallback(interface): | 308 def RecognizeCallback(interface): |
273 """Returns the info for the callback method if the interface smells like a | 309 """Returns the info for the callback method if the interface smells like a |
274 callback. | 310 callback. |
275 """ | 311 """ |
276 if 'Callback' not in interface.ext_attrs: return None | 312 if 'Callback' not in interface.ext_attrs: return None |
277 handlers = [op for op in interface.operations if op.id == 'handleEvent'] | 313 handlers = [op for op in interface.operations if op.id == 'handleEvent'] |
278 if not handlers: return None | 314 if not handlers: return None |
279 if not (handlers == interface.operations): return None | 315 if not (handlers == interface.operations): return None |
280 return AnalyzeOperation(interface, handlers) | 316 return AnalyzeOperation(interface, handlers) |
281 | 317 |
282 def IsDartListType(type): | 318 def IsDartListType(type): |
283 return type == 'List' or type.startswith('List<') | 319 return type == 'List' or type.startswith('List<') |
284 | 320 |
285 def IsDartCollectionType(type): | 321 def IsDartCollectionType(type): |
286 return IsDartListType(type) | 322 return IsDartListType(type) |
287 | 323 |
288 def FindMatchingAttribute(interface, attr1): | 324 def FindMatchingAttribute(interface, attr1): |
289 matches = [attr2 for attr2 in interface.attributes | 325 matches = [attr2 for attr2 in interface.attributes |
290 if attr1.id == attr2.id | 326 if attr1.id == attr2.id |
291 and attr1.is_fc_getter == attr2.is_fc_getter | 327 and attr1.is_fc_getter == attr2.is_fc_getter |
292 and attr1.is_fc_setter == attr2.is_fc_setter] | 328 and attr1.is_fc_setter == attr2.is_fc_setter] |
293 if matches: | 329 if matches: |
294 assert len(matches) == 1 | 330 assert len(matches) == 1 |
295 return matches[0] | 331 return matches[0] |
296 return None | 332 return None |
297 | 333 |
| 334 |
298 class OperationInfo(object): | 335 class OperationInfo(object): |
299 """Holder for various derived information from a set of overloaded operations. | 336 """Holder for various derived information from a set of overloaded operations. |
300 | 337 |
301 Attributes: | 338 Attributes: |
302 overloads: A list of IDL operation overloads with the same name. | 339 overloads: A list of IDL operation overloads with the same name. |
303 name: A string, the simple name of the operation. | 340 name: A string, the simple name of the operation. |
304 type_name: A string, the name of the return type of the operation. | 341 type_name: A string, the name of the return type of the operation. |
305 arg_infos: A list of (name, type, default_value) tuples. | 342 arg_infos: A list of (name, type, default_value) tuples. |
306 default_value is None for mandatory arguments. | 343 default_value is None for mandatory arguments. |
307 """ | 344 """ |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
561 | 598 |
562 original_idl_types = { | 599 original_idl_types = { |
563 } | 600 } |
564 | 601 |
565 def GetIDLTypeInfo(idl_type): | 602 def GetIDLTypeInfo(idl_type): |
566 idl_type_name = original_idl_types.get(idl_type, idl_type.id) | 603 idl_type_name = original_idl_types.get(idl_type, idl_type.id) |
567 return GetIDLTypeInfoByName(idl_type_name) | 604 return GetIDLTypeInfoByName(idl_type_name) |
568 | 605 |
569 def GetIDLTypeInfoByName(idl_type_name): | 606 def GetIDLTypeInfoByName(idl_type_name): |
570 return _idl_type_registry.get(idl_type_name, IDLTypeInfo(idl_type_name)) | 607 return _idl_type_registry.get(idl_type_name, IDLTypeInfo(idl_type_name)) |
OLD | NEW |