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

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: Remove hardcoding 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 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('--idl-files-list', help='file listing all IDLs')
Nils Barth (inactive) 2013/09/17 02:23:35 Could you update the comment here and for --testin
52 parser.add_option('--testing-idl-files-list', help='file listing all IDLs')
haraken 2013/09/17 03:36:52 I'd rename: --idl-files-list => --core-idl-file
Nils Barth (inactive) 2013/09/17 05:17:46 Agreed, this naming makes the purposes clear. Howe
kihong 2013/09/17 06:33:04 We don't need to think core indicate Source/core b
haraken 2013/09/17 06:42:06 We're planning to use --testing-idl-files not only
Nils Barth (inactive) 2013/09/17 06:47:15 Instead of "assistance", maybe "support"? (More id
kihong 2013/10/04 06:11:38 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('--binding-derived-source-file', help='output file')
haraken 2013/09/17 03:36:52 --binding-derived-source-file => --core-derived-so
Nils Barth (inactive) 2013/09/17 05:17:46 Agreed that "derived sources" is pretty confusing.
kihong 2013/09/17 06:33:04 "--binding-derived-source-file" indicates files li
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.binding_derived_source_file is None:
66 parser.error('Must specify an output file using --binding-derived-source -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.testing_idl_files_list is None:
78 parser.error('Must specify the file listing all IDLs using --testing-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 parse_idl_files(idl_files, testing_idl_files, global_constructors_filenames) :
Nils Barth (inactive) 2013/09/17 02:23:35 Could you rename 'idl_files' to something like 'bi
kihong 2013/10/04 06:11:38 Done.
204 """Return dependencies between IDL files, constructors on global objects, an d events. 210 """Return dependencies between IDL files, constructors on global objects, an d events.
205 211
206 Returns: 212 Returns:
207 interfaces: 213 interfaces:
208 set of all interfaces 214 set of all interfaces
215 source_idls:
216 main IDL filename except test support IDLs
209 dependencies: 217 dependencies:
210 dict of main IDL filename (for a given interface) -> list of partial IDL filenames (for that interface) 218 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 219 The keys (main IDL files) are the files for which bindings are
212 generated. This does not include IDL files for interfaces 220 generated. This does not include IDL files for interfaces
213 implemented by another interface. 221 implemented by another interface.
214 global_constructors: 222 global_constructors:
215 dict of global objects -> list of constructors on that object 223 dict of global objects -> list of constructors on that object
216 event_names: 224 event_names:
217 dict of interfaces that inherit from Event -> list of extended attri butes for the interface 225 dict of interfaces that inherit from Event -> list of extended attri butes for the interface
218 """ 226 """
219 interfaces = set() 227 interfaces = set()
228 binding_derived_sources = {}
220 dependencies = {} 229 dependencies = {}
221 partial_interface_files = {} 230 partial_interface_files = {}
222 implements_interfaces = {} 231 implements_interfaces = {}
223 implemented_somewhere = set() 232 implemented_somewhere = set()
224 233
225 global_constructors = {} 234 global_constructors = {}
226 for global_object in global_constructors_filenames.keys(): 235 for global_object in global_constructors_filenames.keys():
227 global_constructors[global_object] = [] 236 global_constructors[global_object] = []
228 237
229 # Parents and extended attributes (of interfaces with parents) are 238 # Parents and extended attributes (of interfaces with parents) are
230 # used in generating event names 239 # used in generating event names
231 parent_interface = {} 240 parent_interface = {}
232 interface_extended_attribute = {} 241 interface_extended_attribute = {}
233 242
243 dependencies_idl_files = idl_files + testing_idl_files
244
234 interface_name_to_idl_file = {} 245 interface_name_to_idl_file = {}
235 for idl_file_name in idl_files: 246 for idl_file_name in dependencies_idl_files:
236 full_path = os.path.realpath(idl_file_name) 247 full_path = os.path.realpath(idl_file_name)
237 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name)) 248 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name))
238 interface_name_to_idl_file[interface_name] = full_path 249 interface_name_to_idl_file[interface_name] = full_path
239 partial_interface_files[interface_name] = [] 250 partial_interface_files[interface_name] = []
240 251
241 for idl_file_name in idl_files: 252 for idl_file_name in dependencies_idl_files:
242 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name)) 253 interface_name, _ = os.path.splitext(os.path.basename(idl_file_name))
243 full_path = interface_name_to_idl_file[interface_name] 254 full_path = interface_name_to_idl_file[interface_name]
244 idl_file_contents = get_file_contents(full_path) 255 idl_file_contents = get_file_contents(full_path)
245 256
246 # Handle partial interfaces 257 # Handle partial interfaces
247 partial_interface_name = get_partial_interface_name_from_idl(idl_file_co ntents) 258 partial_interface_name = get_partial_interface_name_from_idl(idl_file_co ntents)
248 if partial_interface_name: 259 if partial_interface_name:
249 partial_interface_files[partial_interface_name].append(full_path) 260 partial_interface_files[partial_interface_name].append(full_path)
250 continue 261 continue
251 262
252 interfaces.add(interface_name) 263 interfaces.add(interface_name)
253 # Non-partial interfaces default to having bindings generated 264 # Non-partial interfaces default to having bindings generated
254 dependencies[full_path] = [] 265 dependencies[full_path] = []
255 extended_attributes = get_interface_extended_attributes_from_idl(idl_fil e_contents) 266 extended_attributes = get_interface_extended_attributes_from_idl(idl_fil e_contents)
256 267
257 # Parse 'identifier-A implements identifier-B;' statements 268 # Parse 'identifier-A implements identifier-B;' statements
258 implemented_interfaces = get_implemented_interfaces_from_idl(idl_file_co ntents, interface_name) 269 implemented_interfaces = get_implemented_interfaces_from_idl(idl_file_co ntents, interface_name)
259 implements_interfaces[interface_name] = implemented_interfaces 270 implements_interfaces[interface_name] = implemented_interfaces
260 implemented_somewhere |= set(implemented_interfaces) 271 implemented_somewhere |= set(implemented_interfaces)
261 272
262 # Record global constructors 273 if idl_file_name not in testing_idl_files:
Nils Barth (inactive) 2013/09/17 02:23:35 This is kinda hacky: it's clearer to iterate over
Nils Barth (inactive) 2013/09/17 05:17:46 BTW, to elaborate: The code: interface_name, _ = o
kihong 2013/10/04 06:11:38 Done.
263 if not is_callback_interface_from_idl(idl_file_contents) and 'NoInterfac eObject' not in extended_attributes: 274 # Record global constructors
264 global_contexts = extended_attributes.get('GlobalContext', 'Window') .split('&') 275 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) 276 global_contexts = extended_attributes.get('GlobalContext', 'Wind ow').split('&')
266 for global_object in global_contexts: 277 new_constructor_list = generate_constructor_attribute_list(inter face_name, extended_attributes)
267 global_constructors[global_object].extend(new_constructor_list) 278 for global_object in global_contexts:
279 global_constructors[global_object].extend(new_constructor_li st)
268 280
269 # Record parents and extended attributes for generating event names 281 # Record parents and extended attributes for generating event names
270 if interface_name == 'Event': 282 if interface_name == 'Event':
271 interface_extended_attribute[interface_name] = extended_attributes 283 interface_extended_attribute[interface_name] = extended_attribut es
272 parent = get_parent_interface(idl_file_contents) 284 parent = get_parent_interface(idl_file_contents)
273 if parent: 285 if parent:
274 parent_interface[interface_name] = parent 286 parent_interface[interface_name] = parent
275 interface_extended_attribute[interface_name] = extended_attributes 287 interface_extended_attribute[interface_name] = extended_attribut es
276 288
277 # Add constructors on global objects to partial interfaces 289 # Add constructors on global objects to partial interfaces
278 for global_object, filename in global_constructors_filenames.iteritems(): 290 for global_object, filename in global_constructors_filenames.iteritems():
279 if global_object in interfaces: 291 if global_object in interfaces:
280 partial_interface_files[global_object].append(filename) 292 partial_interface_files[global_object].append(filename)
281 293
282 # Interfaces that are implemented by another interface do not have 294 # Interfaces that are implemented by another interface do not have
283 # their own bindings generated, as this would be redundant with the 295 # their own bindings generated, as this would be redundant with the
284 # actual implementation. 296 # actual implementation.
285 for implemented_interface in implemented_somewhere: 297 for implemented_interface in implemented_somewhere:
286 full_path = interface_name_to_idl_file[implemented_interface] 298 full_path = interface_name_to_idl_file[implemented_interface]
287 del dependencies[full_path] 299 del dependencies[full_path]
288 300
289 # An IDL file's dependencies are partial interface files that extend it, 301 # An IDL file's dependencies are partial interface files that extend it,
Nils Barth (inactive) 2013/09/17 02:23:35 If you put this loop (and the global constructors
290 # and files for other interfaces that this interfaces implements. 302 # and files for other interfaces that this interfaces implements.
291 for idl_file_path in dependencies.iterkeys(): 303 for idl_file_path in dependencies.iterkeys():
304 binding_derived_sources[idl_file_path] = []
292 interface_name, _ = os.path.splitext(os.path.basename(idl_file_path)) 305 interface_name, _ = os.path.splitext(os.path.basename(idl_file_path))
293 implemented_interfaces = implements_interfaces[interface_name] 306 implemented_interfaces = implements_interfaces[interface_name]
294 try: 307 try:
295 interface_paths = map(lambda x: interface_name_to_idl_file[x], imple mented_interfaces) 308 interface_paths = map(lambda x: interface_name_to_idl_file[x], imple mented_interfaces)
296 except KeyError as key_name: 309 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) 310 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) 311 dependencies[idl_file_path] = sorted(partial_interface_files[interface_n ame] + interface_paths)
299 312
313 # Remove test suport IDLs for derived_sources_all_in_one
Nils Barth (inactive) 2013/09/17 02:23:35 As above, this is hacky. (Also, "suport" -> "suppo
314 for idl_file_name in testing_idl_files:
315 full_path = os.path.realpath(idl_file_name)
316 if full_path in binding_derived_sources.keys():
317 del binding_derived_sources[full_path]
318
300 # Generate event names for all interfaces that inherit from Event, 319 # Generate event names for all interfaces that inherit from Event,
301 # including Event itself. 320 # including Event itself.
302 event_names = {} 321 event_names = {}
303 if 'Event' in interfaces: 322 if 'Event' in interfaces:
304 event_names[interface_name_to_idl_file['Event']] = interface_extended_at tribute['Event'] 323 event_names[interface_name_to_idl_file['Event']] = interface_extended_at tribute['Event']
305 for interface, parent in parent_interface.iteritems(): 324 for interface, parent in parent_interface.iteritems():
306 while parent in parent_interface: 325 while parent in parent_interface:
307 parent = parent_interface[parent] 326 parent = parent_interface[parent]
308 if parent == 'Event': 327 if parent == 'Event':
309 event_names[interface_name_to_idl_file[interface]] = interface_exten ded_attribute[interface] 328 event_names[interface_name_to_idl_file[interface]] = interface_exten ded_attribute[interface]
310 329
311 return interfaces, dependencies, global_constructors, event_names 330 return interfaces, binding_derived_sources, dependencies, global_constructor s, event_names
312 331
313 332
314 def write_dependency_file(filename, dependencies, only_if_changed): 333 def write_dependency_file(filename, dependencies, only_if_changed):
315 """Write the interface dependencies file. 334 """Write the interface dependencies file.
316 335
317 The format is as follows: 336 The format is as follows:
318 337
319 Document.idl P.idl 338 Document.idl P.idl
320 Event.idl 339 Event.idl
321 Window.idl Q.idl R.idl S.idl 340 Window.idl Q.idl R.idl S.idl
(...skipping 11 matching lines...) Expand all
333 for idl_file, dependency_files in sorted(dependencies.iteritems())] 352 for idl_file, dependency_files in sorted(dependencies.iteritems())]
334 write_file(lines, filename, only_if_changed) 353 write_file(lines, filename, only_if_changed)
335 354
336 355
337 def main(): 356 def main():
338 options = parse_options() 357 options = parse_options()
339 idl_files = [] 358 idl_files = []
340 with open(options.idl_files_list) as idl_files_list_file: 359 with open(options.idl_files_list) as idl_files_list_file:
341 for line in idl_files_list_file: 360 for line in idl_files_list_file:
342 idl_files.append(string.rstrip(line, '\n')) 361 idl_files.append(string.rstrip(line, '\n'))
362 testing_idl_files = []
363 with open(options.testing_idl_files_list) as testing_idl_files_list_file:
364 for line in testing_idl_files_list_file:
365 testing_idl_files.append(string.rstrip(line, '\n'))
343 only_if_changed = options.write_file_only_if_changed 366 only_if_changed = options.write_file_only_if_changed
344 global_constructors_filenames = { 367 global_constructors_filenames = {
345 'Window': options.window_constructors_file, 368 'Window': options.window_constructors_file,
346 'WorkerGlobalScope': options.workerglobalscope_constructors_file, 369 'WorkerGlobalScope': options.workerglobalscope_constructors_file,
347 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_ file, 370 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_ file,
348 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constru ctors_file, 371 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constru ctors_file,
349 } 372 }
350 373
351 interfaces, dependencies, global_constructors, event_names = parse_idl_files (idl_files, global_constructors_filenames) 374 interfaces, binding_derived_sources, dependencies, global_constructors, even t_names = parse_idl_files(idl_files, testing_idl_files, global_constructors_file names)
352 375
353 write_dependency_file(options.interface_dependencies_file, dependencies, onl y_if_changed) 376 write_dependency_file(options.interface_dependencies_file, dependencies, onl y_if_changed)
377 write_dependency_file(options.binding_derived_source_file, binding_derived_s ources, only_if_changed)
354 for interface_name, filename in global_constructors_filenames.iteritems(): 378 for interface_name, filename in global_constructors_filenames.iteritems():
355 if interface_name in interfaces: 379 if interface_name in interfaces:
356 generate_global_constructors_partial_interface(interface_name, filen ame, global_constructors[interface_name], only_if_changed) 380 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) 381 generate_event_names_file(options.event_names_file, event_names, only_if_cha nged)
358 382
359 383
360 if __name__ == '__main__': 384 if __name__ == '__main__':
361 main() 385 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698