Chromium Code Reviews| 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' % (file_name, e)) , | |
|
Anton Muhin
2012/09/26 17:53:09
nit: is line too long? I am personally fine with
vsm
2012/09/28 16:17:25
Done.
| |
| 84 False) | |
| 85 return 1 | |
| 86 except: | |
| 87 result_queue.put('Unknown error loading %s' % file_name, False) | |
| 88 return 1 | |
| 89 | |
| 66 class DatabaseBuilder(object): | 90 class DatabaseBuilder(object): |
| 67 def __init__(self, database): | 91 def __init__(self, database): |
| 68 """DatabaseBuilder is used for importing and merging interfaces into | 92 """DatabaseBuilder is used for importing and merging interfaces into |
| 69 the Database""" | 93 the Database""" |
| 70 self._database = database | 94 self._database = database |
| 71 self._imported_interfaces = [] | 95 self._imported_interfaces = [] |
| 72 self._impl_stmts = [] | 96 self._impl_stmts = [] |
| 73 | 97 |
| 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): | 98 def _resolve_type_defs(self, idl_file): |
| 90 type_def_map = {} | 99 type_def_map = {} |
| 91 # build map | 100 # build map |
| 92 for type_def in idl_file.all(IDLTypeDef): | 101 for type_def in idl_file.all(IDLTypeDef): |
| 93 if type_def.type.id != type_def.id: # sanity check | 102 if type_def.type.id != type_def.id: # sanity check |
| 94 type_def_map[type_def.id] = type_def.type.id | 103 type_def_map[type_def.id] = type_def.type.id |
| 95 # use the map | 104 # use the map |
| 96 for type_node in idl_file.all(IDLType): | 105 for type_node in idl_file.all(IDLType): |
| 97 while type_node.id in type_def_map: | 106 while type_node.id in type_def_map: |
| 98 type_node.id = type_def_map[type_node.id] | 107 type_node.id = type_def_map[type_node.id] |
| 99 | 108 |
| 100 def _strip_ext_attributes(self, idl_file): | 109 def _strip_ext_attributes(self, idl_file): |
| 101 """Strips unuseful extended attributes.""" | 110 """Strips unuseful extended attributes.""" |
| 102 for ext_attrs in idl_file.all(IDLExtAttrs): | 111 for ext_attrs in idl_file.all(IDLExtAttrs): |
| 103 # TODO: Decide which attributes are uninteresting. | 112 # TODO: Decide which attributes are uninteresting. |
| 104 pass | 113 pass |
| 105 | 114 |
| 106 def _rename_types(self, idl_file, import_options): | 115 def _rename_types(self, idl_file, import_options): |
| 107 """Rename interface and type names with names provided in the | 116 """Rename interface and type names with names provided in the |
| 108 options. Also clears scopes from scoped names""" | 117 options. Also clears scopes from scoped names""" |
| 109 | 118 |
| 110 def rename(name): | 119 def rename(name): |
| 111 name_parts = name.split('::') | 120 name_parts = name.split('::') |
| 112 name = name_parts[-1] | 121 name = name_parts[-1] |
| 113 if name in import_options.type_rename_map: | 122 if name in import_options.type_rename_map: |
| 114 name = import_options.type_rename_map[name] | 123 name = import_options.type_rename_map[name] |
| 115 return name | 124 return name |
| 116 | 125 |
| 117 def rename_node(idl_node): | 126 def rename_node(idl_node): |
| 118 idl_node.id = rename(idl_node.id) | 127 new_name = rename(idl_node.id) |
| 128 if new_name != idl_node.id: | |
| 129 idl_node.id = new_name | |
| 130 if isinstance(idl_node, IDLInterface): | |
|
Anton Muhin
2012/09/26 17:53:09
up to you, but might be more natural to have a met
vsm
2012/09/28 16:17:25
Done.
| |
| 131 idl_node.doc_js_name = new_name | |
|
Anton Muhin
2012/09/26 17:53:09
I am not familiar with this part of the system, bu
vsm
2012/09/28 16:17:25
It's a little confusing, but the renaming during d
| |
| 132 idl_node.javascript_binding_name = new_name | |
| 133 for member in idl_node.operations: | |
| 134 member.doc_js_interface_name = new_name | |
| 135 for member in idl_node.attributes: | |
| 136 member.doc_js_interface_name = new_name | |
| 137 for member in idl_node.constants: | |
| 138 member.doc_js_interface_name = new_name | |
| 119 | 139 |
| 120 def rename_ext_attrs(ext_attrs_node): | 140 def rename_ext_attrs(ext_attrs_node): |
| 121 for type_valued_attribute_name in ['Supplemental']: | 141 for type_valued_attribute_name in ['Supplemental']: |
| 122 if type_valued_attribute_name in ext_attrs_node: | 142 if type_valued_attribute_name in ext_attrs_node: |
| 123 value = ext_attrs_node[type_valued_attribute_name] | 143 value = ext_attrs_node[type_valued_attribute_name] |
| 124 if isinstance(value, str): | 144 if isinstance(value, str): |
| 125 ext_attrs_node[type_valued_attribute_name] = rename(value) | 145 ext_attrs_node[type_valued_attribute_name] = rename(value) |
| 126 | 146 |
| 127 map(rename_node, idl_file.all(IDLInterface)) | 147 map(rename_node, idl_file.all(IDLInterface)) |
| 128 map(rename_node, idl_file.all(IDLType)) | 148 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): | 335 not new_interface.is_supplemental): |
| 316 old_interface.annotations[source] = new_interface.annotations[source] | 336 old_interface.annotations[source] = new_interface.annotations[source] |
| 317 changed = True | 337 changed = True |
| 318 | 338 |
| 319 def merge_list(what): | 339 def merge_list(what): |
| 320 old_list = old_interface.__dict__[what] | 340 old_list = old_interface.__dict__[what] |
| 321 new_list = new_interface.__dict__[what] | 341 new_list = new_interface.__dict__[what] |
| 322 | 342 |
| 323 if what != 'parents' and old_interface.id != new_interface.id: | 343 if what != 'parents' and old_interface.id != new_interface.id: |
| 324 for node in new_list: | 344 for node in new_list: |
| 345 node.doc_js_interface_name = old_interface.id | |
| 325 node.ext_attrs['ImplementedBy'] = new_interface.id | 346 node.ext_attrs['ImplementedBy'] = new_interface.id |
| 326 | 347 |
| 327 changed = self._merge_nodes(old_list, new_list, import_options) | 348 changed = self._merge_nodes(old_list, new_list, import_options) |
| 328 | 349 |
| 329 # Delete list items with zero remaining annotations. | 350 # Delete list items with zero remaining annotations. |
| 330 if changed and import_options.obsolete_old_declarations: | 351 if changed and import_options.obsolete_old_declarations: |
| 331 | 352 |
| 332 def has_annotations(idl_node): | 353 def has_annotations(idl_node): |
| 333 return len(idl_node.annotations) | 354 return len(idl_node.annotations) |
| 334 | 355 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 414 else: | 435 else: |
| 415 raise Exception("Supplemental target '%s' not found", target) | 436 raise Exception("Supplemental target '%s' not found", target) |
| 416 | 437 |
| 417 # Step 4: Resolve 'implements' statements | 438 # Step 4: Resolve 'implements' statements |
| 418 for impl_stmt, import_options in self._impl_stmts: | 439 for impl_stmt, import_options in self._impl_stmts: |
| 419 self._merge_impl_stmt(impl_stmt, import_options) | 440 self._merge_impl_stmt(impl_stmt, import_options) |
| 420 | 441 |
| 421 self._impl_stmts = [] | 442 self._impl_stmts = [] |
| 422 self._imported_interfaces = [] | 443 self._imported_interfaces = [] |
| 423 | 444 |
| 424 def import_idl_file(self, file_path, | 445 def import_idl_files(self, file_paths, import_options): |
| 425 import_options=DatabaseBuilderOptions()): | 446 # Parse the IDL files in parallel. |
| 426 """Parses, loads into memory and cleans up and IDL file""" | 447 result_queue = multiprocessing.Queue(len(file_paths)) |
| 427 idl_file = self._load_idl_file(file_path, import_options) | 448 jobs = [ multiprocessing.Process(target=_load_idl_file, |
| 449 args=(file_path, import_options, | |
| 450 result_queue)) | |
| 451 for file_path in file_paths ] | |
| 452 for job in jobs: | |
| 453 job.start() | |
| 454 try: | |
| 455 for job in jobs: | |
| 456 # Timeout and throw after 5 sec. | |
| 457 result = result_queue.get(True, 5) | |
| 458 if isinstance(result, IDLFile): | |
| 459 self._process_idl_file(result, import_options) | |
| 460 else: | |
| 461 raise result | |
| 462 except: | |
| 463 # Clean up child processes on error. | |
| 464 for job in jobs: | |
| 465 job.terminate() | |
|
Anton Muhin
2012/09/26 17:53:09
if you just terminate the parent process, will it
vsm
2012/09/28 16:17:25
Not clear from the docs if start can throw. I've
| |
| 466 raise | |
| 428 | 467 |
| 468 def _process_idl_file(self, idl_file, | |
| 469 import_options): | |
| 429 self._strip_ext_attributes(idl_file) | 470 self._strip_ext_attributes(idl_file) |
| 430 self._resolve_type_defs(idl_file) | 471 self._resolve_type_defs(idl_file) |
| 431 self._rename_types(idl_file, import_options) | 472 self._rename_types(idl_file, import_options) |
| 432 | 473 |
| 433 def enabled(idl_node): | 474 def enabled(idl_node): |
| 434 return self._is_node_enabled(idl_node, import_options.idl_defines) | 475 return self._is_node_enabled(idl_node, import_options.idl_defines) |
| 435 | 476 |
| 436 for module in idl_file.modules: | 477 for module in idl_file.modules: |
| 437 for interface in module.interfaces: | 478 for interface in module.interfaces: |
| 438 if not self._is_node_enabled(interface, import_options.idl_defines): | 479 if not self._is_node_enabled(interface, import_options.idl_defines): |
| 439 _logger.info('skipping interface %s/%s (source=%s file=%s)' | 480 _logger.info('skipping interface %s/%s (source=%s)' |
| 440 % (module.id, interface.id, import_options.source, | 481 % (module.id, interface.id, import_options.source)) |
| 441 file_path)) | |
| 442 continue | 482 continue |
| 443 | 483 |
| 444 _logger.info('importing interface %s/%s (source=%s file=%s)' | 484 _logger.info('importing interface %s/%s (source=%s)' |
| 445 % (module.id, interface.id, import_options.source, | 485 % (module.id, interface.id, import_options.source)) |
| 446 file_path)) | |
| 447 interface.attributes = filter(enabled, interface.attributes) | 486 interface.attributes = filter(enabled, interface.attributes) |
| 448 interface.operations = filter(enabled, interface.operations) | 487 interface.operations = filter(enabled, interface.operations) |
| 449 self._imported_interfaces.append((interface, module.id, import_options)) | 488 self._imported_interfaces.append((interface, module.id, import_options)) |
| 450 | 489 |
| 451 for implStmt in module.implementsStatements: | 490 for implStmt in module.implementsStatements: |
| 452 self._impl_stmts.append((implStmt, import_options)) | 491 self._impl_stmts.append((implStmt, import_options)) |
| 453 | 492 |
| 454 def _is_node_enabled(self, node, idl_defines): | 493 def _is_node_enabled(self, node, idl_defines): |
| 455 if not 'Conditional' in node.ext_attrs: | 494 if not 'Conditional' in node.ext_attrs: |
| 456 return True | 495 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 | 589 # 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 | 590 # 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. | 591 # 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)) | 592 interface = self._database.GetInterface(options.type_rename_map.get(type, type)) |
| 554 if 'V8EnabledPerContext' in attr.ext_attrs: | 593 if 'V8EnabledPerContext' in attr.ext_attrs: |
| 555 interface.ext_attrs['synthesizedV8EnabledPerContext'] = \ | 594 interface.ext_attrs['synthesizedV8EnabledPerContext'] = \ |
| 556 attr.ext_attrs['V8EnabledPerContext'] | 595 attr.ext_attrs['V8EnabledPerContext'] |
| 557 if 'V8EnabledAtRuntime' in attr.ext_attrs: | 596 if 'V8EnabledAtRuntime' in attr.ext_attrs: |
| 558 interface.ext_attrs['synthesizedV8EnabledAtRuntime'] = \ | 597 interface.ext_attrs['synthesizedV8EnabledAtRuntime'] = \ |
| 559 attr.ext_attrs['V8EnabledAtRuntime'] or attr.id | 598 attr.ext_attrs['V8EnabledAtRuntime'] or attr.id |
| OLD | NEW |