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

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 main (compiled to Blink) IDL files')
52 parser.add_option('--support-idl-files-list', help='file listing support IDL files (not compiled to Blink, e.g. testing)')
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 a file listing main IDL files using --main-id l-files-list.')
77 if options.support_idl_files_list is None:
78 parser.error('Must specify a file listing support IDL files using --supp ort-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_dependencies(idl_file_name, interfaces, dependencies, partial_inter face_files, implements_interfaces, implemented_somewhere):
210 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name))
211 full_path = os.path.realpath(idl_file_name)
212 idl_file_contents = get_file_contents(full_path)
213
214 # Handle partial interfaces
215 partial_interface_name = get_partial_interface_name_from_idl(idl_file_conten ts)
216 if partial_interface_name:
217 partial_interface_files[partial_interface_name].append(full_path)
218 return partial_interface_name
219
220 interfaces.add(interface_name)
221 # Non-partial interfaces default to having bindings generated
222 dependencies[full_path] = []
223
224 # Parse 'identifier-A implements identifier-B;' statements
225 implemented_interfaces = get_implemented_interfaces_from_idl(idl_file_conten ts, interface_name)
226 implements_interfaces[interface_name] = implemented_interfaces
227 implemented_somewhere |= set(implemented_interfaces)
228
229 return partial_interface_name
230
231
232 def remove_interfaces_implemented_somewhere(dependencies, interface_name_to_idl_ file, implemented_somewhere):
233 # Interfaces that are implemented by another interface do not have
234 # their own bindings generated, as this would be redundant with the
235 # actual implementation.
236 for implemented_interface in implemented_somewhere:
237 full_path = interface_name_to_idl_file[implemented_interface]
238 del dependencies[full_path]
239
240
241 def record_global_constructors_and_extended_attribute(idl_file_name, global_cons tructors, interface_extended_attribute, parent_interface):
242 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name))
243 full_path = os.path.realpath(idl_file_name)
244 idl_file_contents = get_file_contents(full_path)
245 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co ntents)
246
247 # Record global constructors
248 if not is_callback_interface_from_idl(idl_file_contents) and 'NoInterfaceObj ect' not in extended_attributes:
249 global_contexts = extended_attributes.get('GlobalContext', 'Window').spl it('&')
250 new_constructor_list = generate_constructor_attribute_list(interface_nam e, extended_attributes)
251 for global_object in global_contexts:
252 global_constructors[global_object].extend(new_constructor_list)
253
254 # Record parents and extended attributes for generating event names
255 if interface_name == 'Event':
256 interface_extended_attribute[interface_name] = extended_attributes
257 parent = get_parent_interface(idl_file_contents)
258 if parent:
259 parent_interface[interface_name] = parent
260 interface_extended_attribute[interface_name] = extended_attributes
261
262
263 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. 264 """Return dependencies between IDL files, constructors on global objects, an d events.
205 265
206 Returns: 266 Returns:
207 interfaces: 267 interfaces:
208 set of all interfaces 268 set of all interfaces
269 bindings_derived_sources:
270 list of main IDL file names (except support IDL file names)
209 dependencies: 271 dependencies:
210 dict of main IDL filename (for a given interface) -> list of partial IDL filenames (for that interface) 272 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 273 The keys (main IDL files) are the files for which bindings are
212 generated. This does not include IDL files for interfaces 274 generated. This does not include IDL files for interfaces
213 implemented by another interface. 275 implemented by another interface.
214 global_constructors: 276 global_constructors:
215 dict of global objects -> list of constructors on that object 277 dict of global objects -> list of constructors on that object
216 event_names: 278 event_names:
217 dict of interfaces that inherit from Event -> list of extended attri butes for the interface 279 dict of interfaces that inherit from Event -> list of extended attri butes for the interface
218 """ 280 """
219 interfaces = set() 281 interfaces = set()
220 dependencies = {} 282 dependencies = {}
221 partial_interface_files = {} 283 partial_interface_files = {}
222 implements_interfaces = {} 284 implements_interfaces = {}
223 implemented_somewhere = set() 285 implemented_somewhere = set()
224 286
225 global_constructors = {} 287 global_constructors = {}
226 for global_object in global_constructors_filenames.keys(): 288 for global_object in global_constructors_filenames.keys():
227 global_constructors[global_object] = [] 289 global_constructors[global_object] = []
228 290
229 # Parents and extended attributes (of interfaces with parents) are 291 # Parents and extended attributes (of interfaces with parents) are
230 # used in generating event names 292 # used in generating event names
231 parent_interface = {} 293 parent_interface = {}
232 interface_extended_attribute = {} 294 interface_extended_attribute = {}
233 295
234 interface_name_to_idl_file = {} 296 interface_name_to_idl_file = {}
235 for idl_file_name in idl_files: 297 for idl_file_name in main_idl_files + support_idl_files:
236 full_path = os.path.realpath(idl_file_name) 298 full_path = os.path.realpath(idl_file_name)
237 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name)) 299 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name))
238 interface_name_to_idl_file[interface_name] = full_path 300 interface_name_to_idl_file[interface_name] = full_path
239 partial_interface_files[interface_name] = [] 301 partial_interface_files[interface_name] = []
240 302
241 for idl_file_name in idl_files: 303 # 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)) 304 for idl_file_name in main_idl_files:
243 full_path = interface_name_to_idl_file[interface_name] 305 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) 306 record_global_constructors_and_extended_attribute(idl_file_name, glo bal_constructors, interface_extended_attribute, parent_interface)
245 307
246 # Handle partial interfaces 308 bindings_derived_sources = dependencies.copy()
247 partial_interface_name = get_partial_interface_name_from_idl(idl_file_co ntents) 309 remove_interfaces_implemented_somewhere(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 310
277 # Add constructors on global objects to partial interfaces 311 # Add constructors on global objects to partial interfaces
278 for global_object, filename in global_constructors_filenames.iteritems(): 312 for global_object, filename in global_constructors_filenames.iteritems():
279 if global_object in interfaces: 313 if global_object in interfaces:
280 partial_interface_files[global_object].append(filename) 314 partial_interface_files[global_object].append(filename)
281 315
282 # Interfaces that are implemented by another interface do not have 316 # Add support IDL files to the dependencies for supporting partial interface
283 # their own bindings generated, as this would be redundant with the 317 for idl_file_name in support_idl_files:
284 # actual implementation. 318 generate_dependencies(idl_file_name, interfaces, dependencies, partial_i nterface_files, implements_interfaces, implemented_somewhere)
285 for implemented_interface in implemented_somewhere: 319 remove_interfaces_implemented_somewhere(dependencies, interface_name_to_idl_ file, implemented_somewhere)
286 full_path = interface_name_to_idl_file[implemented_interface]
287 del dependencies[full_path]
288 320
289 # An IDL file's dependencies are partial interface files that extend it, 321 # An IDL file's dependencies are partial interface files that extend it,
290 # and files for other interfaces that this interfaces implements. 322 # and files for other interfaces that this interfaces implements.
291 for idl_file_path in dependencies.iterkeys(): 323 for idl_file_path in dependencies.iterkeys():
292 interface_name, _ = os.path.splitext(os.path.basename(idl_file_path)) 324 interface_name, _ = os.path.splitext(os.path.basename(idl_file_path))
293 implemented_interfaces = implements_interfaces[interface_name] 325 implemented_interfaces = implements_interfaces[interface_name]
294 try: 326 try:
295 interface_paths = map(lambda x: interface_name_to_idl_file[x], imple mented_interfaces) 327 interface_paths = map(lambda x: interface_name_to_idl_file[x], imple mented_interfaces)
296 except KeyError as key_name: 328 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) 329 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) 330 dependencies[idl_file_path] = sorted(partial_interface_files[interface_n ame] + interface_paths)
299 331
300 # Generate event names for all interfaces that inherit from Event, 332 # Generate event names for all interfaces that inherit from Event,
301 # including Event itself. 333 # including Event itself.
302 event_names = {} 334 event_names = {}
303 if 'Event' in interfaces: 335 if 'Event' in interfaces:
304 event_names[interface_name_to_idl_file['Event']] = interface_extended_at tribute['Event'] 336 event_names[interface_name_to_idl_file['Event']] = interface_extended_at tribute['Event']
305 for interface, parent in parent_interface.iteritems(): 337 for interface, parent in parent_interface.iteritems():
306 while parent in parent_interface: 338 while parent in parent_interface:
307 parent = parent_interface[parent] 339 parent = parent_interface[parent]
308 if parent == 'Event': 340 if parent == 'Event':
309 event_names[interface_name_to_idl_file[interface]] = interface_exten ded_attribute[interface] 341 event_names[interface_name_to_idl_file[interface]] = interface_exten ded_attribute[interface]
310 342
311 return interfaces, dependencies, global_constructors, event_names 343 return interfaces, dependencies, bindings_derived_sources, global_constructo rs, event_names
312 344
313 345
314 def write_dependency_file(filename, dependencies, only_if_changed): 346 def write_dependency_file(filename, dependencies, only_if_changed):
315 """Write the interface dependencies file. 347 """Write the interface dependencies file.
316 348
317 The format is as follows: 349 The format is as follows:
318 350
319 Document.idl P.idl 351 Document.idl P.idl
320 Event.idl 352 Event.idl
321 Window.idl Q.idl R.idl S.idl 353 Window.idl Q.idl R.idl S.idl
322 ... 354 ...
323 355
324 The above indicates that: 356 The above indicates that:
325 Document.idl depends on P.idl, 357 Document.idl depends on P.idl,
326 Event.idl depends on no other IDL files, and 358 Event.idl depends on no other IDL files, and
327 Window.idl depends on Q.idl, R.idl, and S.idl. 359 Window.idl depends on Q.idl, R.idl, and S.idl.
328 360
329 An IDL that is a dependency of another IDL (e.g. P.idl) does not have its 361 An IDL that is a dependency of another IDL (e.g. P.idl) does not have its
330 own line in the dependency file. 362 own line in the dependency file.
331 """ 363 """
332 lines = ['%s %s\n' % (idl_file, ' '.join(sorted(dependency_files))) 364 lines = ['%s %s\n' % (idl_file, ' '.join(sorted(dependency_files)))
333 for idl_file, dependency_files in sorted(dependencies.iteritems())] 365 for idl_file, dependency_files in sorted(dependencies.iteritems())]
334 write_file(lines, filename, only_if_changed) 366 write_file(lines, filename, only_if_changed)
335 367
336 368
337 def main(): 369 def main():
338 options = parse_options() 370 options = parse_options()
339 idl_files = [] 371 with open(options.main_idl_files_list) as idl_files_list:
340 with open(options.idl_files_list) as idl_files_list_file: 372 main_idl_files = [string.rstrip(line, '\n') for line in idl_files_list]
341 for line in idl_files_list_file: 373 with open(options.support_idl_files_list) as idl_files_list:
342 idl_files.append(string.rstrip(line, '\n')) 374 support_idl_files = [string.rstrip(line, '\n') for line in idl_files_lis t]
343 only_if_changed = options.write_file_only_if_changed 375 only_if_changed = options.write_file_only_if_changed
344 global_constructors_filenames = { 376 global_constructors_filenames = {
345 'Window': options.window_constructors_file, 377 'Window': options.window_constructors_file,
346 'WorkerGlobalScope': options.workerglobalscope_constructors_file, 378 'WorkerGlobalScope': options.workerglobalscope_constructors_file,
347 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_ file, 379 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_ file,
348 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constru ctors_file, 380 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constru ctors_file,
349 } 381 }
350 382
351 interfaces, dependencies, global_constructors, event_names = parse_idl_files (idl_files, global_constructors_filenames) 383 interfaces, dependencies, bindings_derived_sources, global_constructors, eve nt_names = parse_idl_files(main_idl_files, support_idl_files, global_constructor s_filenames)
352 384
353 write_dependency_file(options.interface_dependencies_file, dependencies, onl y_if_changed) 385 write_dependency_file(options.interface_dependencies_file, dependencies, onl y_if_changed)
386 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(): 387 for interface_name, filename in global_constructors_filenames.iteritems():
355 if interface_name in interfaces: 388 if interface_name in interfaces:
356 generate_global_constructors_partial_interface(interface_name, filen ame, global_constructors[interface_name], only_if_changed) 389 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) 390 generate_event_names_file(options.event_names_file, event_names, only_if_cha nged)
358 391
359 392
360 if __name__ == '__main__': 393 if __name__ == '__main__':
361 main() 394 main()
OLDNEW
« no previous file with comments | « Source/bindings/derived_sources.gyp ('k') | Source/bindings/tests/idls/testing/SupportTestInterface.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698