| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 2 # Copyright (c) 2011, 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 import copy | 6 import copy |
| 7 import database | 7 import database |
| 8 import idlparser | 8 import idlparser |
| 9 import logging | 9 import logging |
| 10 import multiprocessing |
| 10 import os | 11 import os |
| 11 import os.path | 12 import os.path |
| 12 import re | 13 import re |
| 13 | 14 |
| 14 from idlnode import * | 15 from idlnode import * |
| 15 | 16 |
| 16 _logger = logging.getLogger('databasebuilder') | 17 _logger = logging.getLogger('databasebuilder') |
| 17 | 18 |
| 18 # Used in source annotations to specify the parent interface declaring | 19 # Used in source annotations to specify the parent interface declaring |
| 19 # a displaced declaration. The 'via' attribute specifies the parent interface | 20 # a displaced declaration. The 'via' attribute specifies the parent interface |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 self.source_attributes = source_attributes | 57 self.source_attributes = source_attributes |
| 57 self.idl_syntax = idl_syntax | 58 self.idl_syntax = idl_syntax |
| 58 self.idl_defines = idl_defines | 59 self.idl_defines = idl_defines |
| 59 self.type_rename_map = type_rename_map | 60 self.type_rename_map = type_rename_map |
| 60 self.rename_operation_arguments_on_merge = \ | 61 self.rename_operation_arguments_on_merge = \ |
| 61 rename_operation_arguments_on_merge | 62 rename_operation_arguments_on_merge |
| 62 self.add_new_interfaces = add_new_interfaces | 63 self.add_new_interfaces = add_new_interfaces |
| 63 self.obsolete_old_declarations = obsolete_old_declarations | 64 self.obsolete_old_declarations = obsolete_old_declarations |
| 64 | 65 |
| 65 | 66 |
| 67 def _load_idl_file(file_name, import_options, result_queue): |
| 68 """Loads an IDL file into memory""" |
| 69 idl_parser = idlparser.IDLParser(import_options.idl_syntax) |
| 70 |
| 71 try: |
| 72 f = open(file_name, 'r') |
| 73 content = f.read() |
| 74 f.close() |
| 75 |
| 76 idl_ast = idl_parser.parse( |
| 77 content, |
| 78 defines=import_options.idl_defines) |
| 79 result = IDLFile(idl_ast, file_name) |
| 80 result_queue.put(result, False) |
| 81 return 0 |
| 82 except SyntaxError, e: |
| 83 result_queue.put(RuntimeError('Failed to load file %s: %s' |
| 84 % (file_name, e)), |
| 85 False) |
| 86 return 1 |
| 87 except: |
| 88 result_queue.put('Unknown error loading %s' % file_name, False) |
| 89 return 1 |
| 90 |
| 66 class DatabaseBuilder(object): | 91 class DatabaseBuilder(object): |
| 67 def __init__(self, database): | 92 def __init__(self, database): |
| 68 """DatabaseBuilder is used for importing and merging interfaces into | 93 """DatabaseBuilder is used for importing and merging interfaces into |
| 69 the Database""" | 94 the Database""" |
| 70 self._database = database | 95 self._database = database |
| 71 self._imported_interfaces = [] | 96 self._imported_interfaces = [] |
| 72 self._impl_stmts = [] | 97 self._impl_stmts = [] |
| 73 | 98 |
| 74 def _load_idl_file(self, file_name, import_options): | |
| 75 """Loads an IDL file intor memory""" | |
| 76 idl_parser = idlparser.IDLParser(import_options.idl_syntax) | |
| 77 | |
| 78 try: | |
| 79 f = open(file_name, 'r') | |
| 80 content = f.read() | |
| 81 f.close() | |
| 82 | |
| 83 idl_ast = idl_parser.parse(content, | |
| 84 defines=import_options.idl_defines) | |
| 85 return IDLFile(idl_ast, file_name) | |
| 86 except SyntaxError, e: | |
| 87 raise RuntimeError('Failed to load file %s: %s' % (file_name, e)) | |
| 88 | |
| 89 def _resolve_type_defs(self, idl_file): | 99 def _resolve_type_defs(self, idl_file): |
| 90 type_def_map = {} | 100 type_def_map = {} |
| 91 # build map | 101 # build map |
| 92 for type_def in idl_file.all(IDLTypeDef): | 102 for type_def in idl_file.all(IDLTypeDef): |
| 93 if type_def.type.id != type_def.id: # sanity check | 103 if type_def.type.id != type_def.id: # sanity check |
| 94 type_def_map[type_def.id] = type_def.type.id | 104 type_def_map[type_def.id] = type_def.type.id |
| 95 # use the map | 105 # use the map |
| 96 for type_node in idl_file.all(IDLType): | 106 for type_node in idl_file.all(IDLType): |
| 97 while type_node.id in type_def_map: | 107 while type_node.id in type_def_map: |
| 98 type_node.id = type_def_map[type_node.id] | 108 type_node.id = type_def_map[type_node.id] |
| 99 | 109 |
| 100 def _strip_ext_attributes(self, idl_file): | 110 def _strip_ext_attributes(self, idl_file): |
| 101 """Strips unuseful extended attributes.""" | 111 """Strips unuseful extended attributes.""" |
| 102 for ext_attrs in idl_file.all(IDLExtAttrs): | 112 for ext_attrs in idl_file.all(IDLExtAttrs): |
| 103 # TODO: Decide which attributes are uninteresting. | 113 # TODO: Decide which attributes are uninteresting. |
| 104 pass | 114 pass |
| 105 | 115 |
| 106 def _rename_types(self, idl_file, import_options): | 116 def _rename_types(self, idl_file, import_options): |
| 107 """Rename interface and type names with names provided in the | 117 """Rename interface and type names with names provided in the |
| 108 options. Also clears scopes from scoped names""" | 118 options. Also clears scopes from scoped names""" |
| 109 | 119 |
| 110 def rename(name): | 120 def rename(name): |
| 111 name_parts = name.split('::') | 121 name_parts = name.split('::') |
| 112 name = name_parts[-1] | 122 name = name_parts[-1] |
| 113 if name in import_options.type_rename_map: | 123 if name in import_options.type_rename_map: |
| 114 name = import_options.type_rename_map[name] | 124 name = import_options.type_rename_map[name] |
| 115 return name | 125 return name |
| 116 | 126 |
| 117 def rename_node(idl_node): | 127 def rename_node(idl_node): |
| 118 idl_node.id = rename(idl_node.id) | 128 idl_node.reset_id(rename(idl_node.id)) |
| 119 | 129 |
| 120 def rename_ext_attrs(ext_attrs_node): | 130 def rename_ext_attrs(ext_attrs_node): |
| 121 for type_valued_attribute_name in ['Supplemental']: | 131 for type_valued_attribute_name in ['Supplemental']: |
| 122 if type_valued_attribute_name in ext_attrs_node: | 132 if type_valued_attribute_name in ext_attrs_node: |
| 123 value = ext_attrs_node[type_valued_attribute_name] | 133 value = ext_attrs_node[type_valued_attribute_name] |
| 124 if isinstance(value, str): | 134 if isinstance(value, str): |
| 125 ext_attrs_node[type_valued_attribute_name] = rename(value) | 135 ext_attrs_node[type_valued_attribute_name] = rename(value) |
| 126 | 136 |
| 127 map(rename_node, idl_file.all(IDLInterface)) | 137 map(rename_node, idl_file.all(IDLInterface)) |
| 128 map(rename_node, idl_file.all(IDLType)) | 138 map(rename_node, idl_file.all(IDLType)) |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 not new_interface.is_supplemental): | 325 not new_interface.is_supplemental): |
| 316 old_interface.annotations[source] = new_interface.annotations[source] | 326 old_interface.annotations[source] = new_interface.annotations[source] |
| 317 changed = True | 327 changed = True |
| 318 | 328 |
| 319 def merge_list(what): | 329 def merge_list(what): |
| 320 old_list = old_interface.__dict__[what] | 330 old_list = old_interface.__dict__[what] |
| 321 new_list = new_interface.__dict__[what] | 331 new_list = new_interface.__dict__[what] |
| 322 | 332 |
| 323 if what != 'parents' and old_interface.id != new_interface.id: | 333 if what != 'parents' and old_interface.id != new_interface.id: |
| 324 for node in new_list: | 334 for node in new_list: |
| 335 node.doc_js_interface_name = old_interface.id |
| 325 node.ext_attrs['ImplementedBy'] = new_interface.id | 336 node.ext_attrs['ImplementedBy'] = new_interface.id |
| 326 | 337 |
| 327 changed = self._merge_nodes(old_list, new_list, import_options) | 338 changed = self._merge_nodes(old_list, new_list, import_options) |
| 328 | 339 |
| 329 # Delete list items with zero remaining annotations. | 340 # Delete list items with zero remaining annotations. |
| 330 if changed and import_options.obsolete_old_declarations: | 341 if changed and import_options.obsolete_old_declarations: |
| 331 | 342 |
| 332 def has_annotations(idl_node): | 343 def has_annotations(idl_node): |
| 333 return len(idl_node.annotations) | 344 return len(idl_node.annotations) |
| 334 | 345 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 else: | 425 else: |
| 415 raise Exception("Supplemental target '%s' not found", target) | 426 raise Exception("Supplemental target '%s' not found", target) |
| 416 | 427 |
| 417 # Step 4: Resolve 'implements' statements | 428 # Step 4: Resolve 'implements' statements |
| 418 for impl_stmt, import_options in self._impl_stmts: | 429 for impl_stmt, import_options in self._impl_stmts: |
| 419 self._merge_impl_stmt(impl_stmt, import_options) | 430 self._merge_impl_stmt(impl_stmt, import_options) |
| 420 | 431 |
| 421 self._impl_stmts = [] | 432 self._impl_stmts = [] |
| 422 self._imported_interfaces = [] | 433 self._imported_interfaces = [] |
| 423 | 434 |
| 424 def import_idl_file(self, file_path, | 435 def import_idl_files(self, file_paths, import_options): |
| 425 import_options=DatabaseBuilderOptions()): | 436 # Parse the IDL files in parallel. |
| 426 """Parses, loads into memory and cleans up and IDL file""" | 437 result_queue = multiprocessing.Queue(len(file_paths)) |
| 427 idl_file = self._load_idl_file(file_path, import_options) | 438 jobs = [ multiprocessing.Process(target=_load_idl_file, |
| 439 args=(file_path, import_options, |
| 440 result_queue)) |
| 441 for file_path in file_paths ] |
| 442 try: |
| 443 for job in jobs: |
| 444 job.start() |
| 445 for job in jobs: |
| 446 # Timeout and throw after 5 sec. |
| 447 result = result_queue.get(True, 5) |
| 448 if isinstance(result, IDLFile): |
| 449 self._process_idl_file(result, import_options) |
| 450 else: |
| 451 raise result |
| 452 except: |
| 453 # Clean up child processes on error. |
| 454 for job in jobs: |
| 455 job.terminate() |
| 456 raise |
| 428 | 457 |
| 458 def _process_idl_file(self, idl_file, |
| 459 import_options): |
| 429 self._strip_ext_attributes(idl_file) | 460 self._strip_ext_attributes(idl_file) |
| 430 self._resolve_type_defs(idl_file) | 461 self._resolve_type_defs(idl_file) |
| 431 self._rename_types(idl_file, import_options) | 462 self._rename_types(idl_file, import_options) |
| 432 | 463 |
| 433 def enabled(idl_node): | 464 def enabled(idl_node): |
| 434 return self._is_node_enabled(idl_node, import_options.idl_defines) | 465 return self._is_node_enabled(idl_node, import_options.idl_defines) |
| 435 | 466 |
| 436 for module in idl_file.modules: | 467 for module in idl_file.modules: |
| 437 for interface in module.interfaces: | 468 for interface in module.interfaces: |
| 438 if not self._is_node_enabled(interface, import_options.idl_defines): | 469 if not self._is_node_enabled(interface, import_options.idl_defines): |
| 439 _logger.info('skipping interface %s/%s (source=%s file=%s)' | 470 _logger.info('skipping interface %s/%s (source=%s)' |
| 440 % (module.id, interface.id, import_options.source, | 471 % (module.id, interface.id, import_options.source)) |
| 441 file_path)) | |
| 442 continue | 472 continue |
| 443 | 473 |
| 444 _logger.info('importing interface %s/%s (source=%s file=%s)' | 474 _logger.info('importing interface %s/%s (source=%s)' |
| 445 % (module.id, interface.id, import_options.source, | 475 % (module.id, interface.id, import_options.source)) |
| 446 file_path)) | |
| 447 interface.attributes = filter(enabled, interface.attributes) | 476 interface.attributes = filter(enabled, interface.attributes) |
| 448 interface.operations = filter(enabled, interface.operations) | 477 interface.operations = filter(enabled, interface.operations) |
| 449 self._imported_interfaces.append((interface, module.id, import_options)) | 478 self._imported_interfaces.append((interface, module.id, import_options)) |
| 450 | 479 |
| 451 for implStmt in module.implementsStatements: | 480 for implStmt in module.implementsStatements: |
| 452 self._impl_stmts.append((implStmt, import_options)) | 481 self._impl_stmts.append((implStmt, import_options)) |
| 453 | 482 |
| 454 def _is_node_enabled(self, node, idl_defines): | 483 def _is_node_enabled(self, node, idl_defines): |
| 455 if not 'Conditional' in node.ext_attrs: | 484 if not 'Conditional' in node.ext_attrs: |
| 456 return True | 485 return True |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 # TODO(antonm): Ideally we'd like to have pristine copy of WebKit IDLs and
fetch | 579 # TODO(antonm): Ideally we'd like to have pristine copy of WebKit IDLs and
fetch |
| 551 # this information directly from it. Unfortunately right now database is
massaged | 580 # this information directly from it. Unfortunately right now database is
massaged |
| 552 # a lot so it's difficult to maintain necessary information on DOMWindow i
tself. | 581 # a lot so it's difficult to maintain necessary information on DOMWindow i
tself. |
| 553 interface = self._database.GetInterface(options.type_rename_map.get(type,
type)) | 582 interface = self._database.GetInterface(options.type_rename_map.get(type,
type)) |
| 554 if 'V8EnabledPerContext' in attr.ext_attrs: | 583 if 'V8EnabledPerContext' in attr.ext_attrs: |
| 555 interface.ext_attrs['synthesizedV8EnabledPerContext'] = \ | 584 interface.ext_attrs['synthesizedV8EnabledPerContext'] = \ |
| 556 attr.ext_attrs['V8EnabledPerContext'] | 585 attr.ext_attrs['V8EnabledPerContext'] |
| 557 if 'V8EnabledAtRuntime' in attr.ext_attrs: | 586 if 'V8EnabledAtRuntime' in attr.ext_attrs: |
| 558 interface.ext_attrs['synthesizedV8EnabledAtRuntime'] = \ | 587 interface.ext_attrs['synthesizedV8EnabledAtRuntime'] = \ |
| 559 attr.ext_attrs['V8EnabledAtRuntime'] or attr.id | 588 attr.ext_attrs['V8EnabledAtRuntime'] or attr.id |
| OLD | NEW |