#!/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 logging
import monitored
import multiprocessing
import os
import os.path
import re
import sys
import tempfile
import time
import traceback

import idl_validator

import compiler
import compute_interfaces_info_individual
from compute_interfaces_info_individual import InterfaceInfoCollector
import idl_definitions

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'


class DatabaseBuilderOptions(object):
  """Used in specifying options when importing new interfaces"""

  def __init__(self,
      idl_defines=[],
      source=None, source_attributes={},
      rename_operation_arguments_on_merge=False,
      add_new_interfaces=True,
      obsolete_old_declarations=False,
      logging_level=logging.WARNING):
    """Constructor.
    Args:
      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_defines = idl_defines
    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
    _logger.setLevel(logging_level)


def format_exception(e):
    exception_list = traceback.format_stack()
    exception_list = exception_list[:-2]
    exception_list.extend(traceback.format_tb(sys.exc_info()[2]))
    exception_list.extend(traceback.format_exception_only(sys.exc_info()[0], sys.exc_info()[1]))

    exception_str = "Traceback (most recent call last):\n"
    exception_str += "".join(exception_list)
    # Removing the last \n
    exception_str = exception_str[:-1]

    return exception_str


# Compile IDL using Blink's IDL compiler.
def _compile_idl_file(build, file_name, import_options):
  try:
    idl_file_fullpath = os.path.realpath(file_name)
    idl_definition = build.idl_compiler.compile_file(idl_file_fullpath)
    return idl_definition
  except Exception as err:
    print 'ERROR: idl_compiler.py: ' + os.path.basename(file_name)
    print err
    print
    print 'Stack Dump:'
    print format_exception(err)

  return 1


# Create the Model (IDLFile) from the new AST of the compiled IDL file.
def _load_idl_file(build, file_name, import_options):
  try:
    # Compute interface name from IDL filename (it's one for one in WebKit).
    name = os.path.splitext(os.path.basename(file_name))[0]

    idl_definition = new_asts[name]
    return IDLFile(idl_definition, file_name)
  except Exception as err:
    print 'ERROR: loading AST from cache: ' + os.path.basename(file_name)
    print err
    print
    print 'Stack Dump:'
    print format_exception(err)

  return 1


# New IDL parser builder.
class Build():
    def __init__(self, provider):
        # TODO(terry): Consider using the generator to do the work today we're
        #              driven by the databasebuilder.  Blink compiler requires
        #              an output directory even though we don't use (yet). Might
        #              use the code generator portion of the new IDL compiler
        #              then we'd have a real output directory. Today we use the
        #              compiler to only create an AST.
        self.output_directory = tempfile.mkdtemp()
        attrib_file = os.path.join('Source', idl_validator.EXTENDED_ATTRIBUTES_FILENAME)
        # Create compiler.
        self.idl_compiler = compiler.IdlCompilerDart(self.output_directory,
                                            attrib_file,
                                            interfaces_info=provider._info_collector.interfaces_info,
                                            only_if_changed=True)

    def format_exception(self, e):
        exception_list = traceback.format_stack()
        exception_list = exception_list[:-2]
        exception_list.extend(traceback.format_tb(sys.exc_info()[2]))
        exception_list.extend(traceback.format_exception_only(sys.exc_info()[0], sys.exc_info()[1]))

        exception_str = "Traceback (most recent call last):\n"
        exception_str += "".join(exception_list)
        # Removing the last \n
        exception_str = exception_str[:-1]

        return exception_str

    def generate_from_idl(self, idl_file):
        try:
            idl_file_fullpath = os.path.realpath(idl_file)
            self.idl_compiler.compile_file(idl_file_fullpath)
        except Exception as err:
            print 'ERROR: idl_compiler.py: ' + os.path.basename(idl_file)
            print err
            print
            print 'Stack Dump:'
            print self.format_exception(err)

            return 1

        return IDLFile(idl_ast, file_name)


class DatabaseBuilder(object):
  def __init__(self, database):
    """DatabaseBuilder is used for importing and merging interfaces into
    the Database"""
    self._info_collector = InterfaceInfoCollector()

    self._database = database
    self._imported_interfaces = []
    self._impl_stmts = []
    self.conditionals_met = set()

    # Spin up the new IDL parser.
    self.build = Build(self)

    # Global typedef to mapping.
    self.global_type_defs = monitored.Dict('databasebuilder.global_type_defs', {
      'Transferable' : 'MessagePort',
    })

  # TODO(terry): Consider keeping richer type information (e.g.,
  #              IdlArrayOrSequenceType from the Blink parser) instead of just
  #              a type name.
  def _resolve_type_defs(self, idl_file):
    for type_node in idl_file.all(IDLType):
      resolved = False
      type_name = type_node.id
      for typedef in self.global_type_defs:
        seq_name_typedef = 'sequence<%s>' % typedef
        if type_name == typedef:
          type_node.id = self.global_type_defs[typedef]
          resolved = True
        elif type_name == seq_name_typedef:
          type_node.id = 'sequence<%s>' % self.global_type_defs[typedef]
          resolved = True
      if not(resolved):
        for typedef in idl_file.typeDefs:
          if type_name == typedef.id:
            type_node.id = typedef.type.id
            resolved = True

  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 _rename_types(self, idl_file, import_options):
    """Rename interface and type names with names provided in the
    options. Also clears scopes from scoped names"""

    strip_modules = lambda name: name.split('::')[-1]

    def rename_node(idl_node):
      idl_node.reset_id(strip_modules(idl_node.id))

    def rename_ext_attrs(ext_attrs_node):
      for type_valued_attribute_name in ['DartSupplemental']:
        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] = strip_modules(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, 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)

    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 '):]
      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_read_only:
        res.append('readonly')
      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:
        op = res[sig]
        # Only report if the the operations that match are either both suppressed
        # or both not suppressed.  Optional args aren't part of type signature
        # for this routine. Suppressing a non-optional type and supplementing
        # with an optional type appear the same.
        if idl_node.is_fc_suppressed == op.is_fc_suppressed:
          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:
        if name == 'ImplementedAs' and name in old_attrs:
          continue
        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 = old_node.arguments[i]
            new_arg = new_node.arguments[i]

            old_arg_name = old_arg.id
            new_arg_name = new_arg.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

            if self._merge_ext_attrs(old_arg.ext_attrs, new_arg.ext_attrs):
              changed = True

            # Merge in [Default=Undefined] and DOMString a = null handling in
            # IDL.  The IDL model (IDLArgument) coalesces these two different
            # default value syntaxes into the default_value* models.
            old_default_value = old_arg.default_value
            new_default_value = new_arg.default_value
            old_default_value_is_null = old_arg.default_value_is_null
            new_default_value_is_null = new_arg.default_value_is_null
            if old_default_value != new_default_value:
              old_arg.default_value = new_default_value
              changed = True
            if old_default_value_is_null != new_default_value_is_null:
              old_arg.default_value_is_null = new_default_value_is_null
              changed = True

            # Merge in any optional argument differences.
            old_optional = old_arg.optional
            new_optional = new_arg.optional
            if old_optional != new_optional:
              old_arg.optional = new_optional
              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.doc_js_interface_name = old_interface.id
          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))

    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 merge_imported_interfaces(self):
    """Merges all imported interfaces and loads them into the DB."""
    imported_interfaces = self._imported_interfaces

    # Step 1: Pre process imported interfaces
#    for interface, import_options in imported_interfaces.iteritems():
    for interface, import_options in imported_interfaces:
      self._annotate(interface, import_options)

    # Step 2: Add all new interfaces and merge overlapping ones
    for interface, import_options in 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, import_options in imported_interfaces:
      if interface.is_supplemental:
        target = interface.id
        if self._database.HasInterface(target):
          old_interface = self._database.GetInterface(target)
          self._merge_interfaces(old_interface, interface, import_options)
        else:
          _logger.warning("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 _compute_dart_idl_implements(self, idl_filename):
    full_path = os.path.realpath(idl_filename)

    with open(full_path) as f:
        idl_file_contents = f.read()

    implements_re = (r'^\s*'
                     r'(\w+)\s+'
                     r'implements\s+'
                     r'(\w+)\s*'
                     r';')

    implements_matches = re.finditer(implements_re, idl_file_contents, re.MULTILINE)
    return [match.groups() for match in implements_matches]

  # Compile the IDL file with the Blink compiler and remember each AST for the
  # IDL.
  def _blink_compile_idl_files(self, file_paths, import_options, is_dart_idl):
    if not(is_dart_idl):
      start_time = time.time()

    # Compute information for individual files
    # Information is stored in global variables interfaces_info and
    # partial_interface_files.
      for file_path in file_paths:
        self._info_collector.collect_info(file_path)

      end_time = time.time()
      print 'Compute dependencies %s seconds' % round((end_time - start_time), 2)
    else:
      # Compute the interface_info for dart.idl for implements defined.  This
      # file is special in that more than one interface can exist in this file.
      implement_pairs = self._compute_dart_idl_implements(file_paths[0])

      self._info_collector.interfaces_info['__dart_idl___'] = {
        'implement_pairs': implement_pairs,
      }

    # Parse the IDL files serially.
    start_time = time.time()

    for file_path in file_paths:
      file_path = os.path.normpath(file_path)
      ast = _compile_idl_file(self.build, file_path, import_options)
      self._process_ast(os.path.splitext(os.path.basename(file_path))[0], ast)

    end_time = time.time()
    print 'Compiled %s IDL files in %s seconds' % (len(file_paths),
                                                  round((end_time - start_time), 2))

  def _process_ast(self, filename, ast):
    if len(ast) == 1:
      ast = ast.values()[0]
    else:
      print 'ERROR: Processing AST: ' + os.path.basename(file_name)
    new_asts[filename] = ast

  def import_idl_files(self, file_paths, import_options, is_dart_idl):
    self._blink_compile_idl_files(file_paths, import_options, is_dart_idl)

    start_time = time.time()

    # Parse the IDL files in serial.
    for file_path in file_paths:
      file_path = os.path.normpath(file_path)
      idl_file = _load_idl_file(self.build, file_path, import_options)
      _logger.info('Processing %s' % os.path.splitext(os.path.basename(file_path))[0])
      self._process_idl_file(idl_file, import_options, is_dart_idl)

    end_time = time.time()

    print 'Total %s files %sprocessed in databasebuilder in %s seconds' % \
    (len(file_paths), '', round((end_time - start_time), 2))

  def _process_idl_file(self, idl_file, import_options, dart_idl = False):
    # TODO(terry): strip_ext_attributes on an idl_file does nothing.
    #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 interface in idl_file.interfaces:
      if not self._is_node_enabled(interface, import_options.idl_defines):
        _logger.info('skipping interface %s (source=%s)'
          % (interface.id, import_options.source))
        continue

      _logger.info('importing interface %s (source=%s file=%s)'
        % (interface.id, import_options.source, os.path.basename(idl_file.filename)))

      interface.attributes = filter(enabled, interface.attributes)
      interface.operations = filter(enabled, interface.operations)
      self._imported_interfaces.append((interface, import_options))

    # If an IDL dictionary then there is no implementsStatements.
    if hasattr(idl_file, 'implementsStatements'):
      for implStmt in idl_file.implementsStatements:
        self._impl_stmts.append((implStmt, import_options))

    for enum in idl_file.enums:
      self._database.AddEnum(enum)

    for dictionary in idl_file.dictionaries:
      self._database.AddDictionary(dictionary)

    # TODO(terry): Hack to remember all typedef unions they're mapped to any
    #              - no type.
    for typedef in idl_file.typeDefs:
      self._database.AddTypeDef(typedef)

  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('&'):
        condition = condition.strip()
        self.conditionals_met.add(condition)
        if not enabled(condition):
          return False
      return True

    for condition in conditional.split('|'):
      condition = condition.strip()
      self.conditionals_met.add(condition)
      if enabled(condition):
        return True
    return False

  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)

  def map_dictionaries(self):
    """Changes the type of operations/constructors arguments from an IDL
       dictionary to a Dictionary.  The IDL dictionary is just an enums of
       strings which are checked at run-time."""
    def dictionary_to_map(type_node):
      if self._database.HasDictionary(type_node.id):
        type_node.dictionary = type_node.id
        type_node.id = 'Dictionary'

    def all_types(node):
      map(dictionary_to_map, node.all(IDLType))

    for interface in self._database.GetInterfaces():
      map(all_types, interface.all(IDLExtAttrFunctionValue))
      map(all_types, interface.attributes)
      map(all_types, interface.operations)

  def fetch_constructor_data(self, options):
    window_interface = self._database.GetInterface('Window')
    for attr in window_interface.attributes:
      type = attr.type.id
      if not type.endswith('Constructor'):
        continue
      type = re.sub('(Constructor)+$', '', type)
      # TODO(antonm): Ideally we'd like to have pristine copy of WebKit IDLs and fetch
      # this information directly from it.  Unfortunately right now database is massaged
      # a lot so it's difficult to maintain necessary information on Window itself.
      interface = self._database.GetInterface(type)
      if 'V8EnabledPerContext' in attr.ext_attrs:
        interface.ext_attrs['synthesizedV8EnabledPerContext'] = \
            attr.ext_attrs['V8EnabledPerContext']
      if 'V8EnabledAtRuntime' in attr.ext_attrs:
        interface.ext_attrs['synthesizedV8EnabledAtRuntime'] = \
            attr.ext_attrs['V8EnabledAtRuntime'] or attr.id

  # Iterate of the database looking for relationships between dictionaries and
  # interfaces marked with NoInterfaceObject.  This mechanism can be used for
  # other IDL analysis.
  def examine_database(self):
    # Contains list of dictionary structure: {'dictionary': dictionary, 'usages': []}
    self._diag_dictionaries = [];
    self._dictionaries_used_types = [];

    # Record any dictionary.
    for dictionary in self._database.GetDictionaries():
      self._diag_dictionaries.append({'dictionary': dictionary, 'usages': []});

    # Contains list of NoInterfaceObject structures: {'no_interface_object': dictionary, 'usages': []}
    self._diag_no_interfaces = [];
    self._no_interfaces_used_types = [];

    # Record any interface with Blink IDL Extended Attribute 'NoInterfaceObject'.
    for interface in self._database.GetInterfaces():
      if interface.is_no_interface_object:
        self._diag_no_interfaces.append({'no_interface_object': interface, 'usages': []});

    for interface in self._database.GetInterfaces():
      self._constructors(interface)
      self._constructors(interface, check_dictionaries=False)

      for attribute in interface.attributes:
        self._attribute_operation(interface, attribute)
        self._attribute_operation(interface, attribute, check_dictionaries=False)

      for operation in interface.operations:
        self._attribute_operation(interface, operation)
        self._attribute_operation(interface, operation, check_dictionaries=False)

    # Report all dictionaries and their usage.
    self._output_examination()
    # Report all interface marked with NoInterfaceObject and their usage.
    self._output_examination(check_dictionaries=False)

    print '\nKey:'
    print '  (READ-ONLY) - read-only attribute has relationship'
    print '  (GET/SET)   - attribute has relationship'
    print '  RETURN      - operation\'s returned value has relationship'
    print '  (ARGUMENT)  - operation\'s argument(s) has relationship'
    print ''
    print '  (New)       - After dictionary name if constructor(s) exist'
    print '  (Ops,Props,New) after a NoInterfaceObject name is defined as:'
    print '    Ops       - number of operations for a NoInterfaceObject'
    print '    Props     - number of properties for a NoInterfaceObject'
    print '    New       - T(#) number constructors for a NoInterfaceObject'
    print '                F no constructors for a NoInterfaceObject'
    print '                e.g., an interface 5 operations, 3 properties and 2'
    print '                      constructors would display (5,3,T(2))'

    print '\n\nExamination Complete\n'

  def _output_examination(self, check_dictionaries=True):
    # Output diagnostics. First columns is Dictionary or NoInterfaceObject e.g.,
    # |  Dictionary  |  Used In Interface  |  Usage Operation/Attribute  |
    print '\n\n'
    title_bar = ['Dictionary', 'Used In Interface', 'Usage Operation/Attribute'] if check_dictionaries \
                else ['NoInterfaceObject (Ops,Props,New)', 'Used In Interface', 'Usage Operation/Attribute']
    self._tabulate_title(title_bar)
    diags = self._diag_dictionaries if check_dictionaries else self._diag_no_interfaces
    for diag in diags:
      if not(check_dictionaries):
        interface = diag['no_interface_object']
        ops_count = len(interface.operations)
        properties_count = len(interface.attributes)
        any_constructors = 'Constructor' in interface.ext_attrs
        constructors = 'T(%s)' % len(interface.ext_attrs['Constructor']) if any_constructors else 'F'
        interface_detail = '%s (%s,%s,%s)' % \
            (diag['no_interface_object'].id,
             ops_count,
             properties_count,
             constructors)
        self._tabulate([interface_detail, '', ''])
      else:
        dictionary = diag['dictionary']
        any_constructors = 'Constructor' in dictionary.ext_attrs
        self._tabulate(['%s%s' % (dictionary.id, ' (New)' if any_constructors else ''), '', ''])
      for usage in diag['usages']:
        detail = ''
        if 'attribute' in usage:
          attribute_type = 'READ-ONLY' if not usage['argument'] else 'GET/SET'
          detail = '(%s) %s' % (attribute_type, usage['attribute'])
        elif 'operation' in usage:
          detail = '%s %s%s' % ('RETURN' if usage['result'] else '',
                                         usage['operation'],
                                         '(ARGUMENT)' if usage['argument'] else '')
        self._tabulate([None, usage['interface'], detail])
      self._tabulate_break()

  # operation_or_attribute either IDLOperation or IDLAttribute if None then
  # its a constructor (IDLExtAttrFunctionValue).
  def _mark_usage(self, interface, operation_or_attribute = None, check_dictionaries=True):
    for diag in self._diag_dictionaries if check_dictionaries else self._diag_no_interfaces:
      for usage in diag['usages']:
        if not usage['interface']:
          usage['interface'] = interface.id
          if isinstance(operation_or_attribute, IDLOperation):
            usage['operation'] = operation_or_attribute.id
            if check_dictionaries:
              usage['result'] = hasattr(operation_or_attribute.type, 'dictionary') and \
                operation_or_attribute.type.dictionary == diag['dictionary'].id
            else:
              usage['result'] = operation_or_attribute.type.id == diag['no_interface_object'].id
            usage['argument'] = False
            for argument in operation_or_attribute.arguments:
              if check_dictionaries:
                arg = hasattr(argument.type, 'dictionary') and argument.type.dictionary == diag['dictionary'].id
              else:
                arg = argument.type.id == diag['no_interface_object'].id
              if arg:
                usage['argument'] = arg
          elif isinstance(operation_or_attribute, IDLAttribute):
            usage['attribute'] = operation_or_attribute.id
            usage['result'] = True
            usage['argument'] = not operation_or_attribute.is_read_only
          elif not operation_or_attribute:
            # Its a constructor only argument is dictionary or interface with NoInterfaceObject.
            usage['operation'] = 'constructor'
            usage['result'] = False
            usage['argument'] = True

  def _remember_usage(self, node, check_dictionaries=True):
    if check_dictionaries:
      used_types = self._dictionaries_used_types
      diag_list = self._diag_dictionaries
      diag_name = 'dictionary'
    else:
      used_types = self._no_interfaces_used_types
      diag_list = self._diag_no_interfaces
      diag_name = 'no_interface_object'

    if len(used_types) > 0:
      normalized_used = list(set(used_types))
      for recorded_id in normalized_used:
        for diag in diag_list:
          if diag[diag_name].id == recorded_id:
            diag['usages'].append({'interface': None, 'node': node})

  # Iterator function to look for any IDLType that is a dictionary then remember
  # that dictionary.
  def _dictionary_used(self, type_node):
    if hasattr(type_node, 'dictionary'):
      dictionary_id = type_node.dictionary
      if self._database.HasDictionary(dictionary_id):
        for diag_dictionary in self._diag_dictionaries:
          if diag_dictionary['dictionary'].id == dictionary_id:
            # Record the dictionary that was referenced.
            self._dictionaries_used_types.append(dictionary_id)
            return

      # If we get to this point, the IDL dictionary was never defined ... oops.
      print 'DIAGNOSE_ERROR: IDL Dictionary %s doesn\'t exist.' % dictionary_id

  # Iterator function to look for any IDLType that is an interface marked with
  # NoInterfaceObject then remember that interface.
  def _no_interface_used(self, type_node):
    if hasattr(type_node, 'id'):
      no_interface_id = type_node.id
      if self._database.HasInterface(no_interface_id):
        no_interface = self._database.GetInterface(no_interface_id)
        if no_interface.is_no_interface_object:
          for diag_no_interface in self._diag_no_interfaces:
            if diag_no_interface['no_interface_object'].id == no_interface_id:
              # Record the interface marked with NoInterfaceObject.
              self._no_interfaces_used_types.append(no_interface_id)
              return

  def _constructors(self, interface, check_dictionaries=True):
    if check_dictionaries:
      self._dictionaries_used_types = []
      constructor_function = self._dictionary_constructor_types
    else:
      self._no_interfaces_used_types = [];
      constructor_function = self._no_interface_constructor_types

    map(constructor_function, interface.all(IDLExtAttrFunctionValue))

    self._mark_usage(interface, check_dictionaries=check_dictionaries)

  # Scan an attribute or operation for a dictionary or interface with NoInterfaceObject
  # reference.  
  def _attribute_operation(self, interface, operation_attribute, check_dictionaries=True):
    if check_dictionaries:
      self._dictionaries_used_types = []
      used = self._dictionary_used
    else:
      self._no_interfaces_used_types = [];
      used = self._no_interface_used

    map(used, operation_attribute.all(IDLType))

    self._remember_usage(operation_attribute, check_dictionaries=check_dictionaries)
    self._mark_usage(interface, operation_attribute, check_dictionaries=check_dictionaries)

  # Iterator function for map to iterate over all constructor types
  # (IDLExtAttrFunctionValue) that have a dictionary reference.
  def _dictionary_constructor_types(self, node):
    self._dictionaries_used_types = []
    map(self._dictionary_used, node.all(IDLType))
    self._remember_usage(node)

  # Iterator function for map to iterate over all constructor types
  # (IDLExtAttrFunctionValue) that reference an interface with NoInterfaceObject.
  def _no_interface_constructor_types(self, node):
    self._no_interfaces_used_types = [];
    map(self._no_interface_used, node.all(IDLType))
    self._remember_usage(node, check_dictionaries=False)

  # Maximum width of each column.
  def _TABULATE_WIDTH(self):
    return 45

  def _tabulate_title(self, row_title):
    title_separator = "=" * self._TABULATE_WIDTH()
    self._tabulate([title_separator, title_separator, title_separator])
    self._tabulate(row_title)
    self._tabulate([title_separator, title_separator, title_separator])

  def _tabulate_break(self):
    break_separator = "-" * self._TABULATE_WIDTH()
    self._tabulate([break_separator, break_separator, break_separator])

  def _tabulate(self, columns):
    """Tabulate a list of columns for a row.  Each item in columns is a column
       value each column will be padded up to _TABULATE_WIDTH.  Each
       column starts/ends with a vertical bar '|' the format a row:

           | columns[0] | columns[1] | columns[2] | ... |
    """
    if len(columns) > 0:
      for column in columns:
        value = '' if not column else column
        sys.stdout.write('|{0:^{1}}'.format(value, self._TABULATE_WIDTH()))
    else:
      sys.stdout.write('|{0:^{1}}'.format('', self._TABULATE_WIDTH()))

    sys.stdout.write('|\n')
