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

Side by Side Diff: Source/bindings/scripts/compute_dependencies.py

Issue 24053003: Support partial interface for test support idls (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: patch Created 7 years, 2 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 30 matching lines...) Expand all
41 41
42 42
43 class IdlInterfaceFileNotFoundError(Exception): 43 class IdlInterfaceFileNotFoundError(Exception):
44 """Raised if the IDL file implementing an interface cannot be found.""" 44 """Raised if the IDL file implementing an interface cannot be found."""
45 pass 45 pass
46 46
47 47
48 def parse_options(): 48 def parse_options():
49 parser = optparse.OptionParser() 49 parser = optparse.OptionParser()
50 parser.add_option('--event-names-file', help='output file') 50 parser.add_option('--event-names-file', help='output file')
51 parser.add_option('--idl-files-list', help='file listing all IDLs') 51 parser.add_option('--main-idl-files-list', help='file listing all IDLs')
Nils Barth (inactive) 2013/10/08 02:11:18 Not all anymore; how about: 'file listing main (co
kihong 2013/10/10 04:33:57 Done.
52 parser.add_option('--support-idl-files-list', help='file listing to test sup port IDLs')
Nils Barth (inactive) 2013/10/08 02:11:18 'file listing support IDL files (not compiled to B
kihong 2013/10/10 04:33:57 Done.
52 parser.add_option('--interface-dependencies-file', help='output file') 53 parser.add_option('--interface-dependencies-file', help='output file')
54 parser.add_option('--bindings-derived-sources-file', help='output file')
53 parser.add_option('--window-constructors-file', help='output file') 55 parser.add_option('--window-constructors-file', help='output file')
54 parser.add_option('--workerglobalscope-constructors-file', help='output file ') 56 parser.add_option('--workerglobalscope-constructors-file', help='output file ')
55 parser.add_option('--sharedworkerglobalscope-constructors-file', help='outpu t file') 57 parser.add_option('--sharedworkerglobalscope-constructors-file', help='outpu t file')
56 parser.add_option('--dedicatedworkerglobalscope-constructors-file', help='ou tput file') 58 parser.add_option('--dedicatedworkerglobalscope-constructors-file', help='ou tput file')
57 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') 59 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')
58 options, args = parser.parse_args() 60 options, args = parser.parse_args()
59 if options.event_names_file is None: 61 if options.event_names_file is None:
60 parser.error('Must specify an output file using --event-names-file.') 62 parser.error('Must specify an output file using --event-names-file.')
61 if options.interface_dependencies_file is None: 63 if options.interface_dependencies_file is None:
62 parser.error('Must specify an output file using --interface-dependencies -file.') 64 parser.error('Must specify an output file using --interface-dependencies -file.')
65 if options.bindings_derived_sources_file is None:
66 parser.error('Must specify an output file using --bindings-derived-sourc es-file.')
63 if options.window_constructors_file is None: 67 if options.window_constructors_file is None:
64 parser.error('Must specify an output file using --window-constructors-fi le.') 68 parser.error('Must specify an output file using --window-constructors-fi le.')
65 if options.workerglobalscope_constructors_file is None: 69 if options.workerglobalscope_constructors_file is None:
66 parser.error('Must specify an output file using --workerglobalscope-cons tructors-file.') 70 parser.error('Must specify an output file using --workerglobalscope-cons tructors-file.')
67 if options.workerglobalscope_constructors_file is None: 71 if options.workerglobalscope_constructors_file is None:
68 parser.error('Must specify an output file using --sharedworkerglobalscop e-constructors-file.') 72 parser.error('Must specify an output file using --sharedworkerglobalscop e-constructors-file.')
69 if options.workerglobalscope_constructors_file is None: 73 if options.workerglobalscope_constructors_file is None:
70 parser.error('Must specify an output file using --dedicatedworkerglobals cope-constructors-file.') 74 parser.error('Must specify an output file using --dedicatedworkerglobals cope-constructors-file.')
71 if options.idl_files_list is None: 75 if options.main_idl_files_list is None:
72 parser.error('Must specify the file listing all IDLs using --idl-files-l ist.') 76 parser.error('Must specify the file listing all IDLs using --idl-files-l ist.')
Nils Barth (inactive) 2013/10/08 02:11:18 'Must specify a file listing main IDL files using
kihong 2013/10/10 04:33:57 Done.
77 if options.support_idl_files_list is None:
78 parser.error('Must specify the file listing all IDLs using --support-idl -files-list.')
Nils Barth (inactive) 2013/10/08 02:11:18 'Must specify a file listing support IDL files usi
kihong 2013/10/10 04:33:57 Done.
73 if options.write_file_only_if_changed is None: 79 if options.write_file_only_if_changed is None:
74 parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.') 80 parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.')
75 options.write_file_only_if_changed = bool(options.write_file_only_if_changed ) 81 options.write_file_only_if_changed = bool(options.write_file_only_if_changed )
76 if args: 82 if args:
77 parser.error('No arguments taken, but "%s" given.' % ' '.join(args)) 83 parser.error('No arguments taken, but "%s" given.' % ' '.join(args))
78 return options 84 return options
79 85
80 86
81 def get_file_contents(idl_filename): 87 def get_file_contents(idl_filename):
82 with open(idl_filename) as idl_file: 88 with open(idl_filename) as idl_file:
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 if not match: 137 if not match:
132 return {} 138 return {}
133 extended_attributes = {} 139 extended_attributes = {}
134 parts = string.split(match.group(1), ',') 140 parts = string.split(match.group(1), ',')
135 for part in parts: 141 for part in parts:
136 key, _, value = map(string.strip, part.partition('=')) 142 key, _, value = map(string.strip, part.partition('='))
137 if not key: 143 if not key:
138 continue 144 continue
139 value = value or 'VALUE_IS_MISSING' 145 value = value or 'VALUE_IS_MISSING'
140 extended_attributes[key] = value 146 extended_attributes[key] = value
147
141 return extended_attributes 148 return extended_attributes
142 149
143 150
144 def generate_constructor_attribute_list(interface_name, extended_attributes): 151 def generate_constructor_attribute_list(interface_name, extended_attributes):
145 extended_attributes_list = [] 152 extended_attributes_list = []
146 for attribute_name, attribute_value in extended_attributes.iteritems(): 153 for attribute_name, attribute_value in extended_attributes.iteritems():
147 if attribute_name not in ['Conditional', 'EnabledAtRuntime', 'EnabledPer Context']: 154 if attribute_name not in ['Conditional', 'EnabledAtRuntime', 'EnabledPer Context']:
148 continue 155 continue
149 extended_attribute = attribute_name 156 extended_attribute = attribute_name
150 if attribute_value != 'VALUE_IS_MISSING': 157 if attribute_value != 'VALUE_IS_MISSING':
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 200
194 201
195 def generate_global_constructors_partial_interface(interface_name, destination_f ilename, constructor_attributes_list, only_if_changed): 202 def generate_global_constructors_partial_interface(interface_name, destination_f ilename, constructor_attributes_list, only_if_changed):
196 lines = (['partial interface %s {\n' % interface_name] + 203 lines = (['partial interface %s {\n' % interface_name] +
197 [' %s;\n' % constructor_attribute 204 [' %s;\n' % constructor_attribute
198 for constructor_attribute in sorted(constructor_attributes_list)] + 205 for constructor_attribute in sorted(constructor_attributes_list)] +
199 ['};\n']) 206 ['};\n'])
200 write_file(lines, destination_filename, only_if_changed) 207 write_file(lines, destination_filename, only_if_changed)
201 208
202 209
203 def parse_idl_files(idl_files, global_constructors_filenames): 210 def generate_dependencies(idl_file_name, interfaces, dependencies, partial_inter face_files, implements_interfaces, implemented_somewhere):
211 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name))
212 full_path = os.path.realpath(idl_file_name)
213 idl_file_contents = get_file_contents(full_path)
214
215 # Handle partial interfaces
216 partial_interface_name = get_partial_interface_name_from_idl(idl_file_conten ts)
217 if partial_interface_name:
218 partial_interface_files[partial_interface_name].append(full_path)
219 return partial_interface_name
220
221 interfaces.add(interface_name)
222 # Non-partial interfaces default to having bindings generated
223 dependencies[full_path] = []
224
225 # Parse 'identifier-A implements identifier-B;' statements
226 implemented_interfaces = get_implemented_interfaces_from_idl(idl_file_conten ts, interface_name)
227 implements_interfaces[interface_name] = implemented_interfaces
228 implemented_somewhere |= set(implemented_interfaces)
229
230 return partial_interface_name
231
232
233 def remove_implementation_redundancy(dependencies, interface_name_to_idl_file, i mplemented_somewhere):
234 # Interfaces that are implemented by another interface do not have
235 # their own bindings generated, as this would be redundant with the
236 # actual implementation.
237 for implemented_interface in implemented_somewhere:
238 full_path = interface_name_to_idl_file[implemented_interface]
239 del dependencies[full_path]
240
241
242 def record_global_constructors_and_extended_attribute(idl_file_name, global_cons tructors, interface_extended_attribute, parent_interface):
243 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name))
244 full_path = os.path.realpath(idl_file_name)
245 idl_file_contents = get_file_contents(full_path)
246 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co ntents)
247
248 # Record global constructors
249 if not is_callback_interface_from_idl(idl_file_contents) and 'NoInterfaceObj ect' not in extended_attributes:
250 global_contexts = extended_attributes.get('GlobalContext', 'Window').spl it('&')
251 new_constructor_list = generate_constructor_attribute_list(interface_nam e, extended_attributes)
252 for global_object in global_contexts:
253 global_constructors[global_object].extend(new_constructor_list)
254
255 # Record parents and extended attributes for generating event names
256 if interface_name == 'Event':
257 interface_extended_attribute[interface_name] = extended_attributes
258 parent = get_parent_interface(idl_file_contents)
259 if parent:
260 parent_interface[interface_name] = parent
261 interface_extended_attribute[interface_name] = extended_attributes
262
263
264 def parse_idl_files(main_idl_files, support_idl_files, global_constructors_filen ames):
204 """Return dependencies between IDL files, constructors on global objects, an d events. 265 """Return dependencies between IDL files, constructors on global objects, an d events.
205 266
206 Returns: 267 Returns:
207 interfaces: 268 interfaces:
208 set of all interfaces 269 set of all interfaces
270 bindings_derived_sources:
271 main IDL filename except test support IDLs
209 dependencies: 272 dependencies:
210 dict of main IDL filename (for a given interface) -> list of partial IDL filenames (for that interface) 273 dict of main IDL filename (for a given interface) -> list of partial IDL filenames (for that interface)
211 The keys (main IDL files) are the files for which bindings are 274 The keys (main IDL files) are the files for which bindings are
212 generated. This does not include IDL files for interfaces 275 generated. This does not include IDL files for interfaces
213 implemented by another interface. 276 implemented by another interface.
214 global_constructors: 277 global_constructors:
215 dict of global objects -> list of constructors on that object 278 dict of global objects -> list of constructors on that object
216 event_names: 279 event_names:
217 dict of interfaces that inherit from Event -> list of extended attri butes for the interface 280 dict of interfaces that inherit from Event -> list of extended attri butes for the interface
218 """ 281 """
219 interfaces = set() 282 interfaces = set()
220 dependencies = {} 283 dependencies = {}
221 partial_interface_files = {} 284 partial_interface_files = {}
222 implements_interfaces = {} 285 implements_interfaces = {}
223 implemented_somewhere = set() 286 implemented_somewhere = set()
224 287
225 global_constructors = {} 288 global_constructors = {}
226 for global_object in global_constructors_filenames.keys(): 289 for global_object in global_constructors_filenames.keys():
227 global_constructors[global_object] = [] 290 global_constructors[global_object] = []
228 291
229 # Parents and extended attributes (of interfaces with parents) are 292 # Parents and extended attributes (of interfaces with parents) are
230 # used in generating event names 293 # used in generating event names
231 parent_interface = {} 294 parent_interface = {}
232 interface_extended_attribute = {} 295 interface_extended_attribute = {}
233 296
234 interface_name_to_idl_file = {} 297 interface_name_to_idl_file = {}
235 for idl_file_name in idl_files: 298 for idl_file_name in main_idl_files + support_idl_files:
236 full_path = os.path.realpath(idl_file_name) 299 full_path = os.path.realpath(idl_file_name)
237 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name)) 300 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name))
238 interface_name_to_idl_file[interface_name] = full_path 301 interface_name_to_idl_file[interface_name] = full_path
239 partial_interface_files[interface_name] = [] 302 partial_interface_files[interface_name] = []
240 303
241 for idl_file_name in idl_files: 304 # Generate dependencies, global_constructors and interface_extended_attribut es for main IDL files
242 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name)) 305 for idl_file_name in main_idl_files:
243 full_path = interface_name_to_idl_file[interface_name] 306 if not generate_dependencies(idl_file_name, interfaces, dependencies, pa rtial_interface_files, implements_interfaces, implemented_somewhere):
244 idl_file_contents = get_file_contents(full_path) 307 record_global_constructors_and_extended_attribute(idl_file_name, glo bal_constructors, interface_extended_attribute, parent_interface)
245 308
246 # Handle partial interfaces 309 bindings_derived_sources = dependencies.copy()
247 partial_interface_name = get_partial_interface_name_from_idl(idl_file_co ntents) 310 remove_implementation_redundancy(bindings_derived_sources, interface_name_to _idl_file, implemented_somewhere)
248 if partial_interface_name:
249 partial_interface_files[partial_interface_name].append(full_path)
250 continue
251
252 interfaces.add(interface_name)
253 # Non-partial interfaces default to having bindings generated
254 dependencies[full_path] = []
255 extended_attributes = get_interface_extended_attributes_from_idl(idl_fil e_contents)
256
257 # Parse 'identifier-A implements identifier-B;' statements
258 implemented_interfaces = get_implemented_interfaces_from_idl(idl_file_co ntents, interface_name)
259 implements_interfaces[interface_name] = implemented_interfaces
260 implemented_somewhere |= set(implemented_interfaces)
261
262 # Record global constructors
263 if not is_callback_interface_from_idl(idl_file_contents) and 'NoInterfac eObject' not in extended_attributes:
264 global_contexts = extended_attributes.get('GlobalContext', 'Window') .split('&')
265 new_constructor_list = generate_constructor_attribute_list(interface _name, extended_attributes)
266 for global_object in global_contexts:
267 global_constructors[global_object].extend(new_constructor_list)
268
269 # Record parents and extended attributes for generating event names
270 if interface_name == 'Event':
271 interface_extended_attribute[interface_name] = extended_attributes
272 parent = get_parent_interface(idl_file_contents)
273 if parent:
274 parent_interface[interface_name] = parent
275 interface_extended_attribute[interface_name] = extended_attributes
276 311
277 # Add constructors on global objects to partial interfaces 312 # Add constructors on global objects to partial interfaces
278 for global_object, filename in global_constructors_filenames.iteritems(): 313 for global_object, filename in global_constructors_filenames.iteritems():
279 if global_object in interfaces: 314 if global_object in interfaces:
280 partial_interface_files[global_object].append(filename) 315 partial_interface_files[global_object].append(filename)
281 316
282 # Interfaces that are implemented by another interface do not have 317 # Add support IDL files to the dependencies for supporting partial interface
283 # their own bindings generated, as this would be redundant with the 318 for idl_file_name in support_idl_files:
284 # actual implementation. 319 generate_dependencies(idl_file_name, interfaces, dependencies, partial_i nterface_files, implements_interfaces, implemented_somewhere)
285 for implemented_interface in implemented_somewhere: 320 remove_implementation_redundancy(dependencies, interface_name_to_idl_file, i mplemented_somewhere)
286 full_path = interface_name_to_idl_file[implemented_interface]
287 del dependencies[full_path]
288 321
289 # An IDL file's dependencies are partial interface files that extend it, 322 # An IDL file's dependencies are partial interface files that extend it,
290 # and files for other interfaces that this interfaces implements. 323 # and files for other interfaces that this interfaces implements.
291 for idl_file_path in dependencies.iterkeys(): 324 for idl_file_path in dependencies.iterkeys():
292 interface_name, _ = os.path.splitext(os.path.basename(idl_file_path)) 325 interface_name, _ = os.path.splitext(os.path.basename(idl_file_path))
293 implemented_interfaces = implements_interfaces[interface_name] 326 implemented_interfaces = implements_interfaces[interface_name]
294 try: 327 try:
295 interface_paths = map(lambda x: interface_name_to_idl_file[x], imple mented_interfaces) 328 interface_paths = map(lambda x: interface_name_to_idl_file[x], imple mented_interfaces)
296 except KeyError as key_name: 329 except KeyError as key_name:
297 raise IdlInterfaceFileNotFoundError('Could not find the IDL file whe re the following implemented interface is defined: %s' % key_name) 330 raise IdlInterfaceFileNotFoundError('Could not find the IDL file whe re the following implemented interface is defined: %s' % key_name)
298 dependencies[idl_file_path] = sorted(partial_interface_files[interface_n ame] + interface_paths) 331 dependencies[idl_file_path] = sorted(partial_interface_files[interface_n ame] + interface_paths)
299 332
300 # Generate event names for all interfaces that inherit from Event, 333 # Generate event names for all interfaces that inherit from Event,
301 # including Event itself. 334 # including Event itself.
302 event_names = {} 335 event_names = {}
303 if 'Event' in interfaces: 336 if 'Event' in interfaces:
304 event_names[interface_name_to_idl_file['Event']] = interface_extended_at tribute['Event'] 337 event_names[interface_name_to_idl_file['Event']] = interface_extended_at tribute['Event']
305 for interface, parent in parent_interface.iteritems(): 338 for interface, parent in parent_interface.iteritems():
306 while parent in parent_interface: 339 while parent in parent_interface:
307 parent = parent_interface[parent] 340 parent = parent_interface[parent]
308 if parent == 'Event': 341 if parent == 'Event':
309 event_names[interface_name_to_idl_file[interface]] = interface_exten ded_attribute[interface] 342 event_names[interface_name_to_idl_file[interface]] = interface_exten ded_attribute[interface]
310 343
311 return interfaces, dependencies, global_constructors, event_names 344 return interfaces, dependencies, bindings_derived_sources, global_constructo rs, event_names
312 345
313 346
314 def write_dependency_file(filename, dependencies, only_if_changed): 347 def write_dependency_file(filename, dependencies, only_if_changed):
315 """Write the interface dependencies file. 348 """Write the interface dependencies file.
316 349
317 The format is as follows: 350 The format is as follows:
318 351
319 Document.idl P.idl 352 Document.idl P.idl
320 Event.idl 353 Event.idl
321 Window.idl Q.idl R.idl S.idl 354 Window.idl Q.idl R.idl S.idl
322 ... 355 ...
323 356
324 The above indicates that: 357 The above indicates that:
325 Document.idl depends on P.idl, 358 Document.idl depends on P.idl,
326 Event.idl depends on no other IDL files, and 359 Event.idl depends on no other IDL files, and
327 Window.idl depends on Q.idl, R.idl, and S.idl. 360 Window.idl depends on Q.idl, R.idl, and S.idl.
328 361
329 An IDL that is a dependency of another IDL (e.g. P.idl) does not have its 362 An IDL that is a dependency of another IDL (e.g. P.idl) does not have its
330 own line in the dependency file. 363 own line in the dependency file.
331 """ 364 """
332 lines = ['%s %s\n' % (idl_file, ' '.join(sorted(dependency_files))) 365 lines = ['%s %s\n' % (idl_file, ' '.join(sorted(dependency_files)))
333 for idl_file, dependency_files in sorted(dependencies.iteritems())] 366 for idl_file, dependency_files in sorted(dependencies.iteritems())]
334 write_file(lines, filename, only_if_changed) 367 write_file(lines, filename, only_if_changed)
335 368
336 369
337 def main(): 370 def main():
338 options = parse_options() 371 options = parse_options()
339 idl_files = [] 372 main_idl_files = []
340 with open(options.idl_files_list) as idl_files_list_file: 373 with open(options.main_idl_files_list) as idl_files_list_file:
341 for line in idl_files_list_file: 374 for line in idl_files_list_file:
342 idl_files.append(string.rstrip(line, '\n')) 375 main_idl_files.append(string.rstrip(line, '\n'))
376 support_idl_files = []
377 with open(options.support_idl_files_list) as idl_files_list_file:
378 for line in idl_files_list_file:
379 support_idl_files.append(string.rstrip(line, '\n'))
343 only_if_changed = options.write_file_only_if_changed 380 only_if_changed = options.write_file_only_if_changed
344 global_constructors_filenames = { 381 global_constructors_filenames = {
345 'Window': options.window_constructors_file, 382 'Window': options.window_constructors_file,
346 'WorkerGlobalScope': options.workerglobalscope_constructors_file, 383 'WorkerGlobalScope': options.workerglobalscope_constructors_file,
347 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_ file, 384 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_ file,
348 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constru ctors_file, 385 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constru ctors_file,
349 } 386 }
350 387
351 interfaces, dependencies, global_constructors, event_names = parse_idl_files (idl_files, global_constructors_filenames) 388 interfaces, dependencies, bindings_derived_sources, global_constructors, eve nt_names = parse_idl_files(main_idl_files, support_idl_files, global_constructor s_filenames)
352 389
353 write_dependency_file(options.interface_dependencies_file, dependencies, onl y_if_changed) 390 write_dependency_file(options.interface_dependencies_file, dependencies, onl y_if_changed)
391 write_dependency_file(options.bindings_derived_sources_file, bindings_derive d_sources, only_if_changed)
354 for interface_name, filename in global_constructors_filenames.iteritems(): 392 for interface_name, filename in global_constructors_filenames.iteritems():
355 if interface_name in interfaces: 393 if interface_name in interfaces:
356 generate_global_constructors_partial_interface(interface_name, filen ame, global_constructors[interface_name], only_if_changed) 394 generate_global_constructors_partial_interface(interface_name, filen ame, global_constructors[interface_name], only_if_changed)
357 generate_event_names_file(options.event_names_file, event_names, only_if_cha nged) 395 generate_event_names_file(options.event_names_file, event_names, only_if_cha nged)
358 396
359 397
360 if __name__ == '__main__': 398 if __name__ == '__main__':
361 main() 399 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698