def __init__(self, opts, info_provider):
     self._opts = opts
     self._info_provider = info_provider
     self._reader = IdlReader(info_provider.interfaces_info, opts.cache_dir)
     self._interface_contexts = {}
     self._include_files = set(INCLUDES)
     v8_types.set_component_dirs(
         info_provider.interfaces_info['component_dirs'])
Пример #2
0
 def __init__(self, cache_directory=None):
     self.reader = IdlReader(interfaces_info=None,
                             outputdir=cache_directory)
     self.interfaces_info = {}
     self.partial_interface_files = defaultdict(lambda: {
         'full_paths': [],
         'include_paths': [],
     })
     self.union_types = set()
Пример #3
0
def generate_conditional_features(info_provider, options, idl_filenames):
    reader = IdlReader(info_provider.interfaces_info, options.cache_directory)
    jinja_env = initialize_jinja_env(options.cache_directory)

    # Extract the bidirectional mapping of conditional features <-> interfaces
    # from the global info provider and the supplied list of IDL files.
    feature_info = conditional_features_info(info_provider, reader,
                                             idl_filenames,
                                             options.target_component.lower())

    # Convert that mapping into the context required for the Jinja2 templates.
    template_context = conditional_features_context(MODULE_PYNAME,
                                                    feature_info)

    # Generate and write out the header file
    header_text = render_template(
        jinja_env.get_template("ConditionalFeaturesFor%s.h.tmpl" %
                               options.target_component.title()),
        template_context)
    header_path = posixpath.join(
        options.output_directory,
        "ConditionalFeaturesFor%s.h" % options.target_component.title())
    write_file(header_text, header_path)

    # Generate and write out the implementation file
    cpp_text = render_template(
        jinja_env.get_template("ConditionalFeaturesFor%s.cpp.tmpl" %
                               options.target_component.title()),
        template_context)
    cpp_path = posixpath.join(
        options.output_directory,
        "ConditionalFeaturesFor%s.cpp" % options.target_component.title())
    write_file(cpp_text, cpp_path)
Пример #4
0
def generate_origin_trial_features(info_provider, options, idl_filenames):
    reader = IdlReader(info_provider.interfaces_info, options.cache_directory)
    jinja_env = initialize_jinja_env(options.cache_directory)

    # Extract the bidirectional mapping of conditional features <-> interfaces
    # from the global info provider and the supplied list of IDL files.
    feature_info = origin_trial_features_info(info_provider, reader,
                                              idl_filenames,
                                              options.target_component)

    # Convert that mapping into the context required for the Jinja2 templates.
    template_context = origin_trial_features_context(MODULE_PYNAME,
                                                     feature_info)

    file_basename = 'origin_trial_features_for_%s' % options.target_component

    # Generate and write out the header file
    header_text = render_template(
        jinja_env.get_template(file_basename + '.h.tmpl'), template_context)
    header_path = posixpath.join(options.output_directory,
                                 file_basename + '.h')
    write_file(header_text, header_path)

    # Generate and write out the implementation file
    cpp_text = render_template(
        jinja_env.get_template(file_basename + '.cc.tmpl'), template_context)
    cpp_path = posixpath.join(options.output_directory, file_basename + '.cc')
    write_file(cpp_text, cpp_path)
Пример #5
0
 def __init__(
     self,
     output_directory,
     cache_directory="",
     code_generator=None,
     interfaces_info=None,
     interfaces_info_filename="",
     only_if_changed=False,
 ):
     """
     Args:
         interfaces_info:
             interfaces_info dict
             (avoids auxiliary file in run-bindings-tests)
         interfaces_info_file: filename of pickled interfaces_info
     """
     cache_directory = cache_directory or output_directory
     self.cache_directory = cache_directory
     self.code_generator = code_generator
     if interfaces_info_filename:
         with open(interfaces_info_filename) as interfaces_info_file:
             interfaces_info = pickle.load(interfaces_info_file)
     self.interfaces_info = interfaces_info
     self.only_if_changed = only_if_changed
     self.output_directory = output_directory
     self.reader = IdlReader(interfaces_info, cache_directory)
Пример #6
0
class IdlCompiler(object):
    """Abstract Base Class for IDL compilers.

    In concrete classes:
    * self.code_generator must be set, implementing generate_code()
      (returning a list of output code), and
    * compile_file() must be implemented (handling output filenames).
    """
    __metaclass__ = abc.ABCMeta

    def __init__(self,
                 output_directory,
                 code_generator=None,
                 interfaces_info=None,
                 interfaces_info_filename='',
                 only_if_changed=False):
        """
        Args:
            interfaces_info:
                interfaces_info dict
                (avoids auxiliary file in run-bindings-tests)
            interfaces_info_file: filename of pickled interfaces_info
        """
        self.code_generator = code_generator
        if interfaces_info_filename:
            with open(interfaces_info_filename) as interfaces_info_file:
                interfaces_info = pickle.load(interfaces_info_file)
        self.interfaces_info = interfaces_info

        self.only_if_changed = only_if_changed
        self.output_directory = output_directory
        self.reader = IdlReader(interfaces_info, output_directory)

    def compile_and_write(self, idl_filename, output_filenames):
        interface_name = idl_filename_to_interface_name(idl_filename)
        idl_pickle_filename = os.path.join(
            self.output_directory, '%s_globals.pickle' % interface_name)
        definitions = self.reader.read_idl_definitions(idl_filename)
        output_code_list = self.code_generator.generate_code(
            definitions, interface_name, idl_filename, idl_pickle_filename,
            self.only_if_changed)

        for output_code, output_filename in zip(output_code_list,
                                                output_filenames):
            write_file(output_code, output_filename, self.only_if_changed)

    def generate_global_and_write(self, global_entries, output_filenames):
        output_code_list = self.code_generator.generate_globals(global_entries)
        for output_code, output_filename in zip(output_code_list,
                                                output_filenames):
            write_file(output_code, output_filename, self.only_if_changed)

    def generate_dart_blink_and_write(self, global_entries, output_filename):
        output_code = self.code_generator.generate_dart_blink(global_entries)
        write_file(output_code, output_filename, self.only_if_changed)

    @abc.abstractmethod
    def compile_file(self, idl_filename):
        pass
 def __init__(self, opts, info_provider):
     self._opts = opts
     self._info_provider = info_provider
     self._reader = IdlReader(
         info_provider.interfaces_info, opts.cache_dir)
     self._interface_contexts = {}
     self._include_files = set(INCLUDES)
     v8_types.set_component_dirs(info_provider.interfaces_info['component_dirs'])
 def __init__(self, cache_directory=None):
     self.reader = IdlReader(interfaces_info=None, outputdir=cache_directory)
     self.interfaces_info = {}
     self.partial_interface_files = defaultdict(lambda: {
         'full_paths': [],
         'include_paths': [],
     })
     self.union_types = set()
Пример #9
0
class IdlCompiler(object):
    """Abstract Base Class for IDL compilers.

    In concrete classes:
    * self.code_generator must be set, implementing generate_code()
      (returning a list of output code), and
    * compile_file() must be implemented (handling output filenames).
    """
    __metaclass__ = abc.ABCMeta

    def __init__(self, output_directory, code_generator=None,
                 interfaces_info=None, interfaces_info_filename='',
                 only_if_changed=False):
        """
        Args:
            interfaces_info:
                interfaces_info dict
                (avoids auxiliary file in run-bindings-tests)
            interfaces_info_file: filename of pickled interfaces_info
        """
        self.code_generator = code_generator
        if interfaces_info_filename:
            with open(interfaces_info_filename) as interfaces_info_file:
                interfaces_info = pickle.load(interfaces_info_file)
        self.interfaces_info = interfaces_info

        self.only_if_changed = only_if_changed
        self.output_directory = output_directory
        self.reader = IdlReader(interfaces_info, output_directory)

    def compile_and_write(self, idl_filename, output_filenames):
        interface_name = idl_filename_to_interface_name(idl_filename)
        idl_pickle_filename = os.path.join(self.output_directory,
                                           '%s_globals.pickle' % interface_name)
        definitions = self.reader.read_idl_definitions(idl_filename)
        output_code_list = self.code_generator.generate_code(definitions,
                                                             interface_name,
                                                             idl_filename,
                                                             idl_pickle_filename,
                                                             self.only_if_changed)

        for output_code, output_filename in zip(output_code_list, output_filenames):
            write_file(output_code, output_filename, self.only_if_changed)

    def generate_global_and_write(self, global_entries, output_filenames):
        output_code_list = self.code_generator.generate_globals(global_entries)
        for output_code, output_filename in zip(output_code_list, output_filenames):
            write_file(output_code, output_filename, self.only_if_changed)

    def generate_dart_blink_and_write(self, global_entries, output_filename):
        output_code = self.code_generator.generate_dart_blink(global_entries)
        write_file(output_code, output_filename, self.only_if_changed)

    @abc.abstractmethod
    def compile_file(self, idl_filename):
        pass
Пример #10
0
    def __init__(self, output_directory, code_generator=None,
                 interfaces_info=None, interfaces_info_filename='',
                 only_if_changed=False):
        """
        Args:
            interfaces_info:
                interfaces_info dict
                (avoids auxiliary file in run-bindings-tests)
            interfaces_info_file: filename of pickled interfaces_info
        """
        self.code_generator = code_generator
        if interfaces_info_filename:
            with open(interfaces_info_filename) as interfaces_info_file:
                interfaces_info = pickle.load(interfaces_info_file)
        self.interfaces_info = interfaces_info

        self.only_if_changed = only_if_changed
        self.output_directory = output_directory
        self.reader = IdlReader(interfaces_info, output_directory)
 def __init__(self, output_directory, cache_directory=None,
              code_generator_class=None, info_provider=None,
              target_component=None):
     """
     Args:
       output_directory: directory to put output files.
       cache_directory: directory which contains PLY caches.
       code_generator_class: code generator class to be used.
       info_provider: component-specific information provider.
       target_component: component to be processed.
     """
     self.cache_directory = cache_directory
     self.info_provider = info_provider
     self.output_directory = output_directory
     self.target_component = target_component
     self.reader = IdlReader(info_provider.interfaces_info, cache_directory)
     self.code_generator = code_generator_class(self.info_provider,
                                                self.cache_directory,
                                                self.output_directory)
Пример #12
0
 def __init__(self,
              root_directory,
              extend_attributes_filename,
              cache_directory=None):
     self.reader = IdlReader(
         interfaces_info=None,
         outputdir=cache_directory,
         extend_attributes_filename=extend_attributes_filename)
     self.interfaces_info = {}
     self.partial_interface_files = defaultdict(lambda: {
         'full_paths': [],
         'include_paths': [],
     })
     self.enumerations = {}
     self.union_types = set()
     self.typedefs = {}
     self.callback_functions = {}
     self.root_path = root_directory
     self.referenced_from_partial_interfaces = defaultdict(lambda: set())
Пример #13
0
def collect_idl_files(webkit_root):
    from idl_reader import IdlReader
    rdr = IdlReader()

    idl_map = {}
    imp_map = {}
    alias_map = {}
    fcount = 0
    for part in ["core", "modules"]:
        search_root = os.path.join(webkit_root, VARIANT['Source'], part)
        for node, dirs, files in os.walk(search_root):
            for idl in fnmatch.filter(files, "*.idl"):
                idl_path = os.path.join(node, idl)
                if '/testing/' in idl_path:
                    print >> sys.stderr, "Ignoring 'testing' IDL file '%s'" % idl_path
                    continue
                idl_data = rdr.read_idl_file(idl_path)
                fcount += 1
                for imp_left, imp_right in idl_implementations(idl_data):
                    try:
                        imp_map[imp_left].add((imp_right, idl_path))
                    except KeyError:
                        imp_map[imp_left] = set([(imp_right, idl_path)])
                for iface, idef in idl_data.interfaces.items():
                    if 'NamedConstructor' in idef.extended_attributes:
                        alias_map[idef.extended_attributes[
                            'NamedConstructor']] = iface
                    try:
                        idl_list = idl_map[iface]
                        if idef.is_partial:
                            idl_list.append((idl_path, idef))
                        else:
                            idl_list.insert(0, (idl_path, idef))
                    except KeyError:
                        idl_map[iface] = [(idl_path, idef)]

    print >> sys.stderr, "Processed %d IDL files" % fcount
    return idl_map, imp_map, alias_map
Пример #14
0
class IdlCompiler(object):
    """Abstract Base Class for IDL compilers.

    In concrete classes:
    * self.code_generator must be set, implementing generate_code()
      (returning a list of output code), and
    * compile_file() must be implemented (handling output filenames).
    """
    __metaclass__ = abc.ABCMeta

    def __init__(self,
                 output_directory,
                 cache_directory=None,
                 code_generator=None,
                 info_provider=None,
                 only_if_changed=False,
                 target_component=None):
        """
        Args:
          output_directory: directory to put output files.
          cache_directory: directory which contains PLY caches.
          code_generator: code generator to be used.
          info_provider: component-specific information provider.
          only_if_changed: True when the compiler should only write output files
            when the contents are changed.
          target_component: component to be processed.
        """
        self.cache_directory = cache_directory
        self.code_generator = code_generator
        self.info_provider = info_provider
        self.only_if_changed = only_if_changed
        self.output_directory = output_directory
        self.target_component = target_component
        self.reader = IdlReader(info_provider.interfaces_info, cache_directory)

    def compile_and_write(self, idl_filename):
        interface_name = idl_filename_to_interface_name(idl_filename)
        definitions = self.reader.read_idl_definitions(idl_filename)
        target_component = self.target_component or idl_filename_to_component(
            idl_filename)
        target_definitions = definitions[target_component]
        output_code_list = self.code_generator.generate_code(
            target_definitions, interface_name)
        for output_path, output_code in output_code_list:
            write_file(output_code, output_path, self.only_if_changed)

    @abc.abstractmethod
    def compile_file(self, idl_filename):
        pass
Пример #15
0
 def __init__(self,
              output_directory,
              cache_directory=None,
              code_generator=None,
              info_provider=None,
              only_if_changed=False,
              target_component=None):
     """
     Args:
       output_directory: directory to put output files.
       cache_directory: directory which contains PLY caches.
       code_generator: code generator to be used.
       info_provider: component-specific information provider.
       only_if_changed: True when the compiler should only write output files
         when the contents are changed.
       target_component: component to be processed.
     """
     self.cache_directory = cache_directory
     self.code_generator = code_generator
     self.info_provider = info_provider
     self.only_if_changed = only_if_changed
     self.output_directory = output_directory
     self.target_component = target_component
     self.reader = IdlReader(info_provider.interfaces_info, cache_directory)
Пример #16
0
class IdlCompiler(object):
    """The IDL Compiler.

    """
    __metaclass__ = abc.ABCMeta

    def __init__(self,
                 output_directory,
                 cache_directory=None,
                 code_generator_class=None,
                 snake_case_generated_files=False,
                 info_provider=None,
                 target_component=None):
        """
        Args:
          output_directory: directory to put output files.
          cache_directory: directory which contains PLY caches.
          code_generator_class: code generator class to be used.
          info_provider: component-specific information provider.
          target_component: component to be processed.
        """
        self.cache_directory = cache_directory
        self.info_provider = info_provider
        self.output_directory = output_directory
        self.target_component = target_component
        self.reader = IdlReader(info_provider.interfaces_info, cache_directory)
        self.code_generator = code_generator_class(self.info_provider,
                                                   self.cache_directory,
                                                   self.output_directory,
                                                   snake_case_generated_files)

    def compile_and_write(self, idl_filename):
        definitions = self.reader.read_idl_definitions(idl_filename)
        target_definitions = definitions[self.target_component]
        interface_name = target_definitions.first_name
        output_code_list = self.code_generator.generate_code(
            target_definitions, interface_name)

        # Generator may choose to omit the file.
        if output_code_list is None:
            return

        for output_path, output_code in output_code_list:
            write_file(output_code, output_path)

    def compile_file(self, idl_filename):
        self.compile_and_write(idl_filename)
Пример #17
0
class IdlCompiler(object):
    """Abstract Base Class for IDL compilers.

    In concrete classes:
    * self.code_generator must be set, implementing generate_code()
      (returning a list of output code), and
    * compile_file() must be implemented (handling output filenames).
    """
    __metaclass__ = abc.ABCMeta

    def __init__(self,
                 output_directory,
                 cache_directory='',
                 code_generator=None,
                 interfaces_info=None,
                 interfaces_info_filename='',
                 only_if_changed=False):
        """
        Args:
            interfaces_info:
                interfaces_info dict
                (avoids auxiliary file in run-bindings-tests)
            interfaces_info_file: filename of pickled interfaces_info
        """
        cache_directory = cache_directory or output_directory
        self.cache_directory = cache_directory
        self.code_generator = code_generator
        if interfaces_info_filename:
            with open(interfaces_info_filename) as interfaces_info_file:
                interfaces_info = pickle.load(interfaces_info_file)
        self.interfaces_info = interfaces_info
        self.only_if_changed = only_if_changed
        self.output_directory = output_directory
        self.reader = IdlReader(interfaces_info, cache_directory)

    def compile_and_write(self, idl_filename):
        interface_name = idl_filename_to_interface_name(idl_filename)
        component = idl_filename_to_component(idl_filename)
        definitions = self.reader.read_idl_definitions(idl_filename)
        output_code_list = self.code_generator.generate_code(
            definitions[component], interface_name)
        for output_path, output_code in output_code_list:
            write_file(output_code, output_path, self.only_if_changed)

    @abc.abstractmethod
    def compile_file(self, idl_filename):
        pass
Пример #18
0
class IdlCompiler(object):
    """Abstract Base Class for IDL compilers.

    In concrete classes:
    * self.code_generator must be set, implementing generate_code()
      (returning a list of output code), and
    * compile_file() must be implemented (handling output filenames).
    """
    __metaclass__ = abc.ABCMeta

    def __init__(self, output_directory, cache_directory=None,
                 code_generator=None, interfaces_info=None,
                 interfaces_info_filename='', only_if_changed=False,
                 target_component=None):
        """
        Args:
            interfaces_info:
                interfaces_info dict
                (avoids auxiliary file in run-bindings-tests)
            interfaces_info_file: filename of pickled interfaces_info
        """
        self.cache_directory = cache_directory
        self.code_generator = code_generator
        if interfaces_info_filename:
            with open(interfaces_info_filename) as interfaces_info_file:
                interfaces_info = pickle.load(interfaces_info_file)
        self.interfaces_info = interfaces_info
        self.only_if_changed = only_if_changed
        self.output_directory = output_directory
        self.target_component = target_component
        self.reader = IdlReader(interfaces_info, cache_directory)

    def compile_and_write(self, idl_filename):
        interface_name = idl_filename_to_interface_name(idl_filename)
        definitions = self.reader.read_idl_definitions(idl_filename)
        target_component = self.target_component or idl_filename_to_component(idl_filename)
        target_definitions = definitions[target_component]
        output_code_list = self.code_generator.generate_code(
            target_definitions, interface_name)
        for output_path, output_code in output_code_list:
            write_file(output_code, output_path, self.only_if_changed)

    @abc.abstractmethod
    def compile_file(self, idl_filename):
        pass
Пример #19
0
class IdlCompiler(object):
    """Abstract Base Class for IDL compilers.

    In concrete classes:
    * self.code_generator must be set, implementing generate_code()
      (returning a list of output code), and
    * compile_file() must be implemented (handling output filenames).
    """
    __metaclass__ = abc.ABCMeta

    def __init__(self, output_directory, cache_directory=None,
                 code_generator=None, info_provider=None,
                 only_if_changed=False, target_component=None):
        """
        Args:
          output_directory: directory to put output files.
          cache_directory: directory which contains PLY caches.
          code_generator: code generator to be used.
          info_provider: component-specific information provider.
          only_if_changed: True when the compiler should only write output files
            when the contents are changed.
          target_component: component to be processed.
        """
        self.cache_directory = cache_directory
        self.code_generator = code_generator
        self.info_provider = info_provider
        self.only_if_changed = only_if_changed
        self.output_directory = output_directory
        self.target_component = target_component
        self.reader = IdlReader(info_provider.interfaces_info, cache_directory)

    def compile_and_write(self, idl_filename):
        interface_name = idl_filename_to_interface_name(idl_filename)
        definitions = self.reader.read_idl_definitions(idl_filename)
        target_component = self.target_component or idl_filename_to_component(idl_filename)
        target_definitions = definitions[target_component]
        output_code_list = self.code_generator.generate_code(
            target_definitions, interface_name)
        for output_path, output_code in output_code_list:
            write_file(output_code, output_path, self.only_if_changed)

    @abc.abstractmethod
    def compile_file(self, idl_filename):
        pass
Пример #20
0
class IdlCompiler(object):
    """Abstract Base Class for IDL compilers.

    In concrete classes:
    * self.code_generator must be set, implementing generate_code()
      (returning a list of output code), and
    * compile_file() must be implemented (handling output filenames).
    """
    __metaclass__ = abc.ABCMeta

    def __init__(self,
                 output_directory,
                 code_generator=None,
                 interfaces_info=None,
                 interfaces_info_filename='',
                 only_if_changed=False):
        """
        Args:
            interfaces_info:
                interfaces_info dict
                (avoids auxiliary file in run-bindings-tests)
            interfaces_info_file: filename of pickled interfaces_info
        """
        self.code_generator = code_generator
        if interfaces_info_filename:
            with open(interfaces_info_filename) as interfaces_info_file:
                interfaces_info = pickle.load(interfaces_info_file)
        self.interfaces_info = interfaces_info

        self.only_if_changed = only_if_changed
        self.output_directory = output_directory
        self.reader = IdlReader(interfaces_info, output_directory, True)

    def compile_and_write(self, idl_filename, output_filenames):
        # Only compile the IDL file and return the AST.
        definitions = self.reader.read_idl_definitions(idl_filename)
        return definitions

    def generate_global_and_write(self, output_filenames):
        pass

    @abc.abstractmethod
    def compile_file(self, idl_filename):
        pass
Пример #21
0
class IdlCompiler(object):
    """The IDL Compiler.

    """
    __metaclass__ = abc.ABCMeta

    def __init__(self, output_directory, cache_directory=None,
                 code_generator_class=None, info_provider=None,
                 target_component=None):
        """
        Args:
          output_directory: directory to put output files.
          cache_directory: directory which contains PLY caches.
          code_generator_class: code generator class to be used.
          info_provider: component-specific information provider.
          target_component: component to be processed.
        """
        self.cache_directory = cache_directory
        self.info_provider = info_provider
        self.output_directory = output_directory
        self.target_component = target_component
        self.reader = IdlReader(info_provider.interfaces_info, cache_directory)
        self.code_generator = code_generator_class(self.info_provider,
                                                   self.cache_directory,
                                                   self.output_directory)

    def compile_and_write(self, idl_filename):
        interface_name = idl_filename_to_interface_name(idl_filename)
        definitions = self.reader.read_idl_definitions(idl_filename)
        target_definitions = definitions[self.target_component]
        output_code_list = self.code_generator.generate_code(
            target_definitions, interface_name)

        # Generator may choose to omit the file.
        if output_code_list is None:
            return

        for output_path, output_code in output_code_list:
            write_file(output_code, output_path)

    def compile_file(self, idl_filename):
        self.compile_and_write(idl_filename)
Пример #22
0
 def __init__(self, output_directory, cache_directory=None,
              code_generator=None, info_provider=None,
              only_if_changed=False, target_component=None):
     """
     Args:
       output_directory: directory to put output files.
       cache_directory: directory which contains PLY caches.
       code_generator: code generator to be used.
       info_provider: component-specific information provider.
       only_if_changed: True when the compiler should only write output files
         when the contents are changed.
       target_component: component to be processed.
     """
     self.cache_directory = cache_directory
     self.code_generator = code_generator
     self.info_provider = info_provider
     self.only_if_changed = only_if_changed
     self.output_directory = output_directory
     self.target_component = target_component
     self.reader = IdlReader(info_provider.interfaces_info, cache_directory)
Пример #23
0
class IdlCompiler(object):
    """Abstract Base Class for IDL compilers.

    In concrete classes:
    * self.code_generator must be set, implementing generate_code()
      (returning a list of output code), and
    * compile_file() must be implemented (handling output filenames).
    """
    __metaclass__ = abc.ABCMeta

    def __init__(self, output_directory, code_generator=None,
                 interfaces_info=None, interfaces_info_filename='',
                 only_if_changed=False):
        """
        Args:
            interfaces_info:
                interfaces_info dict
                (avoids auxiliary file in run-bindings-tests)
            interfaces_info_file: filename of pickled interfaces_info
        """
        self.code_generator = code_generator
        if interfaces_info_filename:
            with open(interfaces_info_filename) as interfaces_info_file:
                interfaces_info = pickle.load(interfaces_info_file)
        self.interfaces_info = interfaces_info

        self.only_if_changed = only_if_changed
        self.output_directory = output_directory
        self.reader = IdlReader(interfaces_info, output_directory, True)

    def compile_and_write(self, idl_filename, output_filenames):
        # Only compile the IDL file and return the AST.
        definitions = self.reader.read_idl_definitions(idl_filename)
        return definitions

    def generate_global_and_write(self, output_filenames):
        pass

    @abc.abstractmethod
    def compile_file(self, idl_filename):
        pass
Пример #24
0
class InterfaceInfoCollector(object):
    """A class that collects interface information from idl files."""
    def __init__(self, cache_directory=None):
        self.reader = IdlReader(interfaces_info=None,
                                outputdir=cache_directory)
        self.interfaces_info = {}
        self.partial_interface_files = defaultdict(lambda: {
            'full_paths': [],
            'include_paths': [],
        })
        self.enumerations = {}
        self.union_types = set()
        self.typedefs = {}
        self.callback_functions = {}

    def add_paths_to_partials_dict(self, partial_interface_name, full_path,
                                   include_paths):
        paths_dict = self.partial_interface_files[partial_interface_name]
        paths_dict['full_paths'].append(full_path)
        paths_dict['include_paths'].extend(include_paths)

    def check_enum_consistency(self, enum):
        existing_enum = self.enumerations.get(enum.name)
        if not existing_enum:
            return True
        # TODO(bashi): Ideally we should not allow multiple enum declarations
        # but we allow them to work around core/module separation.
        if len(existing_enum.values) != len(enum.values):
            return False
        return all(value in existing_enum.values for value in enum.values)

    def collect_info(self, idl_filename):
        """Reads an idl file and collects information which is required by the
        binding code generation."""
        def collect_unforgeable_attributes(definition, idl_filename):
            """Collects [Unforgeable] attributes so that we can define them on
            sub-interfaces later.  The resulting structure is as follows.
                interfaces_info[interface_name] = {
                    'unforgeable_attributes': [IdlAttribute, ...],
                    ...
                }
            """
            interface_info = {}
            unforgeable_attributes = get_unforgeable_attributes_from_definition(
                definition)
            if not unforgeable_attributes:
                return interface_info

            if definition.is_partial:
                interface_basename = idl_filename_to_interface_name(
                    idl_filename)
                # TODO(yukishiino): [PartialInterfaceImplementedAs] is treated
                # in interface_dependency_resolver.transfer_extended_attributes.
                # Come up with a better way to keep them consistent.
                for attr in unforgeable_attributes:
                    attr.extended_attributes[
                        'PartialInterfaceImplementedAs'] = definition.extended_attributes.get(
                            'ImplementedAs', interface_basename)
            interface_info['unforgeable_attributes'] = unforgeable_attributes
            return interface_info

        definitions = self.reader.read_idl_file(idl_filename)

        this_union_types = collect_union_types_from_definitions(definitions)
        self.union_types.update(this_union_types)
        self.typedefs.update(definitions.typedefs)
        for callback_function_name, callback_function in \
                definitions.callback_functions.iteritems():
            # Set 'component_dir' to specify a directory that callback function files belong to
            self.callback_functions[callback_function_name] = {
                'callback_function': callback_function,
                'component_dir': idl_filename_to_component(idl_filename),
                'full_path': os.path.realpath(idl_filename),
            }
        # Check enum duplication.
        for enum in definitions.enumerations.values():
            if not self.check_enum_consistency(enum):
                raise Exception('Enumeration "%s" is defined more than once '
                                'with different valid values' % enum.name)
        self.enumerations.update(definitions.enumerations)

        if definitions.interfaces:
            definition = next(definitions.interfaces.itervalues())
            interface_info = {
                'is_callback_interface':
                definition.is_callback,
                'is_dictionary':
                False,
                # Interfaces that are referenced (used as types) and that we
                # introspect during code generation (beyond interface-level
                # data ([ImplementedAs], is_callback_interface, ancestors, and
                # inherited extended attributes): deep dependencies.
                # These cause rebuilds of referrers, due to the dependency,
                # so these should be minimized; currently only targets of
                # [PutForwards].
                'referenced_interfaces':
                get_put_forward_interfaces_from_definition(definition),
            }
        elif definitions.dictionaries:
            definition = next(definitions.dictionaries.itervalues())
            interface_info = {
                'is_callback_interface': False,
                'is_dictionary': True,
                'referenced_interfaces': None,
            }
        else:
            return

        if definition.name not in self.interfaces_info:
            self.interfaces_info[definition.name] = {}

        # Remember [Unforgeable] attributes.
        if definitions.interfaces:
            merge_dict_recursively(
                self.interfaces_info[definition.name],
                collect_unforgeable_attributes(definition, idl_filename))

        component = idl_filename_to_component(idl_filename)
        extended_attributes = definition.extended_attributes
        implemented_as = extended_attributes.get('ImplementedAs')
        full_path = os.path.realpath(idl_filename)
        if interface_info['is_dictionary']:
            this_include_path = include_path(idl_filename)
        else:
            this_include_path = include_path(idl_filename, implemented_as)
        if definition.is_partial:
            # We don't create interface_info for partial interfaces, but
            # adds paths to another dict.
            partial_include_paths = []
            if this_include_path:
                partial_include_paths.append(this_include_path)
            self.add_paths_to_partials_dict(definition.name, full_path,
                                            partial_include_paths)
            # Collects C++ header paths which should be included from generated
            # .cpp files.  The resulting structure is as follows.
            #   interfaces_info[interface_name] = {
            #       'cpp_includes': {
            #           'core': set(['core/foo/Foo.h', ...]),
            #           'modules': set(['modules/bar/Bar.h', ...]),
            #       },
            #       ...
            #   }
            if this_include_path:
                merge_dict_recursively(
                    self.interfaces_info[definition.name],
                    {'cpp_includes': {
                        component: set([this_include_path])
                    }})
            return

        # 'includes' statements can be included in either the file for the
        # interface (lhs of 'includes') or mixin (rhs of 'includes'). Store both
        # for now, then merge to the interface later.
        includes_interfaces, includes_mixins = get_includes_from_definitions(
            definitions, definition.name)

        interface_info.update({
            'extended_attributes':
            extended_attributes,
            'full_path':
            full_path,
            'union_types':
            this_union_types,
            'implemented_as':
            implemented_as,
            'included_by_interfaces':
            includes_interfaces,
            'including_mixins':
            includes_mixins,
            'include_path':
            this_include_path,
            # FIXME: temporary private field, while removing old
            # treatement of 'implements': http://crbug.com/360435
            'is_legacy_treat_as_partial_interface':
            'LegacyTreatAsPartialInterface' in extended_attributes,
            'parent':
            definition.parent,
            'relative_dir':
            relative_dir_posix(idl_filename, source_path),
        })
        merge_dict_recursively(self.interfaces_info[definition.name],
                               interface_info)

    def get_info_as_dict(self):
        """Returns info packaged as a dict."""
        return {
            'interfaces_info': self.interfaces_info,
            # Can't pickle defaultdict, convert to dict
            # FIXME: this should be included in get_component_info.
            'partial_interface_files': dict(self.partial_interface_files),
        }

    def get_component_info_as_dict(self, runtime_enabled_features):
        """Returns component wide information as a dict."""
        return {
            'callback_functions':
            self.callback_functions,
            'enumerations':
            dict((enum.name, enum.values)
                 for enum in self.enumerations.values()),
            'runtime_enabled_features':
            runtime_enabled_features,
            'typedefs':
            self.typedefs,
            'union_types':
            self.union_types,
        }
Пример #25
0
class ExternalReferenceTableGenerator(object):
    def __init__(self, opts, info_provider):
        self._opts = opts
        self._info_provider = info_provider
        self._reader = IdlReader(
            info_provider.interfaces_info, opts.cache_dir)
        self._interface_contexts = {}
        self._include_files = set(INCLUDES)
        v8_types.set_component_dirs(info_provider.interfaces_info['component_dirs'])

    # Creates a Jinja context from an IDL file.
    def process_idl_file(self, idl_filename):
        definitions = self._reader.read_idl_definitions(idl_filename)
        base_name, _ = os.path.splitext(os.path.basename(idl_filename))
        for component in definitions:
            target_definitions = definitions[component]
            interfaces = target_definitions.interfaces
            if base_name in interfaces.keys():
                interface = interfaces[base_name]
                self._process_interface(interface, component, interfaces)

    # Creates a Jinja context from an interface. Some interfaces are not used
    # in V8 context snapshot, so we can skip them.
    def _process_interface(self, interface, component, interfaces):
        def has_impl(interface):
            if interface.name in WHITE_LIST_INTERFACES:
                return True
            # Non legacy callback interface does not provide V8 callbacks.
            if interface.is_callback:
                return len(interface.constants) > 0
            if 'RuntimeEnabled' in interface.extended_attributes:
                return False
            return True

        if not has_impl(interface):
            return

        context_builder = InterfaceTemplateContextBuilder(self._opts, self._info_provider)
        context = context_builder.create_interface_context(interface, interfaces)
        name = '%s%s' % (interface.name, 'Partial' if interface.is_partial else '')
        self._interface_contexts[name] = context
        include_file = 'bindings/%s/v8/%s.h' % (component, context['v8_name'])
        self._include_files.add(include_file)

    # Gathers all interface-dependent information and returns as a Jinja template context.
    def _create_template_context(self):
        interfaces = []
        for name in sorted(self._interface_contexts):
            interfaces.append(self._interface_contexts[name])
        return {
            'class': 'V8ContextSnapshotExternalReferences',
            'interfaces': interfaces,
            'include_files': sorted(list(self._include_files)),
        }

    # Applies a Jinja template on a context and generates a C++ code.
    def generate(self):
        jinja_env = initialize_jinja_env(self._opts.cache_dir)
        context = self._create_template_context()
        cpp_template = jinja_env.get_template(TEMPLATE_FILE)
        cpp_text = cpp_template.render(context)
        return cpp_text
Пример #26
0
class InterfaceInfoCollector(object):
    """A class that collects interface information from idl files."""
    def __init__(self,
                 root_directory,
                 extend_attributes_filename,
                 cache_directory=None):
        self.reader = IdlReader(
            interfaces_info=None,
            outputdir=cache_directory,
            extend_attributes_filename=extend_attributes_filename)
        self.interfaces_info = {}
        self.partial_interface_files = defaultdict(lambda: {
            'full_paths': [],
            'include_paths': [],
        })
        self.enumerations = {}
        self.union_types = set()
        self.typedefs = {}
        self.callback_functions = {}
        self.root_path = root_directory
        self.referenced_from_partial_interfaces = defaultdict(lambda: set())

    def add_paths_to_partials_dict(self, partial_interface_name, full_path,
                                   include_paths):
        paths_dict = self.partial_interface_files[partial_interface_name]
        paths_dict['full_paths'].append(full_path)
        paths_dict['include_paths'].extend(include_paths)

    def collect_info(self, idl_filename, is_dependency=False):
        """Reads an idl file and collects information which is required by the
        binding code generation."""
        def collect_unforgeable_attributes(definition, idl_filename):
            """Collects [Unforgeable] attributes so that we can define them on
            sub-interfaces later.  The resulting structure is as follows.
                interfaces_info[interface_name] = {
                    'unforgeable_attributes': {
                        'core': [IdlAttribute, ...],
                        'modules': [IdlAttribute, ...],
                    },
                    ...
                }
            """
            interface_info = {}
            unforgeable_attributes = get_unforgeable_attributes_from_definition(
                definition)
            if not unforgeable_attributes:
                return interface_info

            if definition.is_partial:
                interface_basename = idl_filename_to_interface_name(
                    idl_filename)
                # TODO(yukishiino): [PartialInterfaceImplementedAs] is treated
                # in interface_dependency_resolver.transfer_extended_attributes.
                # Come up with a better way to keep them consistent.
                for attr in unforgeable_attributes:
                    attr.extended_attributes[
                        'PartialInterfaceImplementedAs'] = definition.extended_attributes.get(
                            'ImplementedAs', interface_basename)
            component = idl_filename_to_component(idl_filename)
            interface_info['unforgeable_attributes'] = {}
            interface_info['unforgeable_attributes'][
                component] = unforgeable_attributes
            return interface_info

        definitions = self.reader.read_idl_file(idl_filename)

        this_union_types = collect_union_types_from_definitions(definitions)
        self.union_types.update(this_union_types)
        self.typedefs.update(definitions.typedefs)
        for callback_function_name, callback_function in definitions.callback_functions.iteritems(
        ):
            # Set 'component_dir' to specify a directory that callback function files belong to
            self.callback_functions[callback_function_name] = {
                'callback_function': callback_function,
                'component_dir': idl_filename_to_component(idl_filename),
                'full_path': os.path.realpath(idl_filename),
            }

        # Include more information about the enum for Cobalt.
        for enum_name, values in definitions.enumerations.iteritems():
            # Check enum duplication.
            if self.enumerations.has_key(enum_name):
                raise Exception('Enumeration %s has multiple definitions' %
                                enum_name)
            self.enumerations[enum_name] = {
                'values': values,
                'full_path': os.path.realpath(idl_filename),
            }

        if definitions.interfaces:
            definition = next(definitions.interfaces.itervalues())
            interface_info = {
                'is_callback_interface':
                definition.is_callback,
                'is_dictionary':
                False,
                # Interfaces that are referenced (used as types) and that we
                # introspect during code generation (beyond interface-level
                # data ([ImplementedAs], is_callback_interface, ancestors, and
                # inherited extended attributes): deep dependencies.
                # These cause rebuilds of referrers, due to the dependency,
                # so these should be minimized; currently only targets of
                # [PutForwards].
                'referenced_interfaces':
                get_put_forward_interfaces_from_definition(definition),
                'is_dependency':
                is_dependency,
                'conditional':
                definition.extended_attributes.get('Conditional', None),
                'unsupported':
                'NotSupported' in definition.extended_attributes,
            }
        elif definitions.dictionaries:
            definition = next(definitions.dictionaries.itervalues())
            interface_info = {
                'is_callback_interface':
                False,
                'is_dictionary':
                True,
                'is_dependency':
                True,
                'conditional':
                definition.extended_attributes.get('Conditional', None),
                'unsupported':
                'NotSupported' in definition.extended_attributes,
                'referenced_interfaces':
                None,
            }
        else:
            return

        if definition.name not in self.interfaces_info:
            self.interfaces_info[definition.name] = {}

        # Remember [Unforgeable] attributes.
        if definitions.interfaces:
            merge_dict_recursively(
                self.interfaces_info[definition.name],
                collect_unforgeable_attributes(definition, idl_filename))

        component = idl_filename_to_component(idl_filename)
        extended_attributes = definition.extended_attributes
        implemented_as = extended_attributes.get('ImplementedAs')
        full_path = os.path.realpath(idl_filename)
        this_include_path = include_path(idl_filename, self.root_path,
                                         implemented_as)
        if definition.is_partial:
            # We don't create interface_info for partial interfaces, but
            # adds paths to another dict.
            partial_include_paths = []
            if this_include_path:
                partial_include_paths.append(this_include_path)
            for union_type in this_union_types:
                name = shorten_union_name(union_type)
                partial_include_paths.append('bindings/%s/v8/%s.h' %
                                             (component, name))
            self.add_paths_to_partials_dict(definition.name, full_path,
                                            partial_include_paths)
            referenced_from_interface = get_put_forward_interfaces_from_definition(
                definition)
            self.referenced_from_partial_interfaces[definition.name].update(
                referenced_from_interface)
            #   interfaces_info[interface_name] = {
            #       'cpp_includes': {
            #           'core': set(['core/foo/Foo.h', ...]),
            #           'modules': set(['modules/bar/Bar.h', ...]),
            #       },
            #       ...
            #   }
            if this_include_path:
                merge_dict_recursively(
                    self.interfaces_info[definition.name],
                    {'cpp_includes': {
                        component: set([this_include_path])
                    }})
            return

        # 'implements' statements can be included in either the file for the
        # implement*ing* interface (lhs of 'implements') or implement*ed* interface
        # (rhs of 'implements'). Store both for now, then merge to implement*ing*
        # interface later.
        left_interfaces, right_interfaces = get_implements_from_definitions(
            definitions, definition.name)

        interface_info.update({
            'extended_attributes':
            extended_attributes,
            'full_path':
            full_path,
            'union_types':
            this_union_types,
            'implemented_as':
            implemented_as,
            'implemented_by_interfaces':
            left_interfaces,
            'implements_interfaces':
            right_interfaces,
            'include_path':
            this_include_path,
            # FIXME: temporary private field, while removing old treatement of
            # 'implements': http://crbug.com/360435
            'is_legacy_treat_as_partial_interface':
            'LegacyTreatAsPartialInterface' in extended_attributes,
            'parent':
            definition.parent,
            'relative_dir':
            relative_dir_posix(idl_filename, self.root_path),
        })
        merge_dict_recursively(self.interfaces_info[definition.name],
                               interface_info)

    def get_info_as_dict(self):
        """Returns info packaged as a dict."""
        return {
            'interfaces_info':
            self.interfaces_info,
            # Can't pickle defaultdict, convert to dict
            # FIXME: this should be included in get_component_info.
            'partial_interface_files':
            dict(self.partial_interface_files),
            'partial_interface_referenced_interfaces':
            dict(self.referenced_from_partial_interfaces),
        }

    def get_component_info_as_dict(self):
        """Returns component wide information as a dict."""
        return {
            'callback_functions': self.callback_functions,
            'enumerations': self.enumerations,
            'typedefs': self.typedefs,
            'union_types': self.union_types,
        }
class InterfaceInfoCollector(object):
    """A class that collects interface information from idl files."""
    def __init__(self, cache_directory=None):
        self.reader = IdlReader(interfaces_info=None, outputdir=cache_directory)
        self.interfaces_info = {}
        self.partial_interface_files = defaultdict(lambda: {
            'full_paths': [],
            'include_paths': [],
        })
        self.enumerations = set()
        self.union_types = set()
        self.typedefs = {}

    def add_paths_to_partials_dict(self, partial_interface_name, full_path,
                                   include_paths):
        paths_dict = self.partial_interface_files[partial_interface_name]
        paths_dict['full_paths'].append(full_path)
        paths_dict['include_paths'].extend(include_paths)

    def collect_info(self, idl_filename):
        """Reads an idl file and collects information which is required by the
        binding code generation."""
        def collect_unforgeable_attributes(definition, idl_filename):
            """Collects [Unforgeable] attributes so that we can define them on
            sub-interfaces later.  The resulting structure is as follows.
                interfaces_info[interface_name] = {
                    'unforgeable_attributes': {
                        'core': [IdlAttribute, ...],
                        'modules': [IdlAttribute, ...],
                    },
                    ...
                }
            """
            interface_info = {}
            unforgeable_attributes = get_unforgeable_attributes_from_definition(definition)
            if not unforgeable_attributes:
                return interface_info

            if definition.is_partial:
                interface_basename = idl_filename_to_interface_name(idl_filename)
                # TODO(yukishiino): [PartialInterfaceImplementedAs] is treated
                # in interface_dependency_resolver.transfer_extended_attributes.
                # Come up with a better way to keep them consistent.
                for attr in unforgeable_attributes:
                    attr.extended_attributes['PartialInterfaceImplementedAs'] = definition.extended_attributes.get('ImplementedAs', interface_basename)
            component = idl_filename_to_component(idl_filename)
            interface_info['unforgeable_attributes'] = {}
            interface_info['unforgeable_attributes'][component] = unforgeable_attributes
            return interface_info

        definitions = self.reader.read_idl_file(idl_filename)

        this_union_types = collect_union_types_from_definitions(definitions)
        self.union_types.update(this_union_types)
        self.typedefs.update(definitions.typedefs)
        # Check enum duplication.
        for enum_name in definitions.enumerations.keys():
            for defined_enum in self.enumerations:
                if defined_enum.name == enum_name:
                    raise Exception('Enumeration %s has multiple definitions' % enum_name)
        self.enumerations.update(definitions.enumerations.values())

        if definitions.interfaces:
            definition = next(definitions.interfaces.itervalues())
            interface_info = {
                'is_callback_interface': definition.is_callback,
                'is_dictionary': False,
                # Interfaces that are referenced (used as types) and that we
                # introspect during code generation (beyond interface-level
                # data ([ImplementedAs], is_callback_interface, ancestors, and
                # inherited extended attributes): deep dependencies.
                # These cause rebuilds of referrers, due to the dependency,
                # so these should be minimized; currently only targets of
                # [PutForwards].
                'referenced_interfaces': get_put_forward_interfaces_from_definition(definition),
            }
        elif definitions.dictionaries:
            definition = next(definitions.dictionaries.itervalues())
            interface_info = {
                'is_callback_interface': False,
                'is_dictionary': True,
                'referenced_interfaces': None,
            }
        else:
            return

        if definition.name not in self.interfaces_info:
            self.interfaces_info[definition.name] = {}

        # Remember [Unforgeable] attributes.
        if definitions.interfaces:
            merge_dict_recursively(self.interfaces_info[definition.name],
                                   collect_unforgeable_attributes(definition, idl_filename))

        component = idl_filename_to_component(idl_filename)
        extended_attributes = definition.extended_attributes
        implemented_as = extended_attributes.get('ImplementedAs')
        full_path = os.path.realpath(idl_filename)
        this_include_path = None if 'NoImplHeader' in extended_attributes else include_path(idl_filename, implemented_as)
        if definition.is_partial:
            # We don't create interface_info for partial interfaces, but
            # adds paths to another dict.
            partial_include_paths = []
            if this_include_path:
                partial_include_paths.append(this_include_path)
            if this_union_types:
                partial_include_paths.append(
                    'bindings/%s/v8/UnionTypes%s.h' % (component, component.capitalize()))
            self.add_paths_to_partials_dict(definition.name, full_path, partial_include_paths)
            # Collects C++ header paths which should be included from generated
            # .cpp files.  The resulting structure is as follows.
            #   interfaces_info[interface_name] = {
            #       'cpp_includes': {
            #           'core': set(['core/foo/Foo.h', ...]),
            #           'modules': set(['modules/bar/Bar.h', ...]),
            #       },
            #       ...
            #   }
            if this_include_path:
                merge_dict_recursively(
                    self.interfaces_info[definition.name],
                    {'cpp_includes': {component: set([this_include_path])}})
            return

        # 'implements' statements can be included in either the file for the
        # implement*ing* interface (lhs of 'implements') or implement*ed* interface
        # (rhs of 'implements'). Store both for now, then merge to implement*ing*
        # interface later.
        left_interfaces, right_interfaces = get_implements_from_definitions(
            definitions, definition.name)

        interface_info.update({
            'extended_attributes': extended_attributes,
            'full_path': full_path,
            'has_union_types': bool(this_union_types),
            'implemented_as': implemented_as,
            'implemented_by_interfaces': left_interfaces,
            'implements_interfaces': right_interfaces,
            'include_path': this_include_path,
            # FIXME: temporary private field, while removing old treatement of
            # 'implements': http://crbug.com/360435
            'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterface' in extended_attributes,
            'parent': definition.parent,
            'relative_dir': relative_dir_posix(idl_filename, source_path),
        })
        merge_dict_recursively(self.interfaces_info[definition.name], interface_info)

    def get_info_as_dict(self):
        """Returns info packaged as a dict."""
        return {
            'interfaces_info': self.interfaces_info,
            # Can't pickle defaultdict, convert to dict
            # FIXME: this should be included in get_component_info.
            'partial_interface_files': dict(self.partial_interface_files),
        }

    def get_component_info_as_dict(self):
        """Returns component wide information as a dict."""
        return {
            'enumerations': dict((enum.name, enum.values)
                                 for enum in self.enumerations),
            'typedefs': self.typedefs,
            'union_types': self.union_types,
        }
Пример #28
0
class ExternalReferenceTableGenerator(object):
    def __init__(self, opts, info_provider):
        self._opts = opts
        self._info_provider = info_provider
        self._reader = IdlReader(info_provider.interfaces_info, opts.cache_dir)
        self._interface_contexts = {}
        self._include_files = set(INCLUDES)
        v8_types.set_component_dirs(
            info_provider.interfaces_info['component_dirs'])

    # Creates a Jinja context from an IDL file.
    def process_idl_file(self, idl_filename):
        definitions = self._reader.read_idl_definitions(idl_filename)
        for component in definitions:
            target_definitions = definitions[component]
            interfaces = target_definitions.interfaces
            first_name = target_definitions.first_name
            if first_name in interfaces.keys():
                interface = interfaces[first_name]
                self._process_interface(interface, component, interfaces)

    # Creates a Jinja context from an interface. Some interfaces are not used
    # in V8 context snapshot, so we can skip them.
    def _process_interface(self, interface, component, interfaces):
        def has_impl(interface):
            if interface.name in WHITE_LIST_INTERFACES:
                return True
            # Non legacy callback interface does not provide V8 callbacks.
            if interface.is_callback:
                return len(interface.constants) > 0
            if 'RuntimeEnabled' in interface.extended_attributes:
                return False
            return True

        if not has_impl(interface):
            return

        context_builder = InterfaceTemplateContextBuilder(
            self._opts, self._info_provider)
        context = context_builder.create_interface_context(
            interface, interfaces)
        name = '%s%s' % (interface.name,
                         'Partial' if interface.is_partial else '')
        self._interface_contexts[name] = context
        if self._opts.snake_case_generated_files:
            include_file = 'bindings/%s/v8/%s.h' % (
                component, utilities.to_snake_case(context['v8_name']))
        else:
            include_file = 'bindings/%s/v8/%s.h' % (component,
                                                    context['v8_name'])
        self._include_files.add(include_file)

    # Gathers all interface-dependent information and returns as a Jinja template context.
    def _create_template_context(self):
        interfaces = []
        for name in sorted(self._interface_contexts):
            interfaces.append(self._interface_contexts[name])
        header_name = 'V8ContextSnapshotExternalReferences.h'
        if self._opts.snake_case_generated_files:
            header_name = 'v8_context_snapshot_external_references.h'
        include_files = list(self._include_files)
        # TODO(tkent): Update INCLUDES after the great mv, and remove the
        # following block. crbug.com/760462
        if self._opts.snake_case_generated_files:
            include_files = []
            for include in self._include_files:
                dirname, basename = posixpath.split(include)
                name, ext = posixpath.splitext(basename)
                include_files.append(
                    posixpath.join(dirname,
                                   utilities.to_snake_case(name) + ext))
        return {
            'class': 'V8ContextSnapshotExternalReferences',
            'interfaces': interfaces,
            'include_files': sorted(include_files),
            'this_include_header_name': header_name,
            'code_generator': os.path.basename(__file__),
            'jinja_template_filename': TEMPLATE_FILE
        }

    # Applies a Jinja template on a context and generates a C++ code.
    def generate(self):
        jinja_env = initialize_jinja_env(self._opts.cache_dir)
        context = self._create_template_context()
        cpp_template = jinja_env.get_template(TEMPLATE_FILE)
        cpp_text = cpp_template.render(context)
        return cpp_text
class ExternalReferenceTableGenerator(object):
    def __init__(self, opts, info_provider):
        self._opts = opts
        self._info_provider = info_provider
        self._reader = IdlReader(info_provider.interfaces_info, opts.cache_dir)
        self._interface_contexts = {}
        self._include_files = set(INCLUDES)
        v8_types.set_component_dirs(
            info_provider.interfaces_info['component_dirs'])

    # Creates a Jinja context from an IDL file.
    def process_idl_file(self, idl_filename):
        definitions = self._reader.read_idl_definitions(idl_filename)
        for component in definitions:
            target_definitions = definitions[component]
            interfaces = target_definitions.interfaces
            first_name = target_definitions.first_name
            if first_name in interfaces.keys():
                interface = interfaces[first_name]
                self._process_interface(interface, component, interfaces)

    # Creates a Jinja context from an interface. Some interfaces are not used
    # in V8 context snapshot, so we can skip them.
    def _process_interface(self, interface, component, interfaces):
        def has_impl(interface):
            # Non legacy callback interface does not provide V8 callbacks.
            if interface.is_callback:
                return len(interface.constants) > 0
            if 'RuntimeEnabled' in interface.extended_attributes:
                return False
            if 'Exposed' not in interface.extended_attributes:
                return True
            return any(
                exposure.exposed == 'Window'
                and exposure.runtime_enabled is None
                for exposure in interface.extended_attributes['Exposed'])

        if not has_impl(interface):
            return

        context_builder = InterfaceTemplateContextBuilder(
            self._opts, self._info_provider)
        context = context_builder.create_interface_context(
            interface, component, interfaces)
        name = '%s%s' % (interface.name,
                         'Partial' if interface.is_partial else '')
        self._interface_contexts[name] = context

        # Do not include unnecessary header files.
        if not context['attributes'] and not context['named_property_setter']:
            return

        include_file = 'third_party/blink/renderer/bindings/%s/v8/%s.h' % (
            component, utilities.to_snake_case(context['v8_class']))
        self._include_files.add(include_file)

    # Gathers all interface-dependent information and returns as a Jinja template context.
    def _create_template_context(self):
        interfaces = []
        for name in sorted(self._interface_contexts):
            interfaces.append(self._interface_contexts[name])
        header_path = 'third_party/blink/renderer/bindings/modules/v8/v8_context_snapshot_external_references.h'
        include_files = list(self._include_files)
        return {
            'class': 'V8ContextSnapshotExternalReferences',
            'interfaces': interfaces,
            'include_files': sorted(include_files),
            'this_include_header_path': header_path,
            'code_generator': os.path.basename(__file__),
            'jinja_template_filename': TEMPLATE_FILE
        }

    # Applies a Jinja template on a context and generates a C++ code.
    def generate(self):
        jinja_env = initialize_jinja_env(self._opts.cache_dir)
        context = self._create_template_context()
        cpp_template = jinja_env.get_template(TEMPLATE_FILE)
        cpp_text = cpp_template.render(context)
        return cpp_text
class InterfaceInfoCollector(object):
    """A class that collects interface information from idl files."""
    def __init__(self, cache_directory=None):
        self.reader = IdlReader(interfaces_info=None, outputdir=cache_directory)
        self.interfaces_info = {}
        self.partial_interface_files = defaultdict(lambda: {
            'full_paths': [],
            'include_paths': [],
        })
        self.enumerations = set()
        self.union_types = set()
        self.typedefs = {}

    def add_paths_to_partials_dict(self, partial_interface_name, full_path,
                                   include_paths):
        paths_dict = self.partial_interface_files[partial_interface_name]
        paths_dict['full_paths'].append(full_path)
        paths_dict['include_paths'].extend(include_paths)

    def collect_info(self, idl_filename):
        """Reads an idl file and collects information which is required by the
        binding code generation."""
        definitions = self.reader.read_idl_file(idl_filename)

        this_union_types = collect_union_types_from_definitions(definitions)
        self.union_types.update(this_union_types)
        self.typedefs.update(definitions.typedefs)
        # Check enum duplication.
        for enum_name in definitions.enumerations.keys():
            for defined_enum in self.enumerations:
                if defined_enum.name == enum_name:
                    raise Exception('Enumeration %s has multiple definitions' % enum_name)
        self.enumerations.update(definitions.enumerations.values())

        if definitions.interfaces:
            definition = next(definitions.interfaces.itervalues())
            interface_info = {
                'is_callback_interface': definition.is_callback,
                'is_dictionary': False,
                # Interfaces that are referenced (used as types) and that we
                # introspect during code generation (beyond interface-level
                # data ([ImplementedAs], is_callback_interface, ancestors, and
                # inherited extended attributes): deep dependencies.
                # These cause rebuilds of referrers, due to the dependency,
                # so these should be minimized; currently only targets of
                # [PutForwards].
                'referenced_interfaces': get_put_forward_interfaces_from_definition(definition),
            }
        elif definitions.dictionaries:
            definition = next(definitions.dictionaries.itervalues())
            interface_info = {
                'is_callback_interface': False,
                'is_dictionary': True,
                'referenced_interfaces': None,
            }
        else:
            return

        extended_attributes = definition.extended_attributes
        implemented_as = extended_attributes.get('ImplementedAs')
        full_path = os.path.realpath(idl_filename)
        this_include_path = None if 'NoImplHeader' in extended_attributes else include_path(idl_filename, implemented_as)
        if definition.is_partial:
            # We don't create interface_info for partial interfaces, but
            # adds paths to another dict.
            partial_include_paths = []
            if this_include_path:
                partial_include_paths.append(this_include_path)
            if this_union_types:
                component = idl_filename_to_component(idl_filename)
                partial_include_paths.append(
                    'bindings/%s/v8/UnionTypes%s.h' % (component, component.capitalize()))
            self.add_paths_to_partials_dict(definition.name, full_path, partial_include_paths)
            return

        # 'implements' statements can be included in either the file for the
        # implement*ing* interface (lhs of 'implements') or implement*ed* interface
        # (rhs of 'implements'). Store both for now, then merge to implement*ing*
        # interface later.
        left_interfaces, right_interfaces = get_implements_from_definitions(
            definitions, definition.name)

        interface_info.update({
            'extended_attributes': extended_attributes,
            'full_path': full_path,
            'has_union_types': bool(this_union_types),
            'implemented_as': implemented_as,
            'implemented_by_interfaces': left_interfaces,
            'implements_interfaces': right_interfaces,
            'include_path': this_include_path,
            # FIXME: temporary private field, while removing old treatement of
            # 'implements': http://crbug.com/360435
            'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterface' in extended_attributes,
            'parent': definition.parent,
            'relative_dir': relative_dir_posix(idl_filename),
        })
        self.interfaces_info[definition.name] = interface_info

    def get_info_as_dict(self):
        """Returns info packaged as a dict."""
        return {
            'interfaces_info': self.interfaces_info,
            # Can't pickle defaultdict, convert to dict
            # FIXME: this should be included in get_component_info.
            'partial_interface_files': dict(self.partial_interface_files),
        }

    def get_component_info_as_dict(self):
        """Returns component wide information as a dict."""
        return {
            'enumerations': dict((enum.name, enum.values)
                                 for enum in self.enumerations),
            'typedefs': self.typedefs,
            'union_types': self.union_types,
        }
class InterfaceInfoCollector(object):
    """A class that collects interface information from idl files."""
    def __init__(self, cache_directory=None):
        self.reader = IdlReader(interfaces_info=None,
                                outputdir=cache_directory)
        self.interfaces_info = {}
        self.partial_interface_files = defaultdict(lambda: {
            'full_paths': [],
            'include_paths': [],
        })
        self.enumerations = set()
        self.union_types = set()
        self.typedefs = {}

    def add_paths_to_partials_dict(self, partial_interface_name, full_path,
                                   include_paths):
        paths_dict = self.partial_interface_files[partial_interface_name]
        paths_dict['full_paths'].append(full_path)
        paths_dict['include_paths'].extend(include_paths)

    def collect_info(self, idl_filename):
        """Reads an idl file and collects information which is required by the
        binding code generation."""
        definitions = self.reader.read_idl_file(idl_filename)

        this_union_types = collect_union_types_from_definitions(definitions)
        self.union_types.update(this_union_types)
        self.typedefs.update(definitions.typedefs)
        # Check enum duplication.
        for enum_name in definitions.enumerations.keys():
            for defined_enum in self.enumerations:
                if defined_enum.name == enum_name:
                    raise Exception('Enumeration %s has multiple definitions' %
                                    enum_name)
        self.enumerations.update(definitions.enumerations.values())

        if definitions.interfaces:
            definition = next(definitions.interfaces.itervalues())
            interface_info = {
                'is_callback_interface':
                definition.is_callback,
                'is_dictionary':
                False,
                # Interfaces that are referenced (used as types) and that we
                # introspect during code generation (beyond interface-level
                # data ([ImplementedAs], is_callback_interface, ancestors, and
                # inherited extended attributes): deep dependencies.
                # These cause rebuilds of referrers, due to the dependency,
                # so these should be minimized; currently only targets of
                # [PutForwards].
                'referenced_interfaces':
                get_put_forward_interfaces_from_definition(definition),
            }
        elif definitions.dictionaries:
            definition = next(definitions.dictionaries.itervalues())
            interface_info = {
                'is_callback_interface': False,
                'is_dictionary': True,
                'referenced_interfaces': None,
            }
        else:
            return

        extended_attributes = definition.extended_attributes
        implemented_as = extended_attributes.get('ImplementedAs')
        full_path = os.path.realpath(idl_filename)
        this_include_path = None if 'NoImplHeader' in extended_attributes else include_path(
            idl_filename, implemented_as)
        if definition.is_partial:
            # We don't create interface_info for partial interfaces, but
            # adds paths to another dict.
            partial_include_paths = []
            if this_include_path:
                partial_include_paths.append(this_include_path)
            if this_union_types:
                component = idl_filename_to_component(idl_filename)
                partial_include_paths.append(
                    'bindings/%s/v8/UnionTypes%s.h' %
                    (component, component.capitalize()))
            self.add_paths_to_partials_dict(definition.name, full_path,
                                            partial_include_paths)
            return

        # 'implements' statements can be included in either the file for the
        # implement*ing* interface (lhs of 'implements') or implement*ed* interface
        # (rhs of 'implements'). Store both for now, then merge to implement*ing*
        # interface later.
        left_interfaces, right_interfaces = get_implements_from_definitions(
            definitions, definition.name)

        interface_info.update({
            'extended_attributes':
            extended_attributes,
            'full_path':
            full_path,
            'has_union_types':
            bool(this_union_types),
            'implemented_as':
            implemented_as,
            'implemented_by_interfaces':
            left_interfaces,
            'implements_interfaces':
            right_interfaces,
            'include_path':
            this_include_path,
            # FIXME: temporary private field, while removing old treatement of
            # 'implements': http://crbug.com/360435
            'is_legacy_treat_as_partial_interface':
            'LegacyTreatAsPartialInterface' in extended_attributes,
            'parent':
            definition.parent,
            'relative_dir':
            relative_dir_posix(idl_filename),
        })
        self.interfaces_info[definition.name] = interface_info

    def get_info_as_dict(self):
        """Returns info packaged as a dict."""
        return {
            'interfaces_info': self.interfaces_info,
            # Can't pickle defaultdict, convert to dict
            # FIXME: this should be included in get_component_info.
            'partial_interface_files': dict(self.partial_interface_files),
        }

    def get_component_info_as_dict(self):
        """Returns component wide information as a dict."""
        return {
            'enumerations':
            dict((enum.name, enum.values) for enum in self.enumerations),
            'typedefs':
            self.typedefs,
            'union_types':
            self.union_types,
        }