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

Side by Side Diff: third_party/WebKit/Source/bindings/scripts/code_generator_v8.py

Issue 1974143002: Revert of Generate separate files for union type containers (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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 # Copyright (C) 2013 Google Inc. All rights reserved. 1 # Copyright (C) 2013 Google Inc. All rights reserved.
2 # 2 #
3 # Redistribution and use in source and binary forms, with or without 3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are 4 # modification, are permitted provided that the following conditions are
5 # met: 5 # met:
6 # 6 #
7 # * Redistributions of source code must retain the above copyright 7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer. 8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above 9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer 10 # copyright notice, this list of conditions and the following disclaimer
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 IdlType.set_enums(info_provider.enumerations) 122 IdlType.set_enums(info_provider.enumerations)
123 IdlType.set_implemented_as_interfaces(interfaces_info['implemented_as_interf aces']) 123 IdlType.set_implemented_as_interfaces(interfaces_info['implemented_as_interf aces'])
124 IdlType.set_garbage_collected_types(interfaces_info['garbage_collected_inter faces']) 124 IdlType.set_garbage_collected_types(interfaces_info['garbage_collected_inter faces'])
125 v8_types.set_component_dirs(interfaces_info['component_dirs']) 125 v8_types.set_component_dirs(interfaces_info['component_dirs'])
126 126
127 127
128 def should_generate_code(definitions): 128 def should_generate_code(definitions):
129 return definitions.interfaces or definitions.dictionaries 129 return definitions.interfaces or definitions.dictionaries
130 130
131 131
132 def depending_union_type_name(idl_type): 132 def depends_on_union_types(idl_type):
133 """Returns the union type name if the given idl_type depends on a 133 """Returns true when a given idl_type depends on union containers
134 union type. 134 directly.
135 """ 135 """
136 def find_base_type(current_type): 136 if idl_type.is_union_type:
137 if current_type.is_array_or_sequence_type: 137 return True
138 return find_base_type(current_type.element_type) 138 if idl_type.is_array_or_sequence_type:
139 if current_type.is_nullable: 139 return idl_type.element_type.is_union_type
140 return find_base_type(current_type.inner_type) 140 return False
141 return current_type
142 base_type = find_base_type(idl_type)
143 if base_type.is_union_type:
144 return base_type.name
145 return None
146 141
147 142
148 class TypedefResolver(Visitor): 143 class TypedefResolver(Visitor):
149 def __init__(self, info_provider): 144 def __init__(self, info_provider):
150 self.info_provider = info_provider 145 self.info_provider = info_provider
151 146
152 def resolve(self, definitions, definition_name): 147 def resolve(self, definitions, definition_name):
153 """Traverse definitions and resolves typedefs with the actual types.""" 148 """Traverse definitions and resolves typedefs with the actual types."""
154 self.typedefs = {} 149 self.typedefs = {}
155 for name, typedef in self.info_provider.typedefs.iteritems(): 150 for name, typedef in self.info_provider.typedefs.iteritems():
156 self.typedefs[name] = typedef.idl_type 151 self.typedefs[name] = typedef.idl_type
157 self.additional_header_includes = set() 152 self.additional_includes = set()
158 definitions.accept(self) 153 definitions.accept(self)
159 self._update_dependencies_include_paths(definition_name) 154 self._update_dependencies_include_paths(definition_name)
160 155
161 def _update_dependencies_include_paths(self, definition_name): 156 def _update_dependencies_include_paths(self, definition_name):
162 interface_info = self.info_provider.interfaces_info[definition_name] 157 interface_info = self.info_provider.interfaces_info[definition_name]
163 interface_info['additional_header_includes'] = set( 158 dependencies_include_paths = interface_info['dependencies_include_paths' ]
164 self.additional_header_includes) 159 for include_path in self.additional_includes:
160 if include_path not in dependencies_include_paths:
161 dependencies_include_paths.append(include_path)
165 162
166 def _resolve_typedefs(self, typed_object): 163 def _resolve_typedefs(self, typed_object):
167 """Resolve typedefs to actual types in the object.""" 164 """Resolve typedefs to actual types in the object."""
168 for attribute_name in typed_object.idl_type_attributes: 165 for attribute_name in typed_object.idl_type_attributes:
169 try: 166 try:
170 idl_type = getattr(typed_object, attribute_name) 167 idl_type = getattr(typed_object, attribute_name)
171 except AttributeError: 168 except AttributeError:
172 continue 169 continue
173 if not idl_type: 170 if not idl_type:
174 continue 171 continue
175 resolved_idl_type = idl_type.resolve_typedefs(self.typedefs) 172 resolved_idl_type = idl_type.resolve_typedefs(self.typedefs)
176 # TODO(bashi): Dependency resolution shouldn't happen here. 173 if depends_on_union_types(resolved_idl_type):
177 # Move this into includes_for_type() families. 174 self.additional_includes.add(
178 union_type_name = depending_union_type_name(resolved_idl_type) 175 self.info_provider.include_path_for_union_types)
179 if union_type_name:
180 self.additional_header_includes.add(
181 self.info_provider.include_path_for_union_types(
182 union_type_name))
183 # Need to re-assign the attribute, not just mutate idl_type, since 176 # Need to re-assign the attribute, not just mutate idl_type, since
184 # type(idl_type) may change. 177 # type(idl_type) may change.
185 setattr(typed_object, attribute_name, resolved_idl_type) 178 setattr(typed_object, attribute_name, resolved_idl_type)
186 179
187 def visit_typed_object(self, typed_object): 180 def visit_typed_object(self, typed_object):
188 self._resolve_typedefs(typed_object) 181 self._resolve_typedefs(typed_object)
189 182
190 183
191 class CodeGeneratorBase(object): 184 class CodeGeneratorBase(object):
192 """Base class for v8 bindings generator and IDL dictionary impl generator""" 185 """Base class for v8 bindings generator and IDL dictionary impl generator"""
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 template_context = interface_context(interface) 258 template_context = interface_context(interface)
266 includes.update(interface_info.get('cpp_includes', {}).get(component, se t())) 259 includes.update(interface_info.get('cpp_includes', {}).get(component, se t()))
267 if not interface.is_partial and not is_testing_target(full_path): 260 if not interface.is_partial and not is_testing_target(full_path):
268 template_context['header_includes'].add(self.info_provider.include_p ath_for_export) 261 template_context['header_includes'].add(self.info_provider.include_p ath_for_export)
269 template_context['exported'] = self.info_provider.specifier_for_expo rt 262 template_context['exported'] = self.info_provider.specifier_for_expo rt
270 # Add the include for interface itself 263 # Add the include for interface itself
271 if IdlType(interface_name).is_typed_array: 264 if IdlType(interface_name).is_typed_array:
272 template_context['header_includes'].add('core/dom/DOMTypedArray.h') 265 template_context['header_includes'].add('core/dom/DOMTypedArray.h')
273 elif interface_info['include_path']: 266 elif interface_info['include_path']:
274 template_context['header_includes'].add(interface_info['include_path ']) 267 template_context['header_includes'].add(interface_info['include_path '])
275 template_context['header_includes'].update( 268
276 interface_info.get('additional_header_includes', []))
277 header_template = self.jinja_env.get_template(header_template_filename) 269 header_template = self.jinja_env.get_template(header_template_filename)
278 cpp_template = self.jinja_env.get_template(cpp_template_filename) 270 cpp_template = self.jinja_env.get_template(cpp_template_filename)
279 header_text, cpp_text = render_template( 271 header_text, cpp_text = render_template(
280 include_paths, header_template, cpp_template, template_context, 272 include_paths, header_template, cpp_template, template_context,
281 component) 273 component)
282 header_path, cpp_path = self.output_paths(interface_name) 274 header_path, cpp_path = self.output_paths(interface_name)
283 return ( 275 return (
284 (header_path, header_text), 276 (header_path, header_text),
285 (cpp_path, cpp_text), 277 (cpp_path, cpp_text),
286 ) 278 )
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 if not definition_name in definitions.dictionaries: 316 if not definition_name in definitions.dictionaries:
325 raise ValueError('%s is not an IDL dictionary') 317 raise ValueError('%s is not an IDL dictionary')
326 interfaces_info = self.info_provider.interfaces_info 318 interfaces_info = self.info_provider.interfaces_info
327 dictionary = definitions.dictionaries[definition_name] 319 dictionary = definitions.dictionaries[definition_name]
328 interface_info = interfaces_info[definition_name] 320 interface_info = interfaces_info[definition_name]
329 header_template = self.jinja_env.get_template('dictionary_impl.h') 321 header_template = self.jinja_env.get_template('dictionary_impl.h')
330 cpp_template = self.jinja_env.get_template('dictionary_impl.cpp') 322 cpp_template = self.jinja_env.get_template('dictionary_impl.cpp')
331 template_context = v8_dictionary.dictionary_impl_context( 323 template_context = v8_dictionary.dictionary_impl_context(
332 dictionary, interfaces_info) 324 dictionary, interfaces_info)
333 include_paths = interface_info.get('dependencies_include_paths') 325 include_paths = interface_info.get('dependencies_include_paths')
326 # Add union containers header file to header_includes rather than
327 # cpp file so that union containers can be used in dictionary headers.
328 union_container_headers = [header for header in include_paths
329 if header.find('UnionTypes') > 0]
330 include_paths = [header for header in include_paths
331 if header not in union_container_headers]
332 template_context['header_includes'].update(union_container_headers)
334 if not is_testing_target(interface_info.get('full_path')): 333 if not is_testing_target(interface_info.get('full_path')):
335 template_context['exported'] = self.info_provider.specifier_for_expo rt 334 template_context['exported'] = self.info_provider.specifier_for_expo rt
336 template_context['header_includes'].add(self.info_provider.include_p ath_for_export) 335 template_context['header_includes'].add(self.info_provider.include_p ath_for_export)
337 template_context['header_includes'].update(
338 interface_info.get('additional_header_includes', []))
339 header_text, cpp_text = render_template( 336 header_text, cpp_text = render_template(
340 include_paths, header_template, cpp_template, template_context) 337 include_paths, header_template, cpp_template, template_context)
341 header_path, cpp_path = self.output_paths( 338 header_path, cpp_path = self.output_paths(
342 cpp_name(dictionary), interface_info) 339 cpp_name(dictionary), interface_info)
343 return ( 340 return (
344 (header_path, header_text), 341 (header_path, header_text),
345 (cpp_path, cpp_text), 342 (cpp_path, cpp_text),
346 ) 343 )
347 344
348 345
349 class CodeGeneratorUnionType(object): 346 class CodeGeneratorUnionType(object):
350 """Generates union type container classes. 347 """Generates union type container classes.
351 This generator is different from CodeGeneratorV8 and 348 This generator is different from CodeGeneratorV8 and
352 CodeGeneratorDictionaryImpl. It assumes that all union types are already 349 CodeGeneratorDictionaryImpl. It assumes that all union types are already
353 collected. It doesn't process idl files directly. 350 collected. It doesn't process idl files directly.
354 """ 351 """
355 def __init__(self, info_provider, cache_dir, output_dir, target_component): 352 def __init__(self, info_provider, cache_dir, output_dir, target_component):
356 self.info_provider = info_provider 353 self.info_provider = info_provider
357 self.jinja_env = initialize_jinja_env(cache_dir) 354 self.jinja_env = initialize_jinja_env(cache_dir)
358 self.output_dir = output_dir 355 self.output_dir = output_dir
359 self.target_component = target_component 356 self.target_component = target_component
360 set_global_type_info(info_provider) 357 set_global_type_info(info_provider)
361 358
362 def _generate_container_code(self, union_type): 359 def generate_code(self):
363 header_template = self.jinja_env.get_template('union_container.h') 360 union_types = self.info_provider.union_types
364 cpp_template = self.jinja_env.get_template('union_container.cpp') 361 if not union_types:
365 template_context = v8_union.container_context( 362 return ()
366 union_type, self.info_provider.interfaces_info) 363 header_template = self.jinja_env.get_template('union.h')
367 template_context['header_includes'].append( 364 cpp_template = self.jinja_env.get_template('union.cpp')
368 self.info_provider.include_path_for_export) 365 template_context = v8_union.union_context(
366 union_types, self.info_provider.interfaces_info)
367 template_context['code_generator'] = module_pyname
368 capitalized_component = self.target_component.capitalize()
369 template_context['exported'] = self.info_provider.specifier_for_export
370 template_context['header_filename'] = 'bindings/%s/v8/UnionTypes%s.h' % (
371 self.target_component, capitalized_component)
372 template_context['macro_guard'] = 'UnionType%s_h' % capitalized_componen t
373 additional_header_includes = [self.info_provider.include_path_for_export ]
374
375 # Add UnionTypesCore.h as a dependency when we generate modules union ty pes
376 # because we only generate union type containers which are used by both
377 # core and modules in UnionTypesCore.h.
378 # FIXME: This is an ad hoc workaround and we need a general way to
379 # handle core <-> modules dependency.
380 if self.target_component == 'modules':
381 additional_header_includes.append(
382 'bindings/core/v8/UnionTypesCore.h')
383
369 template_context['header_includes'] = normalize_and_sort_includes( 384 template_context['header_includes'] = normalize_and_sort_includes(
370 template_context['header_includes']) 385 template_context['header_includes'] + additional_header_includes)
371 template_context['code_generator'] = module_pyname 386
372 template_context['exported'] = self.info_provider.specifier_for_export
373 header_text = header_template.render(template_context) 387 header_text = header_template.render(template_context)
374 cpp_text = cpp_template.render(template_context) 388 cpp_text = cpp_template.render(template_context)
375 name = union_type.cpp_type 389 header_path = posixpath.join(self.output_dir,
376 header_path = posixpath.join(self.output_dir, '%s.h' % name) 390 'UnionTypes%s.h' % capitalized_component)
377 cpp_path = posixpath.join(self.output_dir, '%s.cpp' % name) 391 cpp_path = posixpath.join(self.output_dir,
392 'UnionTypes%s.cpp' % capitalized_component)
378 return ( 393 return (
379 (header_path, header_text), 394 (header_path, header_text),
380 (cpp_path, cpp_text), 395 (cpp_path, cpp_text),
381 ) 396 )
382 397
383 def _get_union_types_for_containers(self):
384 union_types = self.info_provider.union_types
385 if not union_types:
386 return None
387 # For container classes we strip nullable wrappers. For example,
388 # both (A or B)? and (A? or B) will become AOrB. This should be OK
389 # because container classes can handle null and it seems that
390 # distinguishing (A or B)? and (A? or B) doesn't make sense.
391 container_cpp_types = set()
392 union_types_for_containers = set()
393 for union_type in union_types:
394 cpp_type = union_type.cpp_type
395 if cpp_type not in container_cpp_types:
396 union_types_for_containers.add(union_type)
397 container_cpp_types.add(cpp_type)
398 return union_types_for_containers
399
400 def generate_code(self):
401 union_types = self._get_union_types_for_containers()
402 if not union_types:
403 return ()
404 outputs = set()
405 for union_type in union_types:
406 outputs.update(self._generate_container_code(union_type))
407 return outputs
408
409 398
410 def initialize_jinja_env(cache_dir): 399 def initialize_jinja_env(cache_dir):
411 jinja_env = jinja2.Environment( 400 jinja_env = jinja2.Environment(
412 loader=jinja2.FileSystemLoader(templates_dir), 401 loader=jinja2.FileSystemLoader(templates_dir),
413 # Bytecode cache is not concurrency-safe unless pre-cached: 402 # Bytecode cache is not concurrency-safe unless pre-cached:
414 # if pre-cached this is read-only, but writing creates a race condition. 403 # if pre-cached this is read-only, but writing creates a race condition.
415 bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir), 404 bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
416 keep_trailing_newline=True, # newline-terminate generated files 405 keep_trailing_newline=True, # newline-terminate generated files
417 lstrip_blocks=True, # so can indent control flow tags 406 lstrip_blocks=True, # so can indent control flow tags
418 trim_blocks=True) 407 trim_blocks=True)
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 456
468 # Create a dummy file as output for the build system, 457 # Create a dummy file as output for the build system,
469 # since filenames of individual cache files are unpredictable and opaque 458 # since filenames of individual cache files are unpredictable and opaque
470 # (they are hashes of the template path, which varies based on environment) 459 # (they are hashes of the template path, which varies based on environment)
471 with open(dummy_filename, 'w') as dummy_file: 460 with open(dummy_filename, 'w') as dummy_file:
472 pass # |open| creates or touches the file 461 pass # |open| creates or touches the file
473 462
474 463
475 if __name__ == '__main__': 464 if __name__ == '__main__':
476 sys.exit(main(sys.argv)) 465 sys.exit(main(sys.argv))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698