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 copy |
9 import re | 10 import re |
10 | 11 |
11 _pure_interfaces = set([ | 12 _pure_interfaces = set([ |
12 # TODO(sra): DOMStringMap should be a class implementing Map<String,String>. | 13 # TODO(sra): DOMStringMap should be a class implementing Map<String,String>. |
13 'DOMStringMap', | 14 'DOMStringMap', |
14 'ElementTimeControl', | 15 'ElementTimeControl', |
15 'ElementTraversal', | 16 'ElementTraversal', |
16 'MediaQueryListListener', | 17 'MediaQueryListListener', |
17 'NodeSelector', | 18 'NodeSelector', |
18 'SVGExternalResourcesRequired', | 19 'SVGExternalResourcesRequired', |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 self.dart_type = dart_type | 187 self.dart_type = dart_type |
187 self.default_value = default_value | 188 self.default_value = default_value |
188 | 189 |
189 def __repr__(self): | 190 def __repr__(self): |
190 content = 'name = %s, type_id = %s, dart_type = %s, default_value = %s' % ( | 191 content = 'name = %s, type_id = %s, dart_type = %s, default_value = %s' % ( |
191 self.name, self.type_id, self.dart_type, self.default_value) | 192 self.name, self.type_id, self.dart_type, self.default_value) |
192 return '<ParamInfo(%s)>' % content | 193 return '<ParamInfo(%s)>' % content |
193 | 194 |
194 | 195 |
195 # Given a list of overloaded arguments, render a dart argument. | 196 # Given a list of overloaded arguments, render a dart argument. |
196 def _DartArg(args, interface): | 197 def _DartArg(args, interface, constructor=False): |
197 # Given a list of overloaded arguments, choose a suitable name. | 198 # Given a list of overloaded arguments, choose a suitable name. |
198 def OverloadedName(args): | 199 def OverloadedName(args): |
199 return '_OR_'.join(sorted(set(arg.id for arg in args))) | 200 return '_OR_'.join(sorted(set(arg.id for arg in args))) |
200 | 201 |
201 # Given a list of overloaded arguments, choose a suitable type. | 202 # Given a list of overloaded arguments, choose a suitable type. |
202 def OverloadedType(args): | 203 def OverloadedType(args): |
203 type_ids = sorted(set(arg.type.id for arg in args)) | 204 type_ids = sorted(set(arg.type.id for arg in args)) |
204 dart_types = sorted(set(DartType(arg.type.id) for arg in args)) | 205 dart_types = sorted(set(DartType(arg.type.id) for arg in args)) |
205 if len(dart_types) == 1: | 206 if len(dart_types) == 1: |
206 if len(type_ids) == 1: | 207 if len(type_ids) == 1: |
207 return (type_ids[0], dart_types[0]) | 208 return (type_ids[0], dart_types[0]) |
208 else: | 209 else: |
209 return (None, dart_types[0]) | 210 return (None, dart_types[0]) |
210 else: | 211 else: |
211 return (None, TypeName(type_ids, interface)) | 212 return (None, TypeName(type_ids, interface)) |
212 | 213 |
| 214 def NeedsDefaultValue(argument): |
| 215 if not argument: |
| 216 return True |
| 217 if 'Callback' in argument.ext_attrs: |
| 218 # Callbacks with 'Optional=XXX' are treated as optional arguments. |
| 219 return 'Optional' in argument.ext_attrs |
| 220 if constructor: |
| 221 # FIXME: Constructors with 'Optional=XXX' shouldn't be treated as |
| 222 # optional arguments. |
| 223 return 'Optional' in argument.ext_attrs |
| 224 return False |
| 225 |
213 filtered = filter(None, args) | 226 filtered = filter(None, args) |
214 optional = any(not arg or arg.is_optional for arg in args) | 227 needs_default_value = any(NeedsDefaultValue(arg) for arg in args) |
215 (type_id, dart_type) = OverloadedType(filtered) | 228 (type_id, dart_type) = OverloadedType(filtered) |
216 name = OverloadedName(filtered) | 229 name = OverloadedName(filtered) |
217 if optional: | 230 if needs_default_value: |
218 return ParamInfo(name, type_id, dart_type, 'null') | 231 return ParamInfo(name, type_id, dart_type, 'null') |
219 else: | 232 else: |
220 return ParamInfo(name, type_id, dart_type, None) | 233 return ParamInfo(name, type_id, dart_type, None) |
221 | 234 |
| 235 def IsOptional(argument): |
| 236 return ('Optional' in argument.ext_attrs and |
| 237 argument.ext_attrs['Optional'] == None) |
222 | 238 |
223 def AnalyzeOperation(interface, operations): | 239 def AnalyzeOperation(interface, operations): |
224 """Makes operation calling convention decision for a set of overloads. | 240 """Makes operation calling convention decision for a set of overloads. |
225 | 241 |
226 Returns: An OperationInfo object. | 242 Returns: An OperationInfo object. |
227 """ | 243 """ |
228 | 244 |
| 245 # split operations with optional args into multiple operations |
| 246 split_operations = [] |
| 247 for operation in operations: |
| 248 for i in range(0, len(operation.arguments)): |
| 249 if IsOptional(operation.arguments[i]): |
| 250 new_operation = copy.deepcopy(operation) |
| 251 new_operation.arguments = new_operation.arguments[:i] |
| 252 split_operations.append(new_operation) |
| 253 split_operations.append(operation) |
| 254 |
229 # Zip together arguments from each overload by position, then convert | 255 # Zip together arguments from each overload by position, then convert |
230 # to a dart argument. | 256 # to a dart argument. |
231 args = map(lambda *args: _DartArg(args, interface), | 257 args = map(lambda *args: _DartArg(args, interface), |
232 *(op.arguments for op in operations)) | 258 *(op.arguments for op in split_operations)) |
233 | 259 |
234 info = OperationInfo() | 260 info = OperationInfo() |
235 info.overloads = operations | 261 info.overloads = split_operations |
236 info.declared_name = operations[0].id | 262 info.declared_name = operations[0].id |
237 info.name = operations[0].ext_attrs.get('DartName', info.declared_name) | 263 info.name = operations[0].ext_attrs.get('DartName', info.declared_name) |
238 info.constructor_name = None | 264 info.constructor_name = None |
239 info.js_name = info.declared_name | 265 info.js_name = info.declared_name |
240 info.type_name = DartType(operations[0].type.id) # TODO: widen. | 266 info.type_name = DartType(operations[0].type.id) # TODO: widen. |
241 info.param_infos = args | 267 info.param_infos = args |
242 return info | 268 return info |
243 | 269 |
244 | 270 |
245 def AnalyzeConstructor(interface): | 271 def AnalyzeConstructor(interface): |
246 """Returns an OperationInfo object for the constructor. | 272 """Returns an OperationInfo object for the constructor. |
247 | 273 |
248 Returns None if the interface has no Constructor. | 274 Returns None if the interface has no Constructor. |
249 """ | 275 """ |
250 def GetArgs(func_value): | 276 def GetArgs(func_value): |
251 return map(lambda arg: _DartArg([arg], interface), func_value.arguments) | 277 return map(lambda arg: _DartArg([arg], interface, True), |
| 278 func_value.arguments) |
252 | 279 |
253 if 'Constructor' in interface.ext_attrs: | 280 if 'Constructor' in interface.ext_attrs: |
254 name = None | 281 name = None |
255 func_value = interface.ext_attrs.get('Constructor') | 282 func_value = interface.ext_attrs.get('Constructor') |
256 if func_value: | 283 if func_value: |
257 # [Constructor(param,...)] | 284 # [Constructor(param,...)] |
258 args = GetArgs(func_value) | 285 args = GetArgs(func_value) |
259 idl_args = func_value.arguments | 286 idl_args = func_value.arguments |
260 else: # [Constructor] | 287 else: # [Constructor] |
261 args = [] | 288 args = [] |
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 '"SVGAnimatedListPropertyTearOff.h"', | 795 '"SVGAnimatedListPropertyTearOff.h"', |
769 '"SVGTransformListPropertyTearOff.h"', | 796 '"SVGTransformListPropertyTearOff.h"', |
770 '"SVGPathSegListPropertyTearOff.h"', | 797 '"SVGPathSegListPropertyTearOff.h"', |
771 ] | 798 ] |
772 | 799 |
773 def GetIDLTypeInfo(idl_type_name): | 800 def GetIDLTypeInfo(idl_type_name): |
774 match = re.match(r'sequence<(\w+)>$', idl_type_name) | 801 match = re.match(r'sequence<(\w+)>$', idl_type_name) |
775 if match: | 802 if match: |
776 return SequenceIDLTypeInfo(idl_type_name, GetIDLTypeInfo(match.group(1))) | 803 return SequenceIDLTypeInfo(idl_type_name, GetIDLTypeInfo(match.group(1))) |
777 return _idl_type_registry.get(idl_type_name, IDLTypeInfo(idl_type_name)) | 804 return _idl_type_registry.get(idl_type_name, IDLTypeInfo(idl_type_name)) |
OLD | NEW |