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

Side by Side Diff: bindings/scripts/compute_interfaces_info_individual.py

Issue 1660113002: Updated to Chrome 45 (2454) moved from SVN to git. Base URL: https://github.com/dart-lang/webcore.git@roll_45
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # 2 #
3 # Copyright (C) 2013 Google Inc. All rights reserved. 3 # Copyright (C) 2013 Google Inc. All rights reserved.
4 # 4 #
5 # Redistribution and use in source and binary forms, with or without 5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are 6 # modification, are permitted provided that the following conditions are
7 # met: 7 # met:
8 # 8 #
9 # * Redistributions of source code must retain the above copyright 9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer. 10 # notice, this list of conditions and the following disclaimer.
(...skipping 29 matching lines...) Expand all
40 40
41 Design doc: http://www.chromium.org/developers/design-documents/idl-build 41 Design doc: http://www.chromium.org/developers/design-documents/idl-build
42 """ 42 """
43 43
44 from collections import defaultdict 44 from collections import defaultdict
45 import optparse 45 import optparse
46 import os 46 import os
47 import posixpath 47 import posixpath
48 import sys 48 import sys
49 49
50 from utilities import get_file_contents, read_file_to_list, idl_filename_to_inte rface_name, idl_filename_to_component, write_pickle_file, get_interface_extended _attributes_from_idl, is_callback_interface_from_idl, is_dictionary_from_idl, ge t_partial_interface_name_from_idl, get_implements_from_idl, get_parent_interface , get_put_forward_interfaces_from_idl 50 from idl_definitions import Visitor
51 from idl_reader import IdlReader
52 from utilities import get_file_contents, read_file_to_list, idl_filename_to_inte rface_name, idl_filename_to_component, write_pickle_file, get_interface_extended _attributes_from_idl, is_callback_interface_from_idl
51 53
52 module_path = os.path.dirname(__file__) 54 module_path = os.path.dirname(__file__)
53 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir)) 55 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir))
54 56
55 # Global variables (filled in and exported) 57
56 interfaces_info = {} 58 class IdlBadFilenameError(Exception):
57 partial_interface_files = defaultdict(lambda: { 59 """Raised if an IDL filename disagrees with the interface name in the file." ""
58 'full_paths': [], 60 pass
59 'include_paths': [],
60 })
61 61
62 62
63 def parse_options(): 63 def parse_options():
64 usage = 'Usage: %prog [options] [generated1.idl]...' 64 usage = 'Usage: %prog [options] [generated1.idl]...'
65 parser = optparse.OptionParser(usage=usage) 65 parser = optparse.OptionParser(usage=usage)
66 parser.add_option('--cache-directory', help='cache directory')
66 parser.add_option('--idl-files-list', help='file listing IDL files') 67 parser.add_option('--idl-files-list', help='file listing IDL files')
67 parser.add_option('--interfaces-info-file', help='output pickle file') 68 parser.add_option('--interfaces-info-file', help='interface info pickle file ')
69 parser.add_option('--component-info-file', help='component wide info pickle file')
68 parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja') 70 parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja')
69 71
70 options, args = parser.parse_args() 72 options, args = parser.parse_args()
71 if options.interfaces_info_file is None: 73 if options.interfaces_info_file is None:
72 parser.error('Must specify an output file using --interfaces-info-file.' ) 74 parser.error('Must specify an output file using --interfaces-info-file.' )
73 if options.idl_files_list is None: 75 if options.idl_files_list is None:
74 parser.error('Must specify a file listing IDL files using --idl-files-li st.') 76 parser.error('Must specify a file listing IDL files using --idl-files-li st.')
75 if options.write_file_only_if_changed is None: 77 if options.write_file_only_if_changed is None:
76 parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.') 78 parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.')
77 options.write_file_only_if_changed = bool(options.write_file_only_if_changed ) 79 options.write_file_only_if_changed = bool(options.write_file_only_if_changed )
(...skipping 19 matching lines...) Expand all
97 """ 99 """
98 relative_dir = relative_dir_posix(idl_filename) 100 relative_dir = relative_dir_posix(idl_filename)
99 101
100 # IDL file basename is used even if only a partial interface file 102 # IDL file basename is used even if only a partial interface file
101 idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename)) 103 idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename))
102 cpp_class_name = implemented_as or idl_file_basename 104 cpp_class_name = implemented_as or idl_file_basename
103 105
104 return posixpath.join(relative_dir, cpp_class_name + '.h') 106 return posixpath.join(relative_dir, cpp_class_name + '.h')
105 107
106 108
107 def add_paths_to_partials_dict(partial_interface_name, full_path, this_include_p ath=None): 109 def get_implements_from_definitions(definitions, definition_name):
108 paths_dict = partial_interface_files[partial_interface_name] 110 left_interfaces = []
109 paths_dict['full_paths'].append(full_path) 111 right_interfaces = []
110 if this_include_path: 112 for implement in definitions.implements:
111 paths_dict['include_paths'].append(this_include_path) 113 if definition_name == implement.left_interface:
114 right_interfaces.append(implement.right_interface)
115 elif definition_name == implement.right_interface:
116 left_interfaces.append(implement.left_interface)
117 else:
118 raise IdlBadFilenameError(
119 'implements statement found in unrelated IDL file.\n'
120 'Statement is:\n'
121 ' %s implements %s;\n'
122 'but filename is unrelated "%s.idl"' %
123 (implement.left_interface, implement.right_interface, definition _name))
124 return left_interfaces, right_interfaces
112 125
113 126
114 def compute_info_individual(idl_filename): 127 def get_put_forward_interfaces_from_definition(definition):
115 full_path = os.path.realpath(idl_filename) 128 return sorted(set(attribute.idl_type.base_type
116 idl_file_contents = get_file_contents(full_path) 129 for attribute in definition.attributes
117 130 if 'PutForwards' in attribute.extended_attributes))
118 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co ntents)
119 implemented_as = extended_attributes.get('ImplementedAs')
120 relative_dir = relative_dir_posix(idl_filename)
121 this_include_path = None if 'NoImplHeader' in extended_attributes else inclu de_path(idl_filename, implemented_as)
122
123 # Handle partial interfaces
124 partial_interface_name = get_partial_interface_name_from_idl(idl_file_conten ts)
125 if partial_interface_name:
126 add_paths_to_partials_dict(partial_interface_name, full_path, this_inclu de_path)
127 return
128
129 # If not a partial interface, the basename is the interface name
130 interface_name = idl_filename_to_interface_name(idl_filename)
131
132 # 'implements' statements can be included in either the file for the
133 # implement*ing* interface (lhs of 'implements') or implement*ed* interface
134 # (rhs of 'implements'). Store both for now, then merge to implement*ing*
135 # interface later.
136 left_interfaces, right_interfaces = get_implements_from_idl(idl_file_content s, interface_name)
137
138 interfaces_info[interface_name] = {
139 'extended_attributes': extended_attributes,
140 'full_path': full_path,
141 'implemented_as': implemented_as,
142 'implemented_by_interfaces': left_interfaces, # private, merged to next
143 'implements_interfaces': right_interfaces,
144 'include_path': this_include_path,
145 'is_callback_interface': is_callback_interface_from_idl(idl_file_content s),
146 'is_dictionary': is_dictionary_from_idl(idl_file_contents),
147 # FIXME: temporary private field, while removing old treatement of
148 # 'implements': http://crbug.com/360435
149 'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterface' in extended_attributes,
150 'parent': get_parent_interface(idl_file_contents),
151 # Interfaces that are referenced (used as types) and that we introspect
152 # during code generation (beyond interface-level data ([ImplementedAs],
153 # is_callback_interface, ancestors, and inherited extended attributes):
154 # deep dependencies.
155 # These cause rebuilds of referrers, due to the dependency, so these
156 # should be minimized; currently only targets of [PutForwards].
157 'referenced_interfaces': get_put_forward_interfaces_from_idl(idl_file_co ntents),
158 'relative_dir': relative_dir,
159 }
160 131
161 132
162 def info_individual(): 133 def collect_union_types_from_definitions(definitions):
163 """Returns info packaged as a dict.""" 134 """Traverse definitions and collect all union types."""
164 return { 135 class UnionTypeCollector(Visitor):
165 'interfaces_info': interfaces_info, 136 def collect(self, definitions):
166 # Can't pickle defaultdict, convert to dict 137 self._union_types = set()
167 'partial_interface_files': dict(partial_interface_files), 138 definitions.accept(self)
168 } 139 return self._union_types
140
141 def visit_typed_object(self, typed_object):
142 for attribute_name in typed_object.idl_type_attributes:
143 attribute = getattr(typed_object, attribute_name, None)
144 if not attribute:
145 continue
146 for idl_type in attribute.idl_types():
147 if idl_type.is_union_type:
148 self._union_types.add(idl_type)
149
150 return UnionTypeCollector().collect(definitions)
151
152
153 class InterfaceInfoCollector(object):
154 """A class that collects interface information from idl files."""
155 def __init__(self, cache_directory=None):
156 self.reader = IdlReader(interfaces_info=None, outputdir=cache_directory)
157 self.interfaces_info = {}
158 self.partial_interface_files = defaultdict(lambda: {
159 'full_paths': [],
160 'include_paths': [],
161 })
162 self.enumerations = set()
163 self.union_types = set()
164 self.typedefs = {}
165
166 def add_paths_to_partials_dict(self, partial_interface_name, full_path,
167 include_paths):
168 paths_dict = self.partial_interface_files[partial_interface_name]
169 paths_dict['full_paths'].append(full_path)
170 paths_dict['include_paths'].extend(include_paths)
171
172 def collect_info(self, idl_filename):
173 """Reads an idl file and collects information which is required by the
174 binding code generation."""
175 definitions = self.reader.read_idl_file(idl_filename)
176
177 this_union_types = collect_union_types_from_definitions(definitions)
178 self.union_types.update(this_union_types)
179 self.typedefs.update(definitions.typedefs)
180 # Check enum duplication.
181 for enum_name in definitions.enumerations.keys():
182 for defined_enum in self.enumerations:
183 if defined_enum.name == enum_name:
184 raise Exception('Enumeration %s has multiple definitions' % enum_name)
185 self.enumerations.update(definitions.enumerations.values())
186
187 if definitions.interfaces:
188 definition = next(definitions.interfaces.itervalues())
189 interface_info = {
190 'is_callback_interface': definition.is_callback,
191 'is_dictionary': False,
192 # Interfaces that are referenced (used as types) and that we
193 # introspect during code generation (beyond interface-level
194 # data ([ImplementedAs], is_callback_interface, ancestors, and
195 # inherited extended attributes): deep dependencies.
196 # These cause rebuilds of referrers, due to the dependency,
197 # so these should be minimized; currently only targets of
198 # [PutForwards].
199 'referenced_interfaces': get_put_forward_interfaces_from_definit ion(definition),
200 }
201 elif definitions.dictionaries:
202 definition = next(definitions.dictionaries.itervalues())
203 interface_info = {
204 'is_callback_interface': False,
205 'is_dictionary': True,
206 'referenced_interfaces': None,
207 }
208 else:
209 return
210
211 extended_attributes = definition.extended_attributes
212 implemented_as = extended_attributes.get('ImplementedAs')
213 full_path = os.path.realpath(idl_filename)
214 this_include_path = None if 'NoImplHeader' in extended_attributes else i nclude_path(idl_filename, implemented_as)
215 if definition.is_partial:
216 # We don't create interface_info for partial interfaces, but
217 # adds paths to another dict.
218 partial_include_paths = []
219 if this_include_path:
220 partial_include_paths.append(this_include_path)
221 if this_union_types:
222 component = idl_filename_to_component(idl_filename)
223 partial_include_paths.append(
224 'bindings/%s/v8/UnionTypes%s.h' % (component, component.capi talize()))
225 self.add_paths_to_partials_dict(definition.name, full_path, partial_ include_paths)
226 return
227
228 # 'implements' statements can be included in either the file for the
229 # implement*ing* interface (lhs of 'implements') or implement*ed* interf ace
230 # (rhs of 'implements'). Store both for now, then merge to implement*ing *
231 # interface later.
232 left_interfaces, right_interfaces = get_implements_from_definitions(
233 definitions, definition.name)
234
235 interface_info.update({
236 'extended_attributes': extended_attributes,
237 'full_path': full_path,
238 'has_union_types': bool(this_union_types),
239 'implemented_as': implemented_as,
240 'implemented_by_interfaces': left_interfaces,
241 'implements_interfaces': right_interfaces,
242 'include_path': this_include_path,
243 # FIXME: temporary private field, while removing old treatement of
244 # 'implements': http://crbug.com/360435
245 'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterfa ce' in extended_attributes,
246 'parent': definition.parent,
247 'relative_dir': relative_dir_posix(idl_filename),
248 })
249 self.interfaces_info[definition.name] = interface_info
250
251 def get_info_as_dict(self):
252 """Returns info packaged as a dict."""
253 return {
254 'interfaces_info': self.interfaces_info,
255 # Can't pickle defaultdict, convert to dict
256 # FIXME: this should be included in get_component_info.
257 'partial_interface_files': dict(self.partial_interface_files),
258 }
259
260 def get_component_info_as_dict(self):
261 """Returns component wide information as a dict."""
262 return {
263 'enumerations': dict((enum.name, enum.values)
264 for enum in self.enumerations),
265 'typedefs': self.typedefs,
266 'union_types': self.union_types,
267 }
169 268
170 269
171 ################################################################################ 270 ################################################################################
172 271
173 def main(): 272 def main():
174 options, args = parse_options() 273 options, args = parse_options()
175 274
176 # Static IDL files are passed in a file (generated at GYP time), due to OS 275 # Static IDL files are passed in a file (generated at GYP time), due to OS
177 # command line length limits 276 # command line length limits
178 idl_files = read_file_to_list(options.idl_files_list) 277 idl_files = read_file_to_list(options.idl_files_list)
179 # Generated IDL files are passed at the command line, since these are in the 278 # Generated IDL files are passed at the command line, since these are in the
180 # build directory, which is determined at build time, not GYP time, so these 279 # build directory, which is determined at build time, not GYP time, so these
181 # cannot be included in the file listing static files 280 # cannot be included in the file listing static files
182 idl_files.extend(args) 281 idl_files.extend(args)
183 282
184 # Compute information for individual files 283 # Compute information for individual files
185 # Information is stored in global variables interfaces_info and 284 # Information is stored in global variables interfaces_info and
186 # partial_interface_files. 285 # partial_interface_files.
286 info_collector = InterfaceInfoCollector(options.cache_directory)
187 for idl_filename in idl_files: 287 for idl_filename in idl_files:
188 compute_info_individual(idl_filename) 288 info_collector.collect_info(idl_filename)
189 289
190 write_pickle_file(options.interfaces_info_file, 290 write_pickle_file(options.interfaces_info_file,
191 info_individual(), 291 info_collector.get_info_as_dict(),
192 options.write_file_only_if_changed) 292 options.write_file_only_if_changed)
193 293 write_pickle_file(options.component_info_file,
294 info_collector.get_component_info_as_dict(),
295 options.write_file_only_if_changed)
194 296
195 if __name__ == '__main__': 297 if __name__ == '__main__':
196 sys.exit(main()) 298 sys.exit(main())
OLDNEW
« no previous file with comments | « bindings/scripts/code_generator_v8.py ('k') | bindings/scripts/compute_interfaces_info_overall.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698