コード例 #1
0
ファイル: dump_idl.py プロジェクト: botwithfeelings/visiblev8
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
コード例 #2
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,
        }
コード例 #3
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,
        }
コード例 #5
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 = 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,
        }
コード例 #6
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 = 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,
        }