Chromium Code Reviews| 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 generates Dart APIs from the IDL database.""" | 6 """This module generates Dart APIs from the IDL database.""" |
| 7 | 7 |
| 8 import emitter | 8 import emitter |
| 9 import idlnode | 9 import idlnode |
| 10 import logging | 10 import logging |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 358 interface.parents = filter(HasAnnotations, interface.parents) | 358 interface.parents = filter(HasAnnotations, interface.parents) |
| 359 else: | 359 else: |
| 360 database.DeleteInterface(interface.id) | 360 database.DeleteInterface(interface.id) |
| 361 | 361 |
| 362 self.FilterMembersWithUnidentifiedTypes(database) | 362 self.FilterMembersWithUnidentifiedTypes(database) |
| 363 | 363 |
| 364 | 364 |
| 365 def Generate(self, database, output_dir, | 365 def Generate(self, database, output_dir, |
| 366 module_source_preference=[], source_filter=None, | 366 module_source_preference=[], source_filter=None, |
| 367 super_database=None, common_prefix=None, super_map={}, | 367 super_database=None, common_prefix=None, super_map={}, |
| 368 lib_dir = None): | 368 lib_dir=None, systems=[]): |
| 369 """Generates Dart and JS files for the loaded interfaces. | 369 """Generates Dart and JS files for the loaded interfaces. |
| 370 | 370 |
| 371 Args: | 371 Args: |
| 372 database -- database containing interfaces to generate code for. | 372 database -- database containing interfaces to generate code for. |
| 373 output_dir -- directory to write generated files to. | 373 output_dir -- directory to write generated files to. |
| 374 module_source_preference -- priority order list of source annotations to | 374 module_source_preference -- priority order list of source annotations to |
| 375 use when choosing a module name, if none specified uses the module name | 375 use when choosing a module name, if none specified uses the module name |
| 376 from the database. | 376 from the database. |
| 377 source_filter -- if specified, only outputs interfaces that have one of | 377 source_filter -- if specified, only outputs interfaces that have one of |
| 378 these source annotation and rewrites the names of superclasses not | 378 these source annotation and rewrites the names of superclasses not |
| 379 marked with this source to use the common prefix. | 379 marked with this source to use the common prefix. |
| 380 super_database -- database containing super interfaces that the generated | 380 super_database -- database containing super interfaces that the generated |
| 381 interfaces should extend. | 381 interfaces should extend. |
| 382 common_prefix -- prefix for the common library, if any. | 382 common_prefix -- prefix for the common library, if any. |
| 383 lib_file_path -- filename for generated .lib file, None if not required. | 383 lib_file_path -- filename for generated .lib file, None if not required. |
| 384 lib_template -- template file in this directory for generated lib file. | 384 lib_template -- template file in this directory for generated lib file. |
| 385 """ | 385 """ |
| 386 | 386 |
| 387 self._emitters = multiemitter.MultiEmitter() | 387 self._emitters = multiemitter.MultiEmitter() |
| 388 self._database = database | 388 self._database = database |
| 389 self._output_dir = output_dir | 389 self._output_dir = output_dir |
| 390 | 390 |
| 391 self._ComputeInheritanceClosure() | 391 self._ComputeInheritanceClosure() |
| 392 | 392 |
| 393 self._systems = [] | |
| 394 | |
| 393 interface_system = InterfacesSystem( | 395 interface_system = InterfacesSystem( |
| 394 TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']), | 396 TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']), |
| 395 self._database, self._emitters, self._output_dir) | 397 self._database, self._emitters, self._output_dir) |
| 398 self._systems.append(interface_system) | |
| 396 | 399 |
| 397 wrapping_system = WrappingImplementationSystem( | 400 if 'native' in systems: |
|
antonm
2012/02/01 13:03:43
nit: some concerns: systems may have system we don
| |
| 398 TemplateLoader(self._template_dir, ['dom/wrapping', 'dom', '']), | 401 native_system = NativeImplementationSystem( |
| 399 self._database, self._emitters, self._output_dir) | 402 TemplateLoader(self._template_dir, ['dom/native', 'dom', '']), |
| 403 self._database, self._emitters, self._auxiliary_dir, | |
| 404 self._output_dir) | |
| 400 | 405 |
| 401 # Makes interface files available for listing in the library for the | 406 self._systems.append(native_system) |
| 402 # wrapping implementation. | |
| 403 | 407 |
| 404 wrapping_system._interface_system = interface_system | 408 if 'wrapping' in systems: |
| 409 wrapping_system = WrappingImplementationSystem( | |
| 410 TemplateLoader(self._template_dir, ['dom/wrapping', 'dom', '']), | |
| 411 self._database, self._emitters, self._output_dir) | |
| 405 | 412 |
| 406 frog_system = FrogSystem( | 413 # Makes interface files available for listing in the library for the |
| 407 TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']), | 414 # wrapping implementation. |
| 408 self._database, self._emitters, self._output_dir) | 415 wrapping_system._interface_system = interface_system |
| 416 self._systems.append(wrapping_system) | |
| 409 | 417 |
| 410 frog_system._interface_system = interface_system | 418 if 'frog' in systems: |
| 419 frog_system = FrogSystem( | |
| 420 TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']), | |
| 421 self._database, self._emitters, self._output_dir) | |
| 411 | 422 |
| 412 self._systems = [interface_system, | 423 frog_system._interface_system = interface_system |
| 413 wrapping_system, | 424 self._systems.append(frog_system) |
| 414 frog_system] | 425 |
| 415 | 426 |
| 416 # Render all interfaces into Dart and save them in files. | 427 # Render all interfaces into Dart and save them in files. |
| 417 for interface in database.GetInterfaces(): | 428 for interface in database.GetInterfaces(): |
| 418 | 429 |
| 419 super_interface = None | 430 super_interface = None |
| 420 super_name = interface.id | 431 super_name = interface.id |
| 421 | 432 |
| 422 if not _MatchSourceFilter(source_filter, interface): | 433 if not _MatchSourceFilter(source_filter, interface): |
| 423 # Skip this interface since it's not present in the required source | 434 # Skip this interface since it's not present in the required source |
| 424 _logger.info('Omitting interface - %s' % interface.id) | 435 _logger.info('Omitting interface - %s' % interface.id) |
| (...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1298 | 1309 |
| 1299 | 1310 |
| 1300 def StartInterface(self): | 1311 def StartInterface(self): |
| 1301 interface = self._interface | 1312 interface = self._interface |
| 1302 interface_name = interface.id | 1313 interface_name = interface.id |
| 1303 | 1314 |
| 1304 self._class_name = self._ImplClassName(interface_name) | 1315 self._class_name = self._ImplClassName(interface_name) |
| 1305 self._type_map.Emit(' "$INTERFACE": native_$(CLASS)_create_$(CLASS),\n', | 1316 self._type_map.Emit(' "$INTERFACE": native_$(CLASS)_create_$(CLASS),\n', |
| 1306 INTERFACE=interface_name, CLASS=self._class_name) | 1317 INTERFACE=interface_name, CLASS=self._class_name) |
| 1307 | 1318 |
| 1308 base = 'DOMWrapperBase' | 1319 base = self._BaseClassName(interface) |
| 1309 if interface.parents: | |
| 1310 supertype = interface.parents[0].type.id | |
| 1311 # FIXME: We're currently injecting List<..> and EventTarget as | |
| 1312 # supertypes in dart.idl. We should annotate/preserve as | |
| 1313 # attributes instead. For now, this hack lets the interfaces | |
| 1314 # inherit, but not the classes. | |
| 1315 if (not _IsDartListType(supertype) and | |
| 1316 not supertype == 'EventTarget'): | |
| 1317 base = self._ImplClassName(supertype) | |
| 1318 if _IsDartCollectionType(supertype): | |
| 1319 # List methods are injected in AddIndexer. | |
| 1320 pass | |
| 1321 elif supertype == 'EventTarget': | |
| 1322 # Most implementors of EventTarget specify the EventListener operations | |
| 1323 # again. If the operations are not specified, try to inherit from the | |
| 1324 # EventTarget implementation. | |
| 1325 # | |
| 1326 # Applies to MessagePort. | |
| 1327 if not [op for op in interface.operations if op.id == 'addEventListener' ]: | |
| 1328 base = self._ImplClassName(supertype) | |
| 1329 else: | |
| 1330 base = self._ImplClassName(supertype) | |
| 1331 | 1320 |
| 1332 (self._members_emitter, | 1321 (self._members_emitter, |
| 1333 self._top_level_emitter) = self._dart_code.Emit( | 1322 self._top_level_emitter) = self._dart_code.Emit( |
| 1334 '\n' | 1323 '\n' |
| 1335 'class $CLASS extends $BASE implements $INTERFACE {\n' | 1324 'class $CLASS extends $BASE implements $INTERFACE {\n' |
| 1336 ' $CLASS() : super() {}\n' | 1325 ' $CLASS() : super() {}\n' |
| 1337 '\n' | 1326 '\n' |
| 1338 ' static create_$CLASS() native {\n' | 1327 ' static create_$CLASS() native {\n' |
| 1339 ' return new $CLASS();\n' | 1328 ' return new $CLASS();\n' |
| 1340 ' }\n' | 1329 ' }\n' |
| 1341 '$!MEMBERS' | 1330 '$!MEMBERS' |
| 1342 '\n' | 1331 '\n' |
| 1343 ' String get typeName() { return "$INTERFACE"; }\n' | 1332 ' String get typeName() { return "$INTERFACE"; }\n' |
| 1344 '}\n' | 1333 '}\n' |
| 1345 '$!TOP_LEVEL', | 1334 '$!TOP_LEVEL', |
| 1346 CLASS=self._class_name, BASE=base, INTERFACE=interface_name) | 1335 CLASS=self._class_name, BASE=base, INTERFACE=interface_name) |
| 1347 | 1336 |
| 1348 def _ImplClassName(self, type_name): | 1337 def _ImplClassName(self, type_name): |
| 1349 return '_' + type_name + 'WrappingImplementation' | 1338 return '_' + type_name + 'WrappingImplementation' |
| 1350 | 1339 |
| 1340 def _BaseClassName(self, interface): | |
| 1341 if not interface.parents: | |
| 1342 return 'DOMWrapperBase' | |
| 1343 | |
| 1344 supertype = interface.parents[0].type.id | |
| 1345 | |
| 1346 # FIXME: We're currently injecting List<..> and EventTarget as | |
| 1347 # supertypes in dart.idl. We should annotate/preserve as | |
| 1348 # attributes instead. For now, this hack lets the interfaces | |
| 1349 # inherit, but not the classes. | |
| 1350 # List methods are injected in AddIndexer. | |
| 1351 if _IsDartListType(supertype) or _IsDartCollectionType(supertype): | |
| 1352 return 'DOMWrapperBase' | |
| 1353 | |
| 1354 if supertype == 'EventTarget': | |
| 1355 # Most implementors of EventTarget specify the EventListener operations | |
| 1356 # again. If the operations are not specified, try to inherit from the | |
| 1357 # EventTarget implementation. | |
| 1358 # | |
| 1359 # Applies to MessagePort. | |
| 1360 if not [op for op in interface.operations if op.id == 'addEventListener']: | |
| 1361 return self._ImplClassName(supertype) | |
| 1362 return 'DOMWrapperBase' | |
| 1363 | |
| 1364 return self._ImplClassName(supertype) | |
| 1365 | |
| 1351 def FinishInterface(self): | 1366 def FinishInterface(self): |
| 1352 """.""" | 1367 """.""" |
| 1353 pass | 1368 pass |
| 1354 | 1369 |
| 1355 def AddConstant(self, constant): | 1370 def AddConstant(self, constant): |
| 1356 # Constants are already defined on the interface. | 1371 # Constants are already defined on the interface. |
| 1357 pass | 1372 pass |
| 1358 | 1373 |
| 1359 def _MethodName(self, prefix, name): | 1374 def _MethodName(self, prefix, name): |
| 1360 method_name = prefix + name | 1375 method_name = prefix + name |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1434 # interface Y extends X, List<T> ... | 1449 # interface Y extends X, List<T> ... |
| 1435 # | 1450 # |
| 1436 # In the non-root case we have to choose between: | 1451 # In the non-root case we have to choose between: |
| 1437 # | 1452 # |
| 1438 # class YImpl extends XImpl { add List<T> methods; } | 1453 # class YImpl extends XImpl { add List<T> methods; } |
| 1439 # | 1454 # |
| 1440 # and | 1455 # and |
| 1441 # | 1456 # |
| 1442 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } | 1457 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } |
| 1443 # | 1458 # |
| 1444 if ('HasIndexGetter' in self._interface.ext_attrs or | 1459 if self._HasNativeIndexGetter(self._interface): |
| 1445 'HasNumericIndexGetter' in self._interface.ext_attrs): | 1460 self._EmitNativeIndexGetter(self._interface, element_type) |
| 1446 method_name = '_index' | |
| 1447 self._members_emitter.Emit( | |
| 1448 '\n' | |
| 1449 ' $TYPE operator[](int index) { return $METHOD(this, index); }\n' | |
| 1450 ' static $TYPE $METHOD(var _this, int index) native;\n', | |
| 1451 TYPE=element_type, METHOD=method_name) | |
| 1452 self._js_code.Emit( | |
| 1453 '\n' | |
| 1454 'function native_$(CLASS)_$(METHOD)(_this, index) {\n' | |
| 1455 ' try {\n' | |
| 1456 ' return __dom_wrap(_this.$dom[index]);\n' | |
| 1457 ' } catch (e) {\n' | |
| 1458 ' throw __dom_wrap_exception(e);\n' | |
| 1459 ' }\n' | |
| 1460 '}\n', | |
| 1461 CLASS=self._class_name, METHOD=method_name) | |
| 1462 else: | 1461 else: |
| 1463 self._members_emitter.Emit( | 1462 self._members_emitter.Emit( |
| 1464 '\n' | 1463 '\n' |
| 1465 ' $TYPE operator[](int index) {\n' | 1464 ' $TYPE operator[](int index) {\n' |
| 1466 ' return item(index);\n' | 1465 ' return item(index);\n' |
| 1467 ' }\n', | 1466 ' }\n', |
| 1468 TYPE=element_type) | 1467 TYPE=element_type) |
| 1469 | 1468 |
| 1470 | 1469 if self._HasNativeIndexSetter(self._interface): |
| 1471 if 'HasCustomIndexSetter' in self._interface.ext_attrs: | 1470 self._EmitNativeIndexSetter(self._interface, element_type) |
| 1472 method_name = '_set_index' | |
| 1473 self._members_emitter.Emit( | |
| 1474 '\n' | |
| 1475 ' void operator[]=(int index, $TYPE value) {\n' | |
| 1476 ' return $METHOD(this, index, value);\n' | |
| 1477 ' }\n' | |
| 1478 ' static $METHOD(_this, index, value) native;\n', | |
| 1479 TYPE=element_type, METHOD=method_name) | |
| 1480 self._js_code.Emit( | |
| 1481 '\n' | |
| 1482 'function native_$(CLASS)_$(METHOD)(_this, index, value) {\n' | |
| 1483 ' try {\n' | |
| 1484 ' return _this.$dom[index] = __dom_unwrap(value);\n' | |
| 1485 ' } catch (e) {\n' | |
| 1486 ' throw __dom_wrap_exception(e);\n' | |
| 1487 ' }\n' | |
| 1488 '}\n', | |
| 1489 CLASS=self._class_name, METHOD=method_name) | |
| 1490 else: | 1471 else: |
| 1491 self._members_emitter.Emit( | 1472 self._members_emitter.Emit( |
| 1492 '\n' | 1473 '\n' |
| 1493 ' void operator[]=(int index, $TYPE value) {\n' | 1474 ' void operator[]=(int index, $TYPE value) {\n' |
| 1494 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n' | 1475 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n' |
| 1495 ' }\n', | 1476 ' }\n', |
| 1496 TYPE=element_type) | 1477 TYPE=element_type) |
| 1497 | 1478 |
| 1498 self._members_emitter.Emit( | 1479 self._members_emitter.Emit( |
| 1499 '\n' | 1480 '\n' |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1577 '\n' | 1558 '\n' |
| 1578 ' bool isEmpty() {\n' | 1559 ' bool isEmpty() {\n' |
| 1579 ' return length == 0;\n' | 1560 ' return length == 0;\n' |
| 1580 ' }\n' | 1561 ' }\n' |
| 1581 '\n' | 1562 '\n' |
| 1582 ' Iterator<$TYPE> iterator() {\n' | 1563 ' Iterator<$TYPE> iterator() {\n' |
| 1583 ' return new _FixedSizeListIterator<$TYPE>(this);\n' | 1564 ' return new _FixedSizeListIterator<$TYPE>(this);\n' |
| 1584 ' }\n', | 1565 ' }\n', |
| 1585 TYPE=element_type) | 1566 TYPE=element_type) |
| 1586 | 1567 |
| 1568 def _HasNativeIndexGetter(self, interface): | |
| 1569 return ('HasIndexGetter' in interface.ext_attrs or | |
| 1570 'HasNumericIndexGetter' in interface.ext_attrs) | |
| 1571 | |
| 1572 def _EmitNativeIndexGetter(self, interface, element_type): | |
| 1573 method_name = '_index' | |
| 1574 self._members_emitter.Emit( | |
| 1575 '\n' | |
| 1576 ' $TYPE operator[](int index) { return $METHOD(this, index); }\n' | |
| 1577 ' static $TYPE $METHOD(var _this, int index) native;\n', | |
| 1578 TYPE=element_type, METHOD=method_name) | |
| 1579 self._js_code.Emit( | |
| 1580 '\n' | |
| 1581 'function native_$(CLASS)_$(METHOD)(_this, index) {\n' | |
| 1582 ' try {\n' | |
| 1583 ' return __dom_wrap(_this.$dom[index]);\n' | |
| 1584 ' } catch (e) {\n' | |
| 1585 ' throw __dom_wrap_exception(e);\n' | |
| 1586 ' }\n' | |
| 1587 '}\n', | |
| 1588 CLASS=self._class_name, METHOD=method_name) | |
| 1589 | |
| 1590 def _HasNativeIndexSetter(self, interface): | |
| 1591 return 'HasCustomIndexSetter' in interface.ext_attrs | |
| 1592 | |
| 1593 def _EmitNativeIndexSetter(self, interface, element_type): | |
| 1594 method_name = '_set_index' | |
| 1595 self._members_emitter.Emit( | |
| 1596 '\n' | |
| 1597 ' void operator[]=(int index, $TYPE value) {\n' | |
| 1598 ' return $METHOD(this, index, value);\n' | |
| 1599 ' }\n' | |
| 1600 ' static $METHOD(_this, index, value) native;\n', | |
| 1601 TYPE=element_type, METHOD=method_name) | |
| 1602 self._js_code.Emit( | |
| 1603 '\n' | |
| 1604 'function native_$(CLASS)_$(METHOD)(_this, index, value) {\n' | |
| 1605 ' try {\n' | |
| 1606 ' return _this.$dom[index] = __dom_unwrap(value);\n' | |
| 1607 ' } catch (e) {\n' | |
| 1608 ' throw __dom_wrap_exception(e);\n' | |
| 1609 ' }\n' | |
| 1610 '}\n', | |
| 1611 CLASS=self._class_name, METHOD=method_name) | |
| 1612 | |
| 1587 def AddOperation(self, info): | 1613 def AddOperation(self, info): |
| 1588 """ | 1614 """ |
| 1589 Arguments: | 1615 Arguments: |
| 1590 info: An OperationInfo object. | 1616 info: An OperationInfo object. |
| 1591 """ | 1617 """ |
| 1592 body = self._members_emitter.Emit( | 1618 body = self._members_emitter.Emit( |
| 1593 '\n' | 1619 '\n' |
| 1594 ' $TYPE $NAME($PARAMS) {\n' | 1620 ' $TYPE $NAME($PARAMS) {\n' |
| 1595 '$!BODY' | 1621 '$!BODY' |
| 1596 ' }\n', | 1622 ' }\n', |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2027 info: An OperationInfo object. | 2053 info: An OperationInfo object. |
| 2028 """ | 2054 """ |
| 2029 # TODO(vsm): Handle overloads. | 2055 # TODO(vsm): Handle overloads. |
| 2030 self._members_emitter.Emit( | 2056 self._members_emitter.Emit( |
| 2031 '\n' | 2057 '\n' |
| 2032 ' $TYPE $NAME($PARAMS) native;\n', | 2058 ' $TYPE $NAME($PARAMS) native;\n', |
| 2033 TYPE=self._NarrowOutputType(info.type_name), | 2059 TYPE=self._NarrowOutputType(info.type_name), |
| 2034 NAME=info.name, | 2060 NAME=info.name, |
| 2035 PARAMS=info.ParametersImplementationDeclaration( | 2061 PARAMS=info.ParametersImplementationDeclaration( |
| 2036 lambda type_name: self._NarrowInputType(type_name))) | 2062 lambda type_name: self._NarrowInputType(type_name))) |
| 2063 | |
| 2064 | |
| 2065 # ------------------------------------------------------------------------------ | |
| 2066 | |
| 2067 class NativeImplementationSystem(System): | |
| 2068 | |
| 2069 def __init__(self, templates, database, emitters, auxiliary_dir, output_dir): | |
| 2070 super(NativeImplementationSystem, self).__init__( | |
| 2071 templates, database, emitters, output_dir) | |
| 2072 | |
| 2073 self._auxiliary_dir = auxiliary_dir | |
| 2074 self._dom_public_files = [] | |
| 2075 self._dom_impl_files = [] | |
| 2076 | |
| 2077 def InterfaceGenerator(self, | |
| 2078 interface, | |
| 2079 common_prefix, | |
| 2080 super_interface_name, | |
| 2081 source_filter): | |
| 2082 interface_name = interface.id | |
| 2083 | |
| 2084 dart_interface_path = self._FilePathForDartInterface(interface_name) | |
| 2085 self._dom_public_files.append(dart_interface_path) | |
| 2086 | |
| 2087 dart_impl_path = self._FilePathForDartImplementation(interface_name) | |
| 2088 self._dom_impl_files.append(dart_impl_path) | |
| 2089 | |
| 2090 return NativeImplementationGenerator(interface, super_interface_name, | |
| 2091 self._emitters.FileEmitter(dart_impl_path), | |
| 2092 self._BaseDefines(interface), | |
| 2093 self._templates) | |
| 2094 | |
| 2095 def ProcessCallback(self, interface, info): | |
| 2096 self._dom_public_files.append(self._FilePathForDartInterface(interface.id)) | |
| 2097 | |
| 2098 def GenerateLibraries(self, lib_dir): | |
| 2099 auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir) | |
| 2100 | |
| 2101 # Generate dom_public.dart. | |
| 2102 dom_public_path = os.path.join(self._output_dir, 'dom_public.dart') | |
| 2103 | |
| 2104 dom_public_imports_emitter = emitter.Emitter() | |
| 2105 for file in self._dom_public_files: | |
| 2106 path = os.path.relpath(file, os.path.dirname(dom_public_path)) | |
| 2107 dom_public_imports_emitter.Emit('#source("$PATH");\n', PATH=path) | |
| 2108 | |
| 2109 dom_public_emitter = self._emitters.FileEmitter(dom_public_path) | |
| 2110 dom_public_emitter.Emit(self._templates.Load('dom_public.darttemplate'), | |
| 2111 AUXILIARY_DIR=auxiliary_dir, | |
| 2112 SOURCES=dom_public_imports_emitter.Fragments()) | |
| 2113 | |
| 2114 # Generate dom_impl.dart. | |
| 2115 dom_impl_path = os.path.join(self._output_dir, 'dom_impl.dart') | |
| 2116 | |
| 2117 dom_impl_imports_emitter = emitter.Emitter() | |
| 2118 for file in self._dom_impl_files: | |
| 2119 path = os.path.relpath(file, os.path.dirname(dom_impl_path)) | |
| 2120 dom_impl_imports_emitter.Emit('#source("$PATH");\n', PATH=path) | |
| 2121 | |
| 2122 dom_impl_emitter = self._emitters.FileEmitter(dom_impl_path) | |
| 2123 dom_impl_emitter.Emit(self._templates.Load('dom_impl.darttemplate'), | |
| 2124 AUXILIARY_DIR=auxiliary_dir, | |
| 2125 SOURCES=dom_impl_imports_emitter.Fragments()) | |
| 2126 | |
| 2127 def Finish(self): | |
| 2128 pass | |
| 2129 | |
| 2130 def _FilePathForDartInterface(self, interface_name): | |
| 2131 return os.path.join(self._output_dir, 'src', 'interface', | |
| 2132 '%s.dart' % interface_name) | |
| 2133 | |
| 2134 def _FilePathForDartImplementation(self, interface_name): | |
| 2135 return os.path.join(self._output_dir, 'dart', | |
| 2136 '%sImplementation.dart' % interface_name) | |
| 2137 | |
| 2138 | |
| 2139 class NativeImplementationGenerator(WrappingInterfaceGenerator): | |
| 2140 """Generates Dart implementation for one DOM IDL interface.""" | |
| 2141 | |
| 2142 def __init__(self, interface, super_interface, dart_impl_emitter, | |
| 2143 base_members, templates): | |
| 2144 """Generates Dart code for the given interface. | |
| 2145 | |
| 2146 Args: | |
| 2147 | |
| 2148 interface: an IDLInterface instance. It is assumed that all types have | |
| 2149 been converted to Dart types (e.g. int, String), unless they are in | |
| 2150 the same package as the interface. | |
| 2151 super_interface: A string or None, the name of the common interface that | |
| 2152 this interface implements, if any. | |
| 2153 dart_impl_emitter: an Emitter for the file containing the Dart | |
| 2154 implementation class. | |
| 2155 base_members: a set of names of members defined in a base class. This is | |
| 2156 used to avoid static member 'overriding' in the generated Dart code. | |
| 2157 """ | |
| 2158 self._interface = interface | |
| 2159 self._super_interface = super_interface | |
| 2160 self._dart_impl_emitter = dart_impl_emitter | |
| 2161 self._base_members = base_members | |
| 2162 self._templates = templates | |
| 2163 self._current_secondary_parent = None | |
| 2164 | |
| 2165 def StartInterface(self): | |
| 2166 self._class_name = self._ImplClassName(self._interface.id) | |
| 2167 self._members_emitter = emitter.Emitter() | |
| 2168 | |
| 2169 def _ImplClassName(self, type_name): | |
| 2170 return type_name + 'Implementation' | |
| 2171 | |
| 2172 def FinishInterface(self): | |
| 2173 interface = self._interface | |
| 2174 interface_name = interface.id | |
| 2175 | |
| 2176 base = self._BaseClassName(interface) | |
| 2177 self._dart_impl_emitter.Emit( | |
| 2178 self._templates.Load('dart_implementation.darttemplate'), | |
| 2179 CLASS=self._class_name, BASE=base, INTERFACE=interface_name, | |
| 2180 MEMBERS=self._members_emitter.Fragments()) | |
| 2181 | |
| 2182 def AddGetter(self, attr): | |
| 2183 self._members_emitter.Emit( | |
| 2184 '\n' | |
| 2185 ' $TYPE get $NAME() native "$(INTERFACE)_$(NAME)_Getter";\n', | |
| 2186 NAME=attr.id, TYPE=attr.type.id, INTERFACE=self._interface.id) | |
| 2187 | |
| 2188 def AddSetter(self, attr): | |
| 2189 self._members_emitter.Emit( | |
| 2190 '\n' | |
| 2191 ' void set $NAME($TYPE) native "$(INTERFACE)_$(NAME)_Setter";\n', | |
| 2192 NAME=attr.id, TYPE=attr.type.id, INTERFACE=self._interface.id) | |
| 2193 | |
| 2194 def _HasNativeIndexGetter(self, interface): | |
| 2195 return ('HasCustomIndexGetter' in interface.ext_attrs or | |
| 2196 'HasNumericIndexGetter' in interface.ext_attrs) | |
| 2197 | |
| 2198 def _EmitNativeIndexGetter(self, interface, element_type): | |
| 2199 native_binding = '%s_numericIndexGetter_Callback' % interface.id | |
| 2200 self._members_emitter.Emit( | |
| 2201 '\n' | |
| 2202 ' $TYPE operator[](int index) native "$NATIVE_BINDING";\n', | |
| 2203 TYPE=element_type, NATIVE_BINDING=native_binding) | |
| 2204 | |
| 2205 def _EmitNativeIndexSetter(self, interface, element_type): | |
| 2206 native_binding = '%s_numericIndexSetter_Callback' % self._interface.id | |
| 2207 self._members_emitter.Emit( | |
| 2208 '\n' | |
| 2209 ' void operator[]=(int index, $TYPE value) native "$NATIVE_BINDING";\n' , | |
| 2210 TYPE=element_type, NATIVE_BINDING=native_binding) | |
| 2211 | |
| 2212 def AddOperation(self, info): | |
| 2213 """ | |
| 2214 Arguments: | |
| 2215 info: An OperationInfo object. | |
| 2216 """ | |
| 2217 | |
| 2218 if 'Custom' in info.overloads[0].ext_attrs: | |
| 2219 self._members_emitter.Emit( | |
| 2220 '\n' | |
| 2221 ' $TYPE $NAME($PARAMETERS) native "$(INTERFACE)_$(NAME)_Callback";\ n', | |
| 2222 TYPE=info.type_name, | |
| 2223 NAME=info.name, | |
| 2224 PARAMETERS=info.ParametersImplementationDeclaration(), | |
| 2225 INTERFACE=self._interface.id) | |
| 2226 return | |
| 2227 | |
| 2228 body = self._members_emitter.Emit( | |
| 2229 '\n' | |
| 2230 ' $TYPE $NAME($PARAMETERS) {\n' | |
| 2231 '$!BODY' | |
| 2232 ' }\n', | |
| 2233 TYPE=info.type_name, | |
| 2234 NAME=info.name, | |
| 2235 PARAMETERS=info.ParametersImplementationDeclaration()) | |
| 2236 | |
| 2237 # Process in order of ascending number of arguments to ensure missing | |
| 2238 # optional arguments are processed early. | |
| 2239 overloads = sorted(info.overloads, | |
| 2240 key=lambda overload: len(overload.arguments)) | |
| 2241 self._native_version = 0 | |
| 2242 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) | |
| 2243 if fallthrough: | |
| 2244 body.Emit(' throw "Incorrect number or type of arguments";\n'); | |
| 2245 | |
| 2246 def GenerateSingleOperation(self, emitter, info, indent, operation): | |
| 2247 """Generates a call to a single operation. | |
| 2248 | |
| 2249 Arguments: | |
| 2250 emitter: an Emitter for the body of a block of code. | |
| 2251 info: the compound information about the operation and its overloads. | |
| 2252 indent: an indentation string for generated code. | |
| 2253 operation: the IDLOperation to call. | |
| 2254 """ | |
| 2255 | |
| 2256 arg_names = [info.arg_infos[i][0] | |
| 2257 for (i, arg) in enumerate(operation.arguments)] | |
| 2258 | |
| 2259 self._native_version += 1 | |
| 2260 native_name = '_%s' % info.name | |
| 2261 if self._native_version > 1: | |
| 2262 native_name = '%s_%s' % (native_name, self._native_version) | |
| 2263 | |
| 2264 argument_expressions = ', '.join(arg_names) | |
| 2265 if info.type_name != 'void': | |
| 2266 emitter.Emit('$(INDENT)return $NATIVENAME($ARGS);\n', | |
| 2267 INDENT=indent, | |
| 2268 NATIVENAME=native_name, | |
| 2269 ARGS=argument_expressions) | |
| 2270 else: | |
| 2271 emitter.Emit('$(INDENT)$NATIVENAME($ARGS);\n' | |
| 2272 '$(INDENT)return;\n', | |
| 2273 INDENT=indent, | |
| 2274 NATIVENAME=native_name, | |
| 2275 ARGS=argument_expressions) | |
| 2276 | |
| 2277 self._members_emitter.Emit(' $TYPE $NATIVE_NAME($PARAMS) native ' | |
| 2278 '"$(INTERFACE)$(NATIVE_NAME)_Callback";\n', | |
| 2279 NATIVE_NAME=native_name, | |
| 2280 TYPE=info.type_name, | |
| 2281 PARAMS=', '.join(arg_names), | |
| 2282 INTERFACE=self._interface.id) | |
| OLD | NEW |