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

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

Issue 1257613003: bindings: Supports inheritance of [Unforgeable] attributes as accessor-type properties. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Made inherit_unforgeable_attributes more robust. Created 5 years, 4 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 | Annotate | Revision Log
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 29 matching lines...) Expand all
40 40
41 Design doc: http://www.chromium.org/developers/design-documents/idl-build 41 Design doc: http://www.chromium.org/developers/design-documents/idl-build
42 """ 42 """
43 43
44 from collections import defaultdict 44 from collections import defaultdict
45 import optparse 45 import optparse
46 import os 46 import os
47 import posixpath 47 import posixpath
48 import sys 48 import sys
49 49
50 from idl_compiler import idl_filename_to_interface_name
50 from idl_definitions import Visitor 51 from idl_definitions import Visitor
51 from idl_reader import IdlReader 52 from idl_reader import IdlReader
52 from utilities import get_file_contents, read_file_to_list, idl_filename_to_inte rface_name, idl_filename_to_component, write_pickle_file, get_interface_extended _attributes_from_idl, is_callback_interface_from_idl 53 from utilities import get_file_contents, read_file_to_list, idl_filename_to_inte rface_name, idl_filename_to_component, write_pickle_file, get_interface_extended _attributes_from_idl, is_callback_interface_from_idl, merge_dict_recursively
53 54
54 module_path = os.path.dirname(__file__) 55 module_path = os.path.dirname(__file__)
55 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir)) 56 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir))
56 57
57 58
58 class IdlBadFilenameError(Exception): 59 class IdlBadFilenameError(Exception):
59 """Raised if an IDL filename disagrees with the interface name in the file." "" 60 """Raised if an IDL filename disagrees with the interface name in the file." ""
60 pass 61 pass
61 62
62 63
(...skipping 30 matching lines...) Expand all
93 94
94 def include_path(idl_filename, implemented_as=None): 95 def include_path(idl_filename, implemented_as=None):
95 """Returns relative path to header file in POSIX format; used in includes. 96 """Returns relative path to header file in POSIX format; used in includes.
96 97
97 POSIX format is used for consistency of output, so reference tests are 98 POSIX format is used for consistency of output, so reference tests are
98 platform-independent. 99 platform-independent.
99 """ 100 """
100 relative_dir = relative_dir_posix(idl_filename) 101 relative_dir = relative_dir_posix(idl_filename)
101 102
102 # IDL file basename is used even if only a partial interface file 103 # IDL file basename is used even if only a partial interface file
103 idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename)) 104 cpp_class_name = implemented_as or idl_filename_to_interface_name(idl_filena me)
104 cpp_class_name = implemented_as or idl_file_basename
105 105
106 return posixpath.join(relative_dir, cpp_class_name + '.h') 106 return posixpath.join(relative_dir, cpp_class_name + '.h')
107 107
108 108
109 def get_implements_from_definitions(definitions, definition_name): 109 def get_implements_from_definitions(definitions, definition_name):
110 left_interfaces = [] 110 left_interfaces = []
111 right_interfaces = [] 111 right_interfaces = []
112 for implement in definitions.implements: 112 for implement in definitions.implements:
113 if definition_name == implement.left_interface: 113 if definition_name == implement.left_interface:
114 right_interfaces.append(implement.right_interface) 114 right_interfaces.append(implement.right_interface)
115 elif definition_name == implement.right_interface: 115 elif definition_name == implement.right_interface:
116 left_interfaces.append(implement.left_interface) 116 left_interfaces.append(implement.left_interface)
117 else: 117 else:
118 raise IdlBadFilenameError( 118 raise IdlBadFilenameError(
119 'implements statement found in unrelated IDL file.\n' 119 'implements statement found in unrelated IDL file.\n'
120 'Statement is:\n' 120 'Statement is:\n'
121 ' %s implements %s;\n' 121 ' %s implements %s;\n'
122 'but filename is unrelated "%s.idl"' % 122 'but filename is unrelated "%s.idl"' %
123 (implement.left_interface, implement.right_interface, definition _name)) 123 (implement.left_interface, implement.right_interface, definition _name))
124 return left_interfaces, right_interfaces 124 return left_interfaces, right_interfaces
125 125
126 126
127 def get_put_forward_interfaces_from_definition(definition): 127 def get_put_forward_interfaces_from_definition(definition):
128 return sorted(set(attribute.idl_type.base_type 128 return sorted(set(attribute.idl_type.base_type
129 for attribute in definition.attributes 129 for attribute in definition.attributes
130 if 'PutForwards' in attribute.extended_attributes)) 130 if 'PutForwards' in attribute.extended_attributes))
131 131
132 132
133 def get_unforgeable_attributes_from_definition(definition):
134 if 'Unforgeable' in definition.extended_attributes:
135 return sorted(definition.attributes)
136 return sorted(attribute for attribute in definition.attributes
137 if 'Unforgeable' in attribute.extended_attributes)
138
139
133 def collect_union_types_from_definitions(definitions): 140 def collect_union_types_from_definitions(definitions):
134 """Traverse definitions and collect all union types.""" 141 """Traverse definitions and collect all union types."""
135 class UnionTypeCollector(Visitor): 142 class UnionTypeCollector(Visitor):
136 def collect(self, definitions): 143 def collect(self, definitions):
137 self._union_types = set() 144 self._union_types = set()
138 definitions.accept(self) 145 definitions.accept(self)
139 return self._union_types 146 return self._union_types
140 147
141 def visit_typed_object(self, typed_object): 148 def visit_typed_object(self, typed_object):
142 for attribute_name in typed_object.idl_type_attributes: 149 for attribute_name in typed_object.idl_type_attributes:
(...skipping 22 matching lines...) Expand all
165 172
166 def add_paths_to_partials_dict(self, partial_interface_name, full_path, 173 def add_paths_to_partials_dict(self, partial_interface_name, full_path,
167 include_paths): 174 include_paths):
168 paths_dict = self.partial_interface_files[partial_interface_name] 175 paths_dict = self.partial_interface_files[partial_interface_name]
169 paths_dict['full_paths'].append(full_path) 176 paths_dict['full_paths'].append(full_path)
170 paths_dict['include_paths'].extend(include_paths) 177 paths_dict['include_paths'].extend(include_paths)
171 178
172 def collect_info(self, idl_filename): 179 def collect_info(self, idl_filename):
173 """Reads an idl file and collects information which is required by the 180 """Reads an idl file and collects information which is required by the
174 binding code generation.""" 181 binding code generation."""
182 def collect_unforgeable_attributes(definition, idl_filename):
183 """Collects [Unforgeable] attributes so that we can define them on
184 sub-interfaces later. The resulting structure is as follows.
185 interfaces_info[interface_name] = {
186 'unforgeable_attributes': {
187 'core': [IdlAttribute, ...],
188 'modules': [IdlAttribute, ...],
189 },
190 ...
191 }
192 """
193 interface_info = {}
194 unforgeable_attributes = get_unforgeable_attributes_from_definition( definition)
195 if not unforgeable_attributes:
196 return interface_info
197
198 if definition.is_partial:
199 interface_basename = idl_filename_to_interface_name(idl_filename )
200 # TODO(yukishiino): [PartialInterfaceImplementedAs] is treated
201 # in interface_dependency_resolver.transfer_extended_attributes.
202 # Come up with a better way to keep them consistent.
203 for attr in unforgeable_attributes:
204 attr.extended_attributes['PartialInterfaceImplementedAs'] = definition.extended_attributes.get('ImplementedAs', interface_basename)
205 component = idl_filename_to_component(idl_filename)
206 interface_info['unforgeable_attributes'] = {}
207 interface_info['unforgeable_attributes'][component] = unforgeable_at tributes
208 return interface_info
209
175 definitions = self.reader.read_idl_file(idl_filename) 210 definitions = self.reader.read_idl_file(idl_filename)
176 211
177 this_union_types = collect_union_types_from_definitions(definitions) 212 this_union_types = collect_union_types_from_definitions(definitions)
178 self.union_types.update(this_union_types) 213 self.union_types.update(this_union_types)
179 self.typedefs.update(definitions.typedefs) 214 self.typedefs.update(definitions.typedefs)
180 # Check enum duplication. 215 # Check enum duplication.
181 for enum_name in definitions.enumerations.keys(): 216 for enum_name in definitions.enumerations.keys():
182 for defined_enum in self.enumerations: 217 for defined_enum in self.enumerations:
183 if defined_enum.name == enum_name: 218 if defined_enum.name == enum_name:
184 raise Exception('Enumeration %s has multiple definitions' % enum_name) 219 raise Exception('Enumeration %s has multiple definitions' % enum_name)
(...skipping 16 matching lines...) Expand all
201 elif definitions.dictionaries: 236 elif definitions.dictionaries:
202 definition = next(definitions.dictionaries.itervalues()) 237 definition = next(definitions.dictionaries.itervalues())
203 interface_info = { 238 interface_info = {
204 'is_callback_interface': False, 239 'is_callback_interface': False,
205 'is_dictionary': True, 240 'is_dictionary': True,
206 'referenced_interfaces': None, 241 'referenced_interfaces': None,
207 } 242 }
208 else: 243 else:
209 return 244 return
210 245
246 if definition.name not in self.interfaces_info:
247 self.interfaces_info[definition.name] = {}
248
249 # Remember [Unforgeable] attributes.
250 if definitions.interfaces:
251 merge_dict_recursively(self.interfaces_info[definition.name],
252 collect_unforgeable_attributes(definition, id l_filename))
253
254 component = idl_filename_to_component(idl_filename)
211 extended_attributes = definition.extended_attributes 255 extended_attributes = definition.extended_attributes
212 implemented_as = extended_attributes.get('ImplementedAs') 256 implemented_as = extended_attributes.get('ImplementedAs')
213 full_path = os.path.realpath(idl_filename) 257 full_path = os.path.realpath(idl_filename)
214 this_include_path = None if 'NoImplHeader' in extended_attributes else i nclude_path(idl_filename, implemented_as) 258 this_include_path = None if 'NoImplHeader' in extended_attributes else i nclude_path(idl_filename, implemented_as)
215 if definition.is_partial: 259 if definition.is_partial:
216 # We don't create interface_info for partial interfaces, but 260 # We don't create interface_info for partial interfaces, but
217 # adds paths to another dict. 261 # adds paths to another dict.
218 partial_include_paths = [] 262 partial_include_paths = []
219 if this_include_path: 263 if this_include_path:
220 partial_include_paths.append(this_include_path) 264 partial_include_paths.append(this_include_path)
221 if this_union_types: 265 if this_union_types:
222 component = idl_filename_to_component(idl_filename)
223 partial_include_paths.append( 266 partial_include_paths.append(
224 'bindings/%s/v8/UnionTypes%s.h' % (component, component.capi talize())) 267 'bindings/%s/v8/UnionTypes%s.h' % (component, component.capi talize()))
225 self.add_paths_to_partials_dict(definition.name, full_path, partial_ include_paths) 268 self.add_paths_to_partials_dict(definition.name, full_path, partial_ include_paths)
269 # Collects C++ header paths which should be included from generated
270 # .cpp files. The resulting structure is as follows.
271 # interfaces_info[interface_name] = {
272 # 'cpp_includes': {
273 # 'core': set(['core/foo/Foo.h', ...]),
274 # 'modules': set(['modules/bar/Bar.h', ...]),
275 # },
276 # ...
277 # }
278 if this_include_path:
279 merge_dict_recursively(
280 self.interfaces_info[definition.name],
281 {'cpp_includes': {component: set([this_include_path])}})
226 return 282 return
227 283
228 # 'implements' statements can be included in either the file for the 284 # 'implements' statements can be included in either the file for the
229 # implement*ing* interface (lhs of 'implements') or implement*ed* interf ace 285 # implement*ing* interface (lhs of 'implements') or implement*ed* interf ace
230 # (rhs of 'implements'). Store both for now, then merge to implement*ing * 286 # (rhs of 'implements'). Store both for now, then merge to implement*ing *
231 # interface later. 287 # interface later.
232 left_interfaces, right_interfaces = get_implements_from_definitions( 288 left_interfaces, right_interfaces = get_implements_from_definitions(
233 definitions, definition.name) 289 definitions, definition.name)
234 290
235 interface_info.update({ 291 interface_info.update({
236 'extended_attributes': extended_attributes, 292 'extended_attributes': extended_attributes,
237 'full_path': full_path, 293 'full_path': full_path,
238 'has_union_types': bool(this_union_types), 294 'has_union_types': bool(this_union_types),
239 'implemented_as': implemented_as, 295 'implemented_as': implemented_as,
240 'implemented_by_interfaces': left_interfaces, 296 'implemented_by_interfaces': left_interfaces,
241 'implements_interfaces': right_interfaces, 297 'implements_interfaces': right_interfaces,
242 'include_path': this_include_path, 298 'include_path': this_include_path,
243 # FIXME: temporary private field, while removing old treatement of 299 # FIXME: temporary private field, while removing old treatement of
244 # 'implements': http://crbug.com/360435 300 # 'implements': http://crbug.com/360435
245 'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterfa ce' in extended_attributes, 301 'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterfa ce' in extended_attributes,
246 'parent': definition.parent, 302 'parent': definition.parent,
247 'relative_dir': relative_dir_posix(idl_filename), 303 'relative_dir': relative_dir_posix(idl_filename),
248 }) 304 })
249 self.interfaces_info[definition.name] = interface_info 305 merge_dict_recursively(self.interfaces_info[definition.name], interface_ info)
250 306
251 def get_info_as_dict(self): 307 def get_info_as_dict(self):
252 """Returns info packaged as a dict.""" 308 """Returns info packaged as a dict."""
253 return { 309 return {
254 'interfaces_info': self.interfaces_info, 310 'interfaces_info': self.interfaces_info,
255 # Can't pickle defaultdict, convert to dict 311 # Can't pickle defaultdict, convert to dict
256 # FIXME: this should be included in get_component_info. 312 # FIXME: this should be included in get_component_info.
257 'partial_interface_files': dict(self.partial_interface_files), 313 'partial_interface_files': dict(self.partial_interface_files),
258 } 314 }
259 315
(...skipping 29 matching lines...) Expand all
289 345
290 write_pickle_file(options.interfaces_info_file, 346 write_pickle_file(options.interfaces_info_file,
291 info_collector.get_info_as_dict(), 347 info_collector.get_info_as_dict(),
292 options.write_file_only_if_changed) 348 options.write_file_only_if_changed)
293 write_pickle_file(options.component_info_file, 349 write_pickle_file(options.component_info_file,
294 info_collector.get_component_info_as_dict(), 350 info_collector.get_component_info_as_dict(),
295 options.write_file_only_if_changed) 351 options.write_file_only_if_changed)
296 352
297 if __name__ == '__main__': 353 if __name__ == '__main__':
298 sys.exit(main()) 354 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698