Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Unified Diff: client/dom/scripts/databasebuilder.py

Issue 9845043: Rename client/{dom,html} to lib/{dom,html} . (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « client/dom/scripts/database_test.py ('k') | client/dom/scripts/databasebuilder_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: client/dom/scripts/databasebuilder.py
===================================================================
--- client/dom/scripts/databasebuilder.py (revision 5796)
+++ client/dom/scripts/databasebuilder.py (working copy)
@@ -1,615 +0,0 @@
-#!/usr/bin/python
-# Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-import copy
-import database
-import idlparser
-import logging
-import os
-import os.path
-
-from idlnode import *
-
-_logger = logging.getLogger('databasebuilder')
-
-# Used in source annotations to specify the parent interface declaring
-# a displaced declaration. The 'via' attribute specifies the parent interface
-# which implements a displaced declaration.
-_VIA_ANNOTATION_ATTR_NAME = 'via'
-
-# Used in source annotations to specify the module that the interface was
-# imported from.
-_MODULE_ANNOTATION_ATTR_NAME = 'module'
-
-
-class DatabaseBuilderOptions(object):
- """Used in specifying options when importing new interfaces"""
-
- def __init__(self,
- idl_syntax=idlparser.WEBIDL_SYNTAX,
- idl_defines=[],
- source=None, source_attributes={},
- type_rename_map={},
- rename_operation_arguments_on_merge=False,
- add_new_interfaces=True,
- obsolete_old_declarations=False):
- """Constructor.
- Args:
- idl_syntax -- the syntax of the IDL file that is imported.
- idl_defines -- list of definitions for the idl gcc pre-processor
- source -- the origin of the IDL file, used for annotating the
- database.
- source_attributes -- this map of attributes is used as
- annotation attributes.
- rename_operation_arguments_on_merge -- if True, will rename
- operation arguments when merging using the new name rather
- than the old.
- add_new_interfaces -- when False, if an interface is a new
- addition, it will be ignored.
- obsolete_old_declarations -- when True, if a declaration
- from a certain source is not re-declared, it will be removed.
- """
- self.source = source
- self.source_attributes = source_attributes
- self.idl_syntax = idl_syntax
- self.idl_defines = idl_defines
- self.type_rename_map = type_rename_map
- self.rename_operation_arguments_on_merge = \
- rename_operation_arguments_on_merge
- self.add_new_interfaces = add_new_interfaces
- self.obsolete_old_declarations = obsolete_old_declarations
-
-
-class DatabaseBuilder(object):
- def __init__(self, database):
- """DatabaseBuilder is used for importing and merging interfaces into
- the Database"""
- self._database = database
- self._imported_interfaces = []
- self._impl_stmts = []
- self._same_signatures = {}
-
- def _load_idl_file(self, file_name, import_options):
- """Loads an IDL file intor memory"""
- idl_parser = idlparser.IDLParser(import_options.idl_syntax)
-
- try:
- f = open(file_name, 'r')
- content = f.read()
- f.close()
-
- idl_ast = idl_parser.parse(content,
- defines=import_options.idl_defines)
- return IDLFile(idl_ast, file_name)
- except SyntaxError, e:
- raise RuntimeError('Failed to load file %s: %s' % (file_name, e))
-
- def _resolve_type_defs(self, idl_file):
- type_def_map = {}
- # build map
- for type_def in idl_file.all(IDLTypeDef):
- if type_def.type.id != type_def.id: # sanity check
- type_def_map[type_def.id] = type_def.type.id
- # use the map
- for type_node in idl_file.all(IDLType):
- while type_node.id in type_def_map:
- type_node.id = type_def_map[type_node.id]
-
- def _strip_ext_attributes(self, idl_file):
- """Strips unuseful extended attributes."""
- for ext_attrs in idl_file.all(IDLExtAttrs):
- # TODO: Decide which attributes are uninteresting.
- pass
-
- def _split_declarations(self, interface, optional_argument_whitelist):
- """Splits read-write attributes and operations with optional
- arguments into multiple declarations"""
-
- # split attributes into setters and getters
- new_attributes = []
- for attribute in interface.attributes:
- if attribute.is_fc_getter or attribute.is_fc_setter:
- new_attributes.append(attribute)
- continue
- getter_attr = copy.deepcopy(attribute)
- getter_attr.is_fc_getter = True
- new_attributes.append(getter_attr)
- if not attribute.is_read_only:
- setter_attr = copy.deepcopy(attribute)
- setter_attr.is_fc_setter = True
- new_attributes.append(setter_attr)
- interface.attributes = new_attributes
-
- # Remove optional annotations from legacy optional arguments.
- for op in interface.operations:
- for i in range(0, len(op.arguments)):
- argument = op.arguments[i]
-
- in_optional_whitelist = (interface.id, op.id, argument.id) in optional_argument_whitelist
- if in_optional_whitelist or set(['Optional', 'Callback']).issubset(argument.ext_attrs.keys()):
- argument.is_optional = True
- argument.ext_attrs['RequiredCppParameter'] = None
- continue
-
- if argument.is_optional:
- if 'Optional' in argument.ext_attrs:
- optional_value = argument.ext_attrs['Optional']
- if optional_value:
- argument.is_optional = False
- del argument.ext_attrs['Optional']
-
- # split operations with optional args into multiple operations
- new_ops = []
- for op in interface.operations:
- for i in range(0, len(op.arguments)):
- if op.arguments[i].is_optional:
- op.arguments[i].is_optional = False
- new_op = copy.deepcopy(op)
- new_op.arguments = new_op.arguments[:i]
- new_ops.append(new_op)
- new_ops.append(op)
- interface.operations = new_ops
-
- def _rename_types(self, idl_file, import_options):
- """Rename interface and type names with names provided in the
- options. Also clears scopes from scoped names"""
-
- def rename(name):
- name_parts = name.split('::')
- name = name_parts[-1]
- if name in import_options.type_rename_map:
- name = import_options.type_rename_map[name]
- return name
-
- def rename_node(idl_node):
- idl_node.id = rename(idl_node.id)
-
- def rename_ext_attrs(ext_attrs_node):
- for type_valued_attribute_name in ['Supplemental']:
- if type_valued_attribute_name in ext_attrs_node:
- value = ext_attrs_node[type_valued_attribute_name]
- if isinstance(value, str):
- ext_attrs_node[type_valued_attribute_name] = rename(value)
-
- map(rename_node, idl_file.all(IDLInterface))
- map(rename_node, idl_file.all(IDLType))
- map(rename_ext_attrs, idl_file.all(IDLExtAttrs))
-
- def _annotate(self, interface, module_name, import_options):
- """Adds @ annotations based on the source and source_attributes
- members of import_options."""
-
- source = import_options.source
- if not source:
- return
-
- def add_source_annotation(idl_node):
- annotation = IDLAnnotation(
- copy.deepcopy(import_options.source_attributes))
- idl_node.annotations[source] = annotation
- if ((isinstance(idl_node, IDLInterface) or
- isinstance(idl_node, IDLMember)) and
- idl_node.is_fc_suppressed):
- annotation['suppressed'] = None
-
- add_source_annotation(interface)
- interface.annotations[source][_MODULE_ANNOTATION_ATTR_NAME] = module_name
-
- map(add_source_annotation, interface.parents)
- map(add_source_annotation, interface.constants)
- map(add_source_annotation, interface.attributes)
- map(add_source_annotation, interface.operations)
-
- def _sign(self, node):
- """Computes a unique signature for the node, for merging purposed, by
- concatenating types and names in the declaration."""
- if isinstance(node, IDLType):
- res = node.id
- if res.startswith('unsigned '):
- res = res[len('unsigned '):]
- if res in self._same_signatures:
- res = self._same_signatures[res]
- return res
-
- res = []
- if isinstance(node, IDLInterface):
- res = ['interface', node.id]
- elif isinstance(node, IDLParentInterface):
- res = ['parent', self._sign(node.type)]
- elif isinstance(node, IDLOperation):
- res = ['op']
- for special in node.specials:
- res.append(special)
- if node.id is not None:
- res.append(node.id)
- for arg in node.arguments:
- res.append(self._sign(arg.type))
- res.append(self._sign(node.type))
- elif isinstance(node, IDLAttribute):
- res = []
- if node.is_fc_getter:
- res.append('getter')
- elif node.is_fc_setter:
- res.append('setter')
- res.append(node.id)
- res.append(self._sign(node.type))
- elif isinstance(node, IDLConstant):
- res = []
- res.append('const')
- res.append(node.id)
- res.append(node.value)
- res.append(self._sign(node.type))
- else:
- raise TypeError("Can't sign input of type %s" % type(node))
- return ':'.join(res)
-
- def _build_signatures_map(self, idl_node_list):
- """Creates a hash table mapping signatures to idl_nodes for the
- given list of nodes"""
- res = {}
- for idl_node in idl_node_list:
- sig = self._sign(idl_node)
- if sig is None:
- continue
- if sig in res:
- raise RuntimeError('Warning: Multiple members have the same '
- 'signature: "%s"' % sig)
- res[sig] = idl_node
- return res
-
- def _get_parent_interfaces(self, interface):
- """Return a list of all the parent interfaces of a given interface"""
- res = []
-
- def recurse(current_interface):
- if current_interface in res:
- return
- res.append(current_interface)
- for parent in current_interface.parents:
- parent_name = parent.type.id
- if self._database.HasInterface(parent_name):
- recurse(self._database.GetInterface(parent_name))
-
- recurse(interface)
- return res[1:]
-
- def _merge_ext_attrs(self, old_attrs, new_attrs):
- """Merges two sets of extended attributes.
-
- Returns: True if old_attrs has changed.
- """
- changed = False
- for (name, value) in new_attrs.items():
- if name in old_attrs and old_attrs[name] == value:
- pass # Identical
- else:
- old_attrs[name] = value
- changed = True
- return changed
-
- def _merge_nodes(self, old_list, new_list, import_options):
- """Merges two lists of nodes. Annotates nodes with the source of each
- node.
-
- Returns:
- True if the old_list has changed.
-
- Args:
- old_list -- the list to merge into.
- new_list -- list containing more nodes.
- import_options -- controls how merging is done.
- """
- changed = False
-
- source = import_options.source
-
- old_signatures_map = self._build_signatures_map(old_list)
- new_signatures_map = self._build_signatures_map(new_list)
-
- # Merge new items
- for (sig, new_node) in new_signatures_map.items():
- if sig not in old_signatures_map:
- # New node:
- old_list.append(new_node)
- changed = True
- else:
- # Merge old and new nodes:
- old_node = old_signatures_map[sig]
- if (source not in old_node.annotations
- and source in new_node.annotations):
- old_node.annotations[source] = new_node.annotations[source]
- changed = True
- # Maybe rename arguments:
- if isinstance(old_node, IDLOperation):
- for i in range(0, len(old_node.arguments)):
- old_arg_name = old_node.arguments[i].id
- new_arg_name = new_node.arguments[i].id
- if (old_arg_name != new_arg_name
- and (old_arg_name == 'arg'
- or old_arg_name.endswith('Arg')
- or import_options.rename_operation_arguments_on_merge)):
- old_node.arguments[i].id = new_arg_name
- changed = True
- # Maybe merge annotations:
- if (isinstance(old_node, IDLAttribute) or
- isinstance(old_node, IDLOperation)):
- if self._merge_ext_attrs(old_node.ext_attrs, new_node.ext_attrs):
- changed = True
-
- # Remove annotations on obsolete items from the same source
- if import_options.obsolete_old_declarations:
- for (sig, old_node) in old_signatures_map.items():
- if (source in old_node.annotations
- and sig not in new_signatures_map):
- _logger.warn('%s not available in %s anymore' %
- (sig, source))
- del old_node.annotations[source]
- changed = True
-
- return changed
-
- def _merge_interfaces(self, old_interface, new_interface, import_options):
- """Merges the new_interface into the old_interface, annotating the
- interface with the sources of each change."""
-
- changed = False
-
- source = import_options.source
- if (source and source not in old_interface.annotations and
- source in new_interface.annotations and
- not new_interface.is_supplemental):
- old_interface.annotations[source] = new_interface.annotations[source]
- changed = True
-
- def merge_list(what):
- old_list = old_interface.__dict__[what]
- new_list = new_interface.__dict__[what]
-
- if what != 'parents' and old_interface.id != new_interface.id:
- for node in new_list:
- node.ext_attrs['ImplementedBy'] = new_interface.id
-
- changed = self._merge_nodes(old_list, new_list, import_options)
-
- # Delete list items with zero remaining annotations.
- if changed and import_options.obsolete_old_declarations:
-
- def has_annotations(idl_node):
- return len(idl_node.annotations)
-
- old_interface.__dict__[what] = filter(has_annotations, old_list)
-
- return changed
-
- # Smartly merge various declarations:
- if merge_list('parents'):
- changed = True
- if merge_list('constants'):
- changed = True
- if merge_list('attributes'):
- changed = True
- if merge_list('operations'):
- changed = True
-
- if self._merge_ext_attrs(old_interface.ext_attrs, new_interface.ext_attrs):
- changed = True
-
- _logger.info('merged interface %s (changed=%s, supplemental=%s)' %
- (old_interface.id, changed, new_interface.is_supplemental))
-
- return changed
-
- def _merge_impl_stmt(self, impl_stmt, import_options):
- """Applies "X implements Y" statemetns on the proper places in the
- database"""
- implementor_name = impl_stmt.implementor.id
- implemented_name = impl_stmt.implemented.id
- _logger.info('merging impl stmt %s implements %s' %
- (implementor_name, implemented_name))
-
- if implementor_name == implemented_name:
- # After renaming, this might happen (e.g. Window impls
- # AbstractView, but AbstractView was renamed to Window).
- return
-
- source = import_options.source
- if self._database.HasInterface(implementor_name):
- interface = self._database.GetInterface(implementor_name)
- if interface.parents is None:
- interface.parents = []
- for parent in interface.parents:
- if parent.type.id == implemented_name:
- if source and source not in parent.annotations:
- parent.annotations[source] = IDLAnnotation(
- import_options.source_attributes)
- return
- # not found, so add new one
- parent = IDLParentInterface(None)
- parent.type = IDLType(implemented_name)
- if source:
- parent.annotations[source] = IDLAnnotation(
- import_options.source_attributes)
- interface.parents.append(parent)
-
- def set_same_signatures(self, signatures_table):
- """Customize signature calculations by providing a custom table
- indicating which types are equivalent"""
- self._same_signatures = signatures_table
-
- def merge_imported_interfaces(self, optional_argument_whitelist):
- """Merges all imported interfaces and loads them into the DB."""
-
- # Step 1: Pre process imported interfaces
- for interface, module_name, import_options in self._imported_interfaces:
- self._split_declarations(interface, optional_argument_whitelist)
- self._annotate(interface, module_name, import_options)
-
- # Step 2: Add all new interfaces and merge overlapping ones
- for interface, module_name, import_options in self._imported_interfaces:
- if not interface.is_supplemental:
- if self._database.HasInterface(interface.id):
- old_interface = self._database.GetInterface(interface.id)
- self._merge_interfaces(old_interface, interface, import_options)
- else:
- if import_options.add_new_interfaces:
- self._database.AddInterface(interface)
-
- # Step 3: Merge in supplemental interfaces
- for interface, module_name, import_options in self._imported_interfaces:
- if interface.is_supplemental:
- target_name = interface.ext_attrs['Supplemental']
- if target_name:
- # [Supplemental=DOMWindow] - merge into DOMWindow.
- target = target_name
- else:
- # [Supplemental] - merge into existing inteface with same name.
- target = interface.id
- if self._database.HasInterface(target):
- old_interface = self._database.GetInterface(target)
- self._merge_interfaces(old_interface, interface, import_options)
- else:
- raise Exception("Supplemental target '%s' not found", target)
-
- # Step 4: Resolve 'implements' statements
- for impl_stmt, import_options in self._impl_stmts:
- self._merge_impl_stmt(impl_stmt, import_options)
-
- self._impl_stmts = []
- self._imported_interfaces = []
-
- def import_idl_file(self, file_path,
- import_options=DatabaseBuilderOptions()):
- """Parses, loads into memory and cleans up and IDL file"""
- idl_file = self._load_idl_file(file_path, import_options)
-
- self._strip_ext_attributes(idl_file)
- self._resolve_type_defs(idl_file)
- self._rename_types(idl_file, import_options)
-
- def enabled(idl_node):
- return self._is_node_enabled(idl_node, import_options.idl_defines)
-
- for module in idl_file.modules:
- for interface in module.interfaces:
- if not self._is_node_enabled(interface, import_options.idl_defines):
- _logger.info('skipping interface %s/%s (source=%s file=%s)'
- % (module.id, interface.id, import_options.source,
- file_path))
- continue
-
- _logger.info('importing interface %s/%s (source=%s file=%s)'
- % (module.id, interface.id, import_options.source,
- file_path))
- interface.attributes = filter(enabled, interface.attributes)
- interface.operations = filter(enabled, interface.operations)
- self._imported_interfaces.append((interface, module.id, import_options))
-
- for implStmt in module.implementsStatements:
- self._impl_stmts.append((implStmt, import_options))
-
- def _is_node_enabled(self, node, idl_defines):
- if not 'Conditional' in node.ext_attrs:
- return True
-
- def enabled(condition):
- return 'ENABLE_%s' % condition in idl_defines
-
- conditional = node.ext_attrs['Conditional']
- if conditional.find('&') != -1:
- for condition in conditional.split('&'):
- if not enabled(condition):
- return False
- return True
-
- for condition in conditional.split('|'):
- if enabled(condition):
- return True
- return False
-
- def import_idl_directory(self, directory_path,
- import_options=DatabaseBuilderOptions()):
- """Parses, loads into memory and cleans up all IDL files in a given
- directory"""
- if not os.path.exists(directory_path):
- raise RuntimeError('directory not found: %s' % directory_path)
-
- def visitor(arg, dir_name, names):
- module = dir_name[len(directory_path) + 1:]
- for name in names:
- file_name = os.path.join(dir_name, name)
- (interface, ext) = os.path.splitext(file_name)
- if ext == '.idl' and not name.startswith('._'):
- self.import_idl_file(file_name, import_options)
- os.path.walk(directory_path, visitor, None)
-
- def fix_displacements(self, source):
- """E.g. In W3C, something is declared on HTMLDocument but in WebKit
- its on Document, so we need to mark that something in HTMLDocument
- with @WebKit(via=Document). The 'via' attribute specifies the
- parent interface that has the declaration."""
-
- for interface in self._database.GetInterfaces():
- changed = False
-
- _logger.info('fixing displacements in %s' % interface.id)
-
- for parent_interface in self._get_parent_interfaces(interface):
- _logger.info('scanning parent %s of %s' %
- (parent_interface.id, interface.id))
-
- def fix_nodes(local_list, parent_list):
- changed = False
- parent_signatures_map = self._build_signatures_map(
- parent_list)
- for idl_node in local_list:
- sig = self._sign(idl_node)
- if sig in parent_signatures_map:
- parent_member = parent_signatures_map[sig]
- if (source in parent_member.annotations
- and source not in idl_node.annotations
- and _VIA_ANNOTATION_ATTR_NAME
- not in parent_member.annotations[source]):
- idl_node.annotations[source] = IDLAnnotation(
- {_VIA_ANNOTATION_ATTR_NAME: parent_interface.id})
- changed = True
- return changed
-
- changed = fix_nodes(interface.constants,
- parent_interface.constants) or changed
- changed = fix_nodes(interface.attributes,
- parent_interface.attributes) or changed
- changed = fix_nodes(interface.operations,
- parent_interface.operations) or changed
- if changed:
- _logger.info('fixed displaced declarations in %s' %
- interface.id)
-
- def normalize_annotations(self, sources):
- """Makes the IDLs less verbose by removing annotation attributes
- that are identical to the ones defined at the interface level.
-
- Args:
- sources -- list of source names to normalize."""
- for interface in self._database.GetInterfaces():
- _logger.debug('normalizing annotations for %s' % interface.id)
- for source in sources:
- if (source not in interface.annotations or
- not interface.annotations[source]):
- continue
- top_level_annotation = interface.annotations[source]
-
- def normalize(idl_node):
- if (source in idl_node.annotations
- and idl_node.annotations[source]):
- annotation = idl_node.annotations[source]
- for name, value in annotation.items():
- if (name in top_level_annotation
- and value == top_level_annotation[name]):
- del annotation[name]
-
- map(normalize, interface.parents)
- map(normalize, interface.constants)
- map(normalize, interface.attributes)
- map(normalize, interface.operations)
« no previous file with comments | « client/dom/scripts/database_test.py ('k') | client/dom/scripts/databasebuilder_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698