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

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: Created 7 years, 3 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 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
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('--idl-files-list', help='file listing all IDLs')
52 parser.add_option('--interface-dependencies-file', help='output file') 52 parser.add_option('--interface-dependencies-file', help='output file')
53 parser.add_option('--test-support-idl-files-list', help='file listing all te st support IDLs')
54 parser.add_option('--test-support-interface-dependencies-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.test_support_interface_dependencies_file is None:
66 parser.error('Must specify an output file using --test-support-interface -dependencies-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.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.')
77 if options.test_support_idl_files_list is None:
78 parser.error('Must specify the file listing all IDLs using --test-suppor t-idl-files-list.')
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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 199
194 200
195 def generate_global_constructors_partial_interface(interface_name, destination_f ilename, constructor_attributes_list, only_if_changed): 201 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] + 202 lines = (['partial interface %s {\n' % interface_name] +
197 [' %s;\n' % constructor_attribute 203 [' %s;\n' % constructor_attribute
198 for constructor_attribute in sorted(constructor_attributes_list)] + 204 for constructor_attribute in sorted(constructor_attributes_list)] +
199 ['};\n']) 205 ['};\n'])
200 write_file(lines, destination_filename, only_if_changed) 206 write_file(lines, destination_filename, only_if_changed)
201 207
202 208
203 def parse_idl_files(idl_files, global_constructors_filenames): 209 def generate_interface_name_to_idl_file(idl_files,
204 """Return dependencies between IDL files, constructors on global objects, an d events. 210 interface_name_to_idl_file,
205 211 partial_interface_files,
206 Returns: 212 interfaces,
207 interfaces: 213 dependencies,
208 set of all interfaces 214 implements_interfaces,
209 dependencies: 215 implemented_somewhere,
210 dict of main IDL filename (for a given interface) -> list of partial IDL filenames (for that interface) 216 global_constructors,
211 The keys (main IDL files) are the files for which bindings are 217 parent_interface,
212 generated. This does not include IDL files for interfaces 218 interface_extended_attribute):
213 implemented by another interface.
214 global_constructors:
215 dict of global objects -> list of constructors on that object
216 event_names:
217 dict of interfaces that inherit from Event -> list of extended attri butes for the interface
218 """
219 interfaces = set()
220 dependencies = {}
221 partial_interface_files = {}
222 implements_interfaces = {}
223 implemented_somewhere = set()
224
225 global_constructors = {}
226 for global_object in global_constructors_filenames.keys():
227 global_constructors[global_object] = []
228
229 # Parents and extended attributes (of interfaces with parents) are
230 # used in generating event names
231 parent_interface = {}
232 interface_extended_attribute = {}
233
234 interface_name_to_idl_file = {}
235 for idl_file_name in idl_files: 219 for idl_file_name in idl_files:
236 full_path = os.path.realpath(idl_file_name) 220 full_path = os.path.realpath(idl_file_name)
237 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name)) 221 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name))
238 interface_name_to_idl_file[interface_name] = full_path 222 interface_name_to_idl_file[interface_name] = full_path
239 partial_interface_files[interface_name] = [] 223 partial_interface_files[interface_name] = []
240 224
241 for idl_file_name in idl_files: 225 for idl_file_name in idl_files:
242 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name)) 226 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name))
243 full_path = interface_name_to_idl_file[interface_name] 227 full_path = interface_name_to_idl_file[interface_name]
244 idl_file_contents = get_file_contents(full_path) 228 idl_file_contents = get_file_contents(full_path)
245 229
246 # Handle partial interfaces 230 # Handle partial interfaces
247 partial_interface_name = get_partial_interface_name_from_idl(idl_file_co ntents) 231 partial_interface_name = get_partial_interface_name_from_idl(idl_file_co ntents)
248 if partial_interface_name: 232 if partial_interface_name:
249 partial_interface_files[partial_interface_name].append(full_path) 233 partial_interface_files[partial_interface_name].append(full_path)
250 continue 234 continue
251 235
252 interfaces.add(interface_name) 236 interfaces.add(interface_name)
253 # Non-partial interfaces default to having bindings generated 237 # Non-partial interfaces default to having bindings generated
254 dependencies[full_path] = [] 238 dependencies[full_path] = []
255 extended_attributes = get_interface_extended_attributes_from_idl(idl_fil e_contents) 239 extended_attributes = get_interface_extended_attributes_from_idl(idl_fil e_contents)
256 240
257 # Parse 'identifier-A implements identifier-B;' statements 241 # Parse 'identifier-A implements identifier-B;' statements
258 implemented_interfaces = get_implemented_interfaces_from_idl(idl_file_co ntents, interface_name) 242 implemented_interfaces = get_implemented_interfaces_from_idl(idl_file_co ntents, interface_name)
259 implements_interfaces[interface_name] = implemented_interfaces 243 implements_interfaces[interface_name] = implemented_interfaces
260 implemented_somewhere |= set(implemented_interfaces) 244 implemented_somewhere |= set(implemented_interfaces)
261 245
262 # Record global constructors 246 # Record global constructors
263 if not is_callback_interface_from_idl(idl_file_contents) and 'NoInterfac eObject' not in extended_attributes: 247 if global_constructors:
264 global_contexts = extended_attributes.get('GlobalContext', 'Window') .split('&') 248 if not is_callback_interface_from_idl(idl_file_contents) and 'NoInte rfaceObject' not in extended_attributes:
265 new_constructor_list = generate_constructor_attribute_list(interface _name, extended_attributes) 249 global_contexts = extended_attributes.get('GlobalContext', 'Wind ow').split('&')
266 for global_object in global_contexts: 250 new_constructor_list = generate_constructor_attribute_list(inter face_name, extended_attributes)
267 global_constructors[global_object].extend(new_constructor_list) 251 for global_object in global_contexts:
252 global_constructors[global_object].extend(new_constructor_li st)
268 253
269 # Record parents and extended attributes for generating event names 254 # Record parents and extended attributes for generating event names
270 if interface_name == 'Event': 255 if interface_name == 'Event':
271 interface_extended_attribute[interface_name] = extended_attributes 256 interface_extended_attribute[interface_name] = extended_attributes
272 parent = get_parent_interface(idl_file_contents) 257 parent = get_parent_interface(idl_file_contents)
273 if parent: 258 if parent:
274 parent_interface[interface_name] = parent 259 parent_interface[interface_name] = parent
275 interface_extended_attribute[interface_name] = extended_attributes 260 interface_extended_attribute[interface_name] = extended_attributes
276 261
262
263 def parse_idl_files(idl_files, test_support_idl_files, global_constructors_filen ames):
264 """Return dependencies between IDL files, constructors on global objects, an d events.
265
266 Returns:
267 interfaces:
268 set of all interfaces
269 dependencies:
270 dict of main IDL filename (for a given interface) -> list of partial IDL filenames (for that interface)
271 The keys (main IDL files) are the files for which bindings are
272 generated. This does not include IDL files for interfaces
273 implemented by another interface.
274 test_support_dependencies:
275 dict of test support IDL filename (for a given interface) -> list of partial IDL filenames (for that interface)
276 The keys (main IDL files) are the files for which bindings are
277 generated. This does not include IDL files for interfaces
278 implemented by another interface.
279 global_constructors:
280 dict of global objects -> list of constructors on that object
281 event_names:
282 dict of interfaces that inherit from Event -> list of extended attri butes for the interface
283 """
284 interfaces = set()
285 dependencies = {}
286 partial_interface_files = {}
287 implements_interfaces = {}
288 implemented_somewhere = set()
289
290 test_support_interfaces = set()
291 test_support_dependencies = {}
292 test_support_partial_interface_files = {}
293 test_support_implements_interfaces = {}
294 test_support_implemented_somewhere = set()
295
296 global_constructors = {}
297 for global_object in global_constructors_filenames.keys():
298 global_constructors[global_object] = []
299
300 # Parents and extended attributes (of interfaces with parents) are
301 # used in generating event names
302 parent_interface = {}
303 interface_extended_attribute = {}
304
305 interface_name_to_idl_file = {}
306 generate_interface_name_to_idl_file(idl_files,
307 interface_name_to_idl_file,
308 partial_interface_files,
309 interfaces,
310 dependencies,
311 implements_interfaces,
312 implemented_somewhere,
313 global_constructors,
314 parent_interface,
315 interface_extended_attribute)
316
317 test_support_interface_name_to_idl_file = {}
318 generate_interface_name_to_idl_file(test_support_idl_files,
319 test_support_interface_name_to_idl_file,
320 test_support_partial_interface_files,
321 test_support_interfaces,
322 test_support_dependencies,
323 test_support_implements_interfaces,
324 test_support_implemented_somewhere,
325 None,
326 parent_interface,
327 interface_extended_attribute)
328
277 # Add constructors on global objects to partial interfaces 329 # Add constructors on global objects to partial interfaces
330
278 for global_object, filename in global_constructors_filenames.iteritems(): 331 for global_object, filename in global_constructors_filenames.iteritems():
279 if global_object in interfaces: 332 if global_object in interfaces:
280 partial_interface_files[global_object].append(filename) 333 partial_interface_files[global_object].append(filename)
334 if global_object in test_support_interfaces:
do-not-use 2013/09/09 07:27:10 elif?
Nils Barth (inactive) 2013/09/10 09:52:10 I'm actually confused about whether we want to be
335 test_support_partial_interface_files[global_object].append(filename)
281 336
282 # Interfaces that are implemented by another interface do not have 337 # Interfaces that are implemented by another interface do not have
283 # their own bindings generated, as this would be redundant with the 338 # their own bindings generated, as this would be redundant with the
284 # actual implementation. 339 # actual implementation.
285 for implemented_interface in implemented_somewhere: 340 for implemented_interface in implemented_somewhere:
286 full_path = interface_name_to_idl_file[implemented_interface] 341 full_path = interface_name_to_idl_file[implemented_interface]
287 del dependencies[full_path] 342 del dependencies[full_path]
288 343
344 for test_support_implemented_interface in test_support_implemented_somewhere :
345 full_path = test_support_interface_name_to_idl_file[test_support_impleme nted_interface]
346 del test_support_dependencies[full_path]
347
289 # An IDL file's dependencies are partial interface files that extend it, 348 # An IDL file's dependencies are partial interface files that extend it,
290 # and files for other interfaces that this interfaces implements. 349 # and files for other interfaces that this interfaces implements.
291 for idl_file_path in dependencies.iterkeys(): 350 for idl_file_path in dependencies.iterkeys():
292 interface_name, _ = os.path.splitext(os.path.basename(idl_file_path)) 351 interface_name, _ = os.path.splitext(os.path.basename(idl_file_path))
293 implemented_interfaces = implements_interfaces[interface_name] 352 implemented_interfaces = implements_interfaces[interface_name]
294 try: 353 try:
295 interface_paths = map(lambda x: interface_name_to_idl_file[x], imple mented_interfaces) 354 interface_paths = map(lambda x: interface_name_to_idl_file[x], imple mented_interfaces)
296 except KeyError as key_name: 355 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) 356 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) 357 dependencies[idl_file_path] = sorted(partial_interface_files[interface_n ame] + interface_paths)
299 358
359 for test_support_idl_file_path in test_support_dependencies.iterkeys():
360 interface_name, _ = os.path.splitext(os.path.basename(test_support_idl_f ile_path))
361 test_support_implemented_interfaces = test_support_implements_interfaces [interface_name]
362 try:
363 interface_paths = map(lambda x: test_support_interface_name_to_idl_f ile[x], test_support_implemented_interfaces)
364 except KeyError, key_name:
365 raise IdlInterfaceFileNotFoundError('Could not find the IDL file whe re the following implemented interface is defined: %s' % key_name)
366 test_support_dependencies[test_support_idl_file_path] = sorted(test_supp ort_partial_interface_files[interface_name] + interface_paths)
367
300 # Generate event names for all interfaces that inherit from Event, 368 # Generate event names for all interfaces that inherit from Event,
301 # including Event itself. 369 # including Event itself.
302 event_names = {} 370 event_names = {}
303 if 'Event' in interfaces: 371 if 'Event' in interfaces:
304 event_names[interface_name_to_idl_file['Event']] = interface_extended_at tribute['Event'] 372 event_names[interface_name_to_idl_file['Event']] = interface_extended_at tribute['Event']
305 for interface, parent in parent_interface.iteritems(): 373 for interface, parent in parent_interface.iteritems():
306 while parent in parent_interface: 374 while parent in parent_interface:
307 parent = parent_interface[parent] 375 parent = parent_interface[parent]
308 if parent == 'Event': 376 if parent == 'Event':
309 event_names[interface_name_to_idl_file[interface]] = interface_exten ded_attribute[interface] 377 event_names[interface_name_to_idl_file[interface]] = interface_exten ded_attribute[interface]
310 378
311 return interfaces, dependencies, global_constructors, event_names 379 return interfaces, dependencies, test_support_dependencies, global_construct ors, event_names
312 380
313 381
314 def write_dependency_file(filename, dependencies, only_if_changed): 382 def write_dependency_file(filename, dependencies, only_if_changed):
315 """Write the interface dependencies file. 383 """Write the interface dependencies file.
316 384
317 The format is as follows: 385 The format is as follows:
318 386
319 Document.idl P.idl 387 Document.idl P.idl
320 Event.idl 388 Event.idl
321 Window.idl Q.idl R.idl S.idl 389 Window.idl Q.idl R.idl S.idl
322 ... 390 ...
323 391
324 The above indicates that: 392 The above indicates that:
325 Document.idl depends on P.idl, 393 Document.idl depends on P.idl,
326 Event.idl depends on no other IDL files, and 394 Event.idl depends on no other IDL files, and
327 Window.idl depends on Q.idl, R.idl, and S.idl. 395 Window.idl depends on Q.idl, R.idl, and S.idl.
328 396
329 An IDL that is a dependency of another IDL (e.g. P.idl) does not have its 397 An IDL that is a dependency of another IDL (e.g. P.idl) does not have its
330 own line in the dependency file. 398 own line in the dependency file.
331 """ 399 """
332 lines = ['%s %s\n' % (idl_file, ' '.join(sorted(dependency_files))) 400 lines = ['%s %s\n' % (idl_file, ' '.join(sorted(dependency_files)))
333 for idl_file, dependency_files in sorted(dependencies.iteritems())] 401 for idl_file, dependency_files in sorted(dependencies.iteritems())]
334 write_file(lines, filename, only_if_changed) 402 write_file(lines, filename, only_if_changed)
335 403
336 404
405
337 def main(): 406 def main():
338 options = parse_options() 407 options = parse_options()
339 idl_files = [] 408 idl_files = []
340 with open(options.idl_files_list) as idl_files_list_file: 409 with open(options.idl_files_list) as idl_files_list_file:
341 for line in idl_files_list_file: 410 for line in idl_files_list_file:
342 idl_files.append(string.rstrip(line, '\n')) 411 idl_files.append(string.rstrip(line, '\n'))
412 test_support_idl_files = []
413 with open(options.test_support_idl_files_list) as test_support_idl_files_lis t_file:
414 for line in test_support_idl_files_list_file:
415 test_support_idl_files.append(string.rstrip(line, '\n'))
343 only_if_changed = options.write_file_only_if_changed 416 only_if_changed = options.write_file_only_if_changed
344 global_constructors_filenames = { 417 global_constructors_filenames = {
345 'Window': options.window_constructors_file, 418 'Window': options.window_constructors_file,
346 'WorkerGlobalScope': options.workerglobalscope_constructors_file, 419 'WorkerGlobalScope': options.workerglobalscope_constructors_file,
347 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_ file, 420 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_ file,
348 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constru ctors_file, 421 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constru ctors_file,
349 } 422 }
350 423
351 interfaces, dependencies, global_constructors, event_names = parse_idl_files (idl_files, global_constructors_filenames) 424 interfaces, dependencies, test_support_dependencies, global_constructors, ev ent_names = parse_idl_files(idl_files, test_support_idl_files, global_constructo rs_filenames)
352 425
353 write_dependency_file(options.interface_dependencies_file, dependencies, onl y_if_changed) 426 write_dependency_file(options.interface_dependencies_file, dependencies, onl y_if_changed)
427 write_dependency_file(options.test_support_interface_dependencies_file, test _support_dependencies, only_if_changed)
354 for interface_name, filename in global_constructors_filenames.iteritems(): 428 for interface_name, filename in global_constructors_filenames.iteritems():
355 if interface_name in interfaces: 429 if interface_name in interfaces:
356 generate_global_constructors_partial_interface(interface_name, filen ame, global_constructors[interface_name], only_if_changed) 430 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) 431 generate_event_names_file(options.event_names_file, event_names, only_if_cha nged)
358 432
359 433
360 if __name__ == '__main__': 434 if __name__ == '__main__':
361 main() 435 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698