OLD | NEW |
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 12 matching lines...) Expand all Loading... |
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 | 30 |
31 import optparse | 31 import optparse |
32 import os | 32 import os |
33 import cPickle as pickle | |
34 import posixpath | 33 import posixpath |
35 import re | 34 |
36 import string | 35 from utilities import get_file_contents, write_file, write_pickle_file, get_inte
rface_extended_attributes_from_idl, is_callback_interface_from_idl, get_partial_
interface_name_from_idl, get_implemented_interfaces_from_idl, get_parent_interfa
ce, get_put_forward_interfaces_from_idl |
37 | 36 |
38 module_path = os.path.dirname(__file__) | 37 module_path = os.path.dirname(__file__) |
39 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir)) | 38 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir)) |
40 | 39 |
41 INHERITED_EXTENDED_ATTRIBUTES = set([ | 40 INHERITED_EXTENDED_ATTRIBUTES = set([ |
42 'ActiveDOMObject', | 41 'ActiveDOMObject', |
43 'DependentLifetime', | 42 'DependentLifetime', |
44 'WillBeGarbageCollected', | 43 'WillBeGarbageCollected', |
45 ]) | 44 ]) |
46 | 45 |
47 | 46 |
48 # interfaces_info is *exported* (in a pickle), and should only contain data | 47 # interfaces_info is *exported* (in a pickle), and should only contain data |
49 # about an interface that contains paths or is needed by *other* interfaces, | 48 # about an interface that contains paths or is needed by *other* interfaces, |
50 # i.e., file layout data (to abstract the compiler from file paths) or | 49 # i.e., file layout data (to abstract the compiler from file paths) or |
51 # public data (to avoid having to read other interfaces unnecessarily). | 50 # public data (to avoid having to read other interfaces unnecessarily). |
52 # It should *not* contain full information about an interface (e.g., all | 51 # It should *not* contain full information about an interface (e.g., all |
53 # extended attributes), as this would cause unnecessary rebuilds. | 52 # extended attributes), as this would cause unnecessary rebuilds. |
54 interfaces_info = {} | 53 interfaces_info = {} |
55 | 54 |
56 # Auxiliary variables (not visible to future build steps) | 55 # Auxiliary variables (not visible to future build steps) |
57 partial_interface_files = {} | 56 partial_interface_files = {} |
58 parent_interfaces = {} | 57 parent_interfaces = {} |
59 extended_attributes_by_interface = {} # interface name -> extended attributes | 58 extended_attributes_by_interface = {} # interface name -> extended attributes |
60 | 59 |
61 | 60 |
62 class IdlBadFilenameError(Exception): | |
63 """Raised if an IDL filename disagrees with the interface name in the file."
"" | |
64 pass | |
65 | |
66 | |
67 class IdlInterfaceFileNotFoundError(Exception): | 61 class IdlInterfaceFileNotFoundError(Exception): |
68 """Raised if the IDL file implementing an interface cannot be found.""" | 62 """Raised if the IDL file implementing an interface cannot be found.""" |
69 pass | 63 pass |
70 | 64 |
71 | 65 |
72 def parse_options(): | 66 def parse_options(): |
73 usage = 'Usage: %prog [options] [generated1.idl]...' | 67 usage = 'Usage: %prog [options] [generated1.idl]...' |
74 parser = optparse.OptionParser(usage=usage) | 68 parser = optparse.OptionParser(usage=usage) |
75 parser.add_option('--event-names-file', help='output file') | 69 parser.add_option('--event-names-file', help='output file') |
76 parser.add_option('--idl-files-list', help='file listing IDL files') | 70 parser.add_option('--idl-files-list', help='file listing IDL files') |
77 parser.add_option('--interface-dependencies-file', help='output file') | 71 parser.add_option('--interface-dependencies-file', help='output file') |
78 parser.add_option('--interfaces-info-file', help='output pickle file') | 72 parser.add_option('--interfaces-info-file', help='output pickle file') |
79 parser.add_option('--window-constructors-file', help='output file') | |
80 parser.add_option('--workerglobalscope-constructors-file', help='output file
') | |
81 parser.add_option('--sharedworkerglobalscope-constructors-file', help='outpu
t file') | |
82 parser.add_option('--dedicatedworkerglobalscope-constructors-file', help='ou
tput file') | |
83 parser.add_option('--serviceworkerglobalscope-constructors-file', help='outp
ut file') | |
84 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') | 73 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') |
85 options, args = parser.parse_args() | 74 options, args = parser.parse_args() |
86 if options.event_names_file is None: | 75 if options.event_names_file is None: |
87 parser.error('Must specify an output file using --event-names-file.') | 76 parser.error('Must specify an output file using --event-names-file.') |
88 if options.interface_dependencies_file is None: | 77 if options.interface_dependencies_file is None: |
89 parser.error('Must specify an output file using --interface-dependencies
-file.') | 78 parser.error('Must specify an output file using --interface-dependencies
-file.') |
90 if options.interfaces_info_file is None: | 79 if options.interfaces_info_file is None: |
91 parser.error('Must specify an output file using --interfaces-info-file.'
) | 80 parser.error('Must specify an output file using --interfaces-info-file.'
) |
92 if options.window_constructors_file is None: | |
93 parser.error('Must specify an output file using --window-constructors-fi
le.') | |
94 if options.workerglobalscope_constructors_file is None: | |
95 parser.error('Must specify an output file using --workerglobalscope-cons
tructors-file.') | |
96 if options.sharedworkerglobalscope_constructors_file is None: | |
97 parser.error('Must specify an output file using --sharedworkerglobalscop
e-constructors-file.') | |
98 if options.dedicatedworkerglobalscope_constructors_file is None: | |
99 parser.error('Must specify an output file using --dedicatedworkerglobals
cope-constructors-file.') | |
100 if options.serviceworkerglobalscope_constructors_file is None: | |
101 parser.error('Must specify an output file using --serviceworkerglobalsco
pe-constructors-file.') | |
102 if options.idl_files_list is None: | 81 if options.idl_files_list is None: |
103 parser.error('Must specify a file listing IDL files using --idl-files-li
st.') | 82 parser.error('Must specify a file listing IDL files using --idl-files-li
st.') |
104 if options.write_file_only_if_changed is None: | 83 if options.write_file_only_if_changed is None: |
105 parser.error('Must specify whether file is only written if changed using
--write-file-only-if-changed.') | 84 parser.error('Must specify whether file is only written if changed using
--write-file-only-if-changed.') |
106 options.write_file_only_if_changed = bool(options.write_file_only_if_changed
) | 85 options.write_file_only_if_changed = bool(options.write_file_only_if_changed
) |
107 return options, args | 86 return options, args |
108 | 87 |
109 | 88 |
110 ################################################################################ | 89 ################################################################################ |
111 # Basic file reading/writing | |
112 ################################################################################ | |
113 | |
114 def get_file_contents(idl_filename): | |
115 with open(idl_filename) as idl_file: | |
116 lines = idl_file.readlines() | |
117 return ''.join(lines) | |
118 | |
119 | |
120 def write_file(new_lines, destination_filename, only_if_changed): | |
121 if only_if_changed and os.path.isfile(destination_filename): | |
122 with open(destination_filename) as destination_file: | |
123 if destination_file.readlines() == new_lines: | |
124 return | |
125 with open(destination_filename, 'w') as destination_file: | |
126 destination_file.write(''.join(new_lines)) | |
127 | |
128 | |
129 def write_pickle_file(pickle_filename, data, only_if_changed): | |
130 if only_if_changed and os.path.isfile(pickle_filename): | |
131 with open(pickle_filename) as pickle_file: | |
132 if pickle.load(pickle_file) == data: | |
133 return | |
134 with open(pickle_filename, 'w') as pickle_file: | |
135 pickle.dump(data, pickle_file) | |
136 | |
137 | |
138 ################################################################################ | |
139 # IDL parsing | |
140 # | |
141 # We use regular expressions for parsing; this is incorrect (Web IDL is not a | |
142 # regular language), but simple and sufficient in practice. | |
143 # Leading and trailing context (e.g. following '{') used to avoid false matches. | |
144 ################################################################################ | |
145 | |
146 def get_partial_interface_name_from_idl(file_contents): | |
147 match = re.search(r'partial\s+interface\s+(\w+)\s*{', file_contents) | |
148 return match and match.group(1) | |
149 | |
150 | |
151 # identifier-A implements identifier-B; | |
152 # http://www.w3.org/TR/WebIDL/#idl-implements-statements | |
153 def get_implemented_interfaces_from_idl(file_contents, interface_name): | |
154 def get_implemented(left_identifier, right_identifier): | |
155 # identifier-A must be the current interface | |
156 if left_identifier != interface_name: | |
157 raise IdlBadFilenameError("Identifier on the left of the 'implements
' statement should be %s in %s.idl, but found %s" % (interface_name, interface_n
ame, left_identifier)) | |
158 return right_identifier | |
159 | |
160 implements_re = (r'^\s*' | |
161 r'(\w+)\s+' | |
162 r'implements\s+' | |
163 r'(\w+)\s*' | |
164 r';') | |
165 implements_matches = re.finditer(implements_re, file_contents, re.MULTILINE) | |
166 implements_pairs = [(match.group(1), match.group(2)) | |
167 for match in implements_matches] | |
168 return [get_implemented(left, right) for left, right in implements_pairs] | |
169 | |
170 | |
171 def is_callback_interface_from_idl(file_contents): | |
172 match = re.search(r'callback\s+interface\s+\w+\s*{', file_contents) | |
173 return bool(match) | |
174 | |
175 | |
176 def get_parent_interface(file_contents): | |
177 match = re.search(r'interface\s+' | |
178 r'\w+\s*' | |
179 r':\s*(\w+)\s*' | |
180 r'{', | |
181 file_contents) | |
182 return match and match.group(1) | |
183 | |
184 | |
185 def get_interface_extended_attributes_from_idl(file_contents): | |
186 match = re.search(r'\[(.*)\]\s*' | |
187 r'((callback|partial)\s+)?' | |
188 r'(interface|exception)\s+' | |
189 r'\w+\s*' | |
190 r'(:\s*\w+\s*)?' | |
191 r'{', | |
192 file_contents, flags=re.DOTALL) | |
193 if not match: | |
194 return {} | |
195 # Strip comments | |
196 # re.compile needed b/c Python 2.6 doesn't support flags in re.sub | |
197 single_line_comment_re = re.compile(r'//.*$', flags=re.MULTILINE) | |
198 block_comment_re = re.compile(r'/\*.*?\*/', flags=re.MULTILINE | re.DOTALL) | |
199 extended_attributes_string = re.sub(single_line_comment_re, '', match.group(
1)) | |
200 extended_attributes_string = re.sub(block_comment_re, '', extended_attribute
s_string) | |
201 extended_attributes = {} | |
202 # FIXME: this splitting is WRONG: it fails on ExtendedAttributeArgList like | |
203 # 'NamedConstructor=Foo(a, b)' | |
204 parts = [extended_attribute.strip() | |
205 for extended_attribute in extended_attributes_string.split(',') | |
206 # Discard empty parts, which may exist due to trailing comma | |
207 if extended_attribute.strip()] | |
208 for part in parts: | |
209 name, _, value = map(string.strip, part.partition('=')) | |
210 extended_attributes[name] = value | |
211 return extended_attributes | |
212 | |
213 | |
214 def get_put_forward_interfaces_from_idl(file_contents): | |
215 put_forwards_pattern = (r'\[[^\]]*PutForwards=[^\]]*\]\s+' | |
216 r'readonly\s+' | |
217 r'attribute\s+' | |
218 r'(\w+)') | |
219 return sorted(set(match.group(1) | |
220 for match in re.finditer(put_forwards_pattern, | |
221 file_contents, | |
222 flags=re.DOTALL))) | |
223 | |
224 | |
225 ################################################################################ | |
226 # Write files | 90 # Write files |
227 ################################################################################ | 91 ################################################################################ |
228 | 92 |
229 def write_dependencies_file(dependencies_filename, only_if_changed): | 93 def write_dependencies_file(dependencies_filename, only_if_changed): |
230 """Write the interface dependencies file. | 94 """Write the interface dependencies file. |
231 | 95 |
232 The format is as follows: | 96 The format is as follows: |
233 | 97 |
234 Document.idl P.idl | 98 Document.idl P.idl |
235 Event.idl | 99 Event.idl |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 refined_filename, _ = os.path.splitext(os.path.relpath(filename, source_
dir)) | 145 refined_filename, _ = os.path.splitext(os.path.relpath(filename, source_
dir)) |
282 refined_filename = refined_filename.replace(os.sep, posixpath.sep) | 146 refined_filename = refined_filename.replace(os.sep, posixpath.sep) |
283 extended_attributes_list = [ | 147 extended_attributes_list = [ |
284 extended_attribute_string(name) | 148 extended_attribute_string(name) |
285 for name in 'Conditional', 'ImplementedAs', 'RuntimeEnabled' | 149 for name in 'Conditional', 'ImplementedAs', 'RuntimeEnabled' |
286 if name in extended_attributes] | 150 if name in extended_attributes] |
287 lines.append('%s %s\n' % (refined_filename, ', '.join(extended_attribute
s_list))) | 151 lines.append('%s %s\n' % (refined_filename, ', '.join(extended_attribute
s_list))) |
288 write_file(lines, destination_filename, only_if_changed) | 152 write_file(lines, destination_filename, only_if_changed) |
289 | 153 |
290 | 154 |
291 def write_global_constructors_partial_interface(interface_name, destination_file
name, constructor_attributes_list, only_if_changed): | |
292 lines = (['partial interface %s {\n' % interface_name] + | |
293 [' %s;\n' % constructor_attribute | |
294 for constructor_attribute in sorted(constructor_attributes_list)]
+ | |
295 ['};\n']) | |
296 write_file(lines, destination_filename, only_if_changed) | |
297 | |
298 | |
299 ################################################################################ | 155 ################################################################################ |
300 # Dependency resolution | 156 # Dependency resolution |
301 ################################################################################ | 157 ################################################################################ |
302 | 158 |
303 def include_path(idl_filename, implemented_as=None): | 159 def include_path(idl_filename, implemented_as=None): |
304 """Returns relative path to header file in POSIX format; used in includes. | 160 """Returns relative path to header file in POSIX format; used in includes. |
305 | 161 |
306 POSIX format is used for consistency of output, so reference tests are | 162 POSIX format is used for consistency of output, so reference tests are |
307 platform-independent. | 163 platform-independent. |
308 """ | 164 """ |
(...skipping 24 matching lines...) Expand all Loading... |
333 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co
ntents) | 189 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co
ntents) |
334 implemented_as = extended_attributes.get('ImplementedAs') | 190 implemented_as = extended_attributes.get('ImplementedAs') |
335 # FIXME: remove [NoHeader] once switch to Python | 191 # FIXME: remove [NoHeader] once switch to Python |
336 this_include_path = (include_path(idl_filename, implemented_as) | 192 this_include_path = (include_path(idl_filename, implemented_as) |
337 if 'NoHeader' not in extended_attributes else None) | 193 if 'NoHeader' not in extended_attributes else None) |
338 | 194 |
339 # Handle partial interfaces | 195 # Handle partial interfaces |
340 partial_interface_name = get_partial_interface_name_from_idl(idl_file_conten
ts) | 196 partial_interface_name = get_partial_interface_name_from_idl(idl_file_conten
ts) |
341 if partial_interface_name: | 197 if partial_interface_name: |
342 add_paths_to_partials_dict(partial_interface_name, full_path, this_inclu
de_path) | 198 add_paths_to_partials_dict(partial_interface_name, full_path, this_inclu
de_path) |
343 return False | 199 return |
344 | 200 |
345 # If not a partial interface, the basename is the interface name | 201 # If not a partial interface, the basename is the interface name |
346 interface_name, _ = os.path.splitext(os.path.basename(idl_filename)) | 202 interface_name, _ = os.path.splitext(os.path.basename(idl_filename)) |
347 | 203 |
348 interfaces_info[interface_name] = { | 204 interfaces_info[interface_name] = { |
349 'full_path': full_path, | 205 'full_path': full_path, |
350 'implements_interfaces': get_implemented_interfaces_from_idl(idl_file_co
ntents, interface_name), | 206 'implements_interfaces': get_implemented_interfaces_from_idl(idl_file_co
ntents, interface_name), |
351 'is_callback_interface': is_callback_interface_from_idl(idl_file_content
s), | 207 'is_callback_interface': is_callback_interface_from_idl(idl_file_content
s), |
352 # Interfaces that are referenced (used as types) and that we introspect | 208 # Interfaces that are referenced (used as types) and that we introspect |
353 # during code generation (beyond interface-level data ([ImplementedAs], | 209 # during code generation (beyond interface-level data ([ImplementedAs], |
354 # is_callback_interface, ancestors, and inherited extended attributes): | 210 # is_callback_interface, ancestors, and inherited extended attributes): |
355 # deep dependencies. | 211 # deep dependencies. |
356 # These cause rebuilds of referrers, due to the dependency, so these | 212 # These cause rebuilds of referrers, due to the dependency, so these |
357 # should be minimized; currently only targets of [PutForwards]. | 213 # should be minimized; currently only targets of [PutForwards]. |
358 'referenced_interfaces': get_put_forward_interfaces_from_idl(idl_file_co
ntents), | 214 'referenced_interfaces': get_put_forward_interfaces_from_idl(idl_file_co
ntents), |
359 } | 215 } |
360 if this_include_path: | 216 if this_include_path: |
361 interfaces_info[interface_name]['include_path'] = this_include_path | 217 interfaces_info[interface_name]['include_path'] = this_include_path |
362 if implemented_as: | 218 if implemented_as: |
363 interfaces_info[interface_name]['implemented_as'] = implemented_as | 219 interfaces_info[interface_name]['implemented_as'] = implemented_as |
364 | 220 |
365 return True | |
366 | |
367 | |
368 def generate_constructor_attribute_list(interface_name, extended_attributes): | |
369 extended_attributes_list = [ | |
370 name + '=' + extended_attributes[name] | |
371 for name in 'Conditional', 'PerContextEnabled', 'RuntimeEnabled' | |
372 if name in extended_attributes] | |
373 if extended_attributes_list: | |
374 extended_string = '[%s] ' % ', '.join(extended_attributes_list) | |
375 else: | |
376 extended_string = '' | |
377 | |
378 attribute_string = 'attribute {interface_name}Constructor {interface_name}'.
format(interface_name=interface_name) | |
379 attributes_list = [extended_string + attribute_string] | |
380 | |
381 # In addition to the regular property, for every [NamedConstructor] | |
382 # extended attribute on an interface, a corresponding property MUST exist | |
383 # on the ECMAScript global object. | |
384 if 'NamedConstructor' in extended_attributes: | |
385 named_constructor = extended_attributes['NamedConstructor'] | |
386 # Extract function name, namely everything before opening '(' | |
387 constructor_name = re.sub(r'\(.*', '', named_constructor) | |
388 # Note the reduplicated 'ConstructorConstructor' | |
389 attribute_string = 'attribute %sConstructorConstructor %s' % (interface_
name, constructor_name) | |
390 attributes_list.append(extended_string + attribute_string) | |
391 | |
392 return attributes_list | |
393 | |
394 | |
395 def record_global_constructors_and_extended_attributes(idl_filename, global_cons
tructors): | |
396 interface_name, _ = os.path.splitext(os.path.basename(idl_filename)) | |
397 full_path = os.path.realpath(idl_filename) | |
398 idl_file_contents = get_file_contents(full_path) | |
399 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co
ntents) | |
400 | |
401 # Record extended attributes | 221 # Record extended attributes |
402 extended_attributes_by_interface[interface_name] = extended_attributes | 222 extended_attributes_by_interface[interface_name] = extended_attributes |
403 | 223 |
404 # Record global constructors | |
405 if (not is_callback_interface_from_idl(idl_file_contents) and | |
406 'NoInterfaceObject' not in extended_attributes): | |
407 global_contexts = extended_attributes.get('GlobalContext', 'Window').spl
it('&') | |
408 new_constructor_list = generate_constructor_attribute_list(interface_nam
e, extended_attributes) | |
409 for global_object in global_contexts: | |
410 global_constructors[global_object].extend(new_constructor_list) | |
411 | |
412 # Record parents | 224 # Record parents |
413 parent = get_parent_interface(idl_file_contents) | 225 parent = get_parent_interface(idl_file_contents) |
414 if parent: | 226 if parent: |
415 parent_interfaces[interface_name] = parent | 227 parent_interfaces[interface_name] = parent |
416 | 228 |
417 | 229 |
418 def record_extended_attributes(idl_filename): | |
419 interface_name, _ = os.path.splitext(os.path.basename(idl_filename)) | |
420 full_path = os.path.realpath(idl_filename) | |
421 idl_file_contents = get_file_contents(full_path) | |
422 extended_attributes = get_interface_extended_attributes_from_idl(idl_file_co
ntents) | |
423 extended_attributes_by_interface[interface_name] = extended_attributes | |
424 | |
425 | |
426 def generate_ancestors_and_inherited_extended_attributes(interface_name): | 230 def generate_ancestors_and_inherited_extended_attributes(interface_name): |
427 interface_info = interfaces_info[interface_name] | 231 interface_info = interfaces_info[interface_name] |
428 interface_extended_attributes = extended_attributes_by_interface[interface_n
ame] | 232 interface_extended_attributes = extended_attributes_by_interface[interface_n
ame] |
429 inherited_extended_attributes = dict( | 233 inherited_extended_attributes = dict( |
430 (key, value) | 234 (key, value) |
431 for key, value in interface_extended_attributes.iteritems() | 235 for key, value in interface_extended_attributes.iteritems() |
432 if key in INHERITED_EXTENDED_ATTRIBUTES) | 236 if key in INHERITED_EXTENDED_ATTRIBUTES) |
433 | 237 |
434 def generate_ancestors(interface_name): | 238 def generate_ancestors(interface_name): |
435 while interface_name in parent_interfaces: | 239 while interface_name in parent_interfaces: |
(...skipping 13 matching lines...) Expand all Loading... |
449 # IDL files, or generated support files. | 253 # IDL files, or generated support files. |
450 ancestor_extended_attributes = extended_attributes_by_interface.get(ance
stor, {}) | 254 ancestor_extended_attributes = extended_attributes_by_interface.get(ance
stor, {}) |
451 inherited_extended_attributes.update(dict( | 255 inherited_extended_attributes.update(dict( |
452 (key, value) | 256 (key, value) |
453 for key, value in ancestor_extended_attributes.iteritems() | 257 for key, value in ancestor_extended_attributes.iteritems() |
454 if key in INHERITED_EXTENDED_ATTRIBUTES)) | 258 if key in INHERITED_EXTENDED_ATTRIBUTES)) |
455 if inherited_extended_attributes: | 259 if inherited_extended_attributes: |
456 interface_info['inherited_extended_attributes'] = inherited_extended_att
ributes | 260 interface_info['inherited_extended_attributes'] = inherited_extended_att
ributes |
457 | 261 |
458 | 262 |
459 def parse_idl_files(idl_files, global_constructors_filenames): | 263 def parse_idl_files(idl_files): |
460 """Compute dependencies between IDL files, and return constructors on global
objects. | 264 """Compute information about IDL files. |
461 | 265 |
462 Primary effect is computing info about main interfaces, stored in global | 266 Primary effect is computing info about main interfaces, stored in global |
463 interfaces_info. | 267 interfaces_info. |
464 The keys are the interfaces for which bindings are generated; | |
465 this does not include interfaces implemented by another interface. | |
466 | |
467 Returns: | |
468 global_constructors: | |
469 dict of global objects -> list of constructors on that object | |
470 """ | 268 """ |
471 global_constructors = dict([ | 269 # Generate dependencies. |
472 (global_object, []) | |
473 for global_object in global_constructors_filenames]) | |
474 | |
475 # Generate dependencies, and (for main IDL files), record | |
476 # global_constructors and extended_attributes_by_interface. | |
477 for idl_filename in idl_files: | 270 for idl_filename in idl_files: |
478 # Test skips partial interfaces | 271 generate_dependencies(idl_filename) |
479 if generate_dependencies(idl_filename): | |
480 record_global_constructors_and_extended_attributes(idl_filename, glo
bal_constructors) | |
481 | 272 |
482 for interface_name in interfaces_info: | 273 for interface_name in interfaces_info: |
483 generate_ancestors_and_inherited_extended_attributes(interface_name) | 274 generate_ancestors_and_inherited_extended_attributes(interface_name) |
484 | 275 |
485 # Add constructors on global objects to partial interfaces | |
486 # These are all partial interfaces, but the files are dynamically generated, | |
487 # so they need to be handled separately from static partial interfaces. | |
488 for global_object, constructor_filename in global_constructors_filenames.ite
ritems(): | |
489 if global_object in interfaces_info: | |
490 # No include path needed, as already included in the header file | |
491 add_paths_to_partials_dict(global_object, constructor_filename) | |
492 | |
493 # An IDL file's dependencies are partial interface files that extend it, | 276 # An IDL file's dependencies are partial interface files that extend it, |
494 # and files for other interfaces that this interfaces implements. | 277 # and files for other interfaces that this interfaces implements. |
495 for interface_name, interface_info in interfaces_info.iteritems(): | 278 for interface_name, interface_info in interfaces_info.iteritems(): |
496 partial_interfaces_full_paths, partial_interfaces_include_paths = ( | 279 partial_interfaces_full_paths, partial_interfaces_include_paths = ( |
497 (partial_interface_files[interface_name]['full_paths'], | 280 (partial_interface_files[interface_name]['full_paths'], |
498 partial_interface_files[interface_name]['include_paths']) | 281 partial_interface_files[interface_name]['include_paths']) |
499 if interface_name in partial_interface_files else ([], [])) | 282 if interface_name in partial_interface_files else ([], [])) |
500 | 283 |
501 implemented_interfaces = interface_info['implements_interfaces'] | 284 implemented_interfaces = interface_info['implements_interfaces'] |
502 try: | 285 try: |
503 implemented_interfaces_full_paths = [ | 286 implemented_interfaces_full_paths = [ |
504 interfaces_info[interface]['full_path'] | 287 interfaces_info[interface]['full_path'] |
505 for interface in implemented_interfaces] | 288 for interface in implemented_interfaces] |
506 implemented_interfaces_include_paths = [ | 289 implemented_interfaces_include_paths = [ |
507 interfaces_info[interface]['include_path'] | 290 interfaces_info[interface]['include_path'] |
508 for interface in implemented_interfaces | 291 for interface in implemented_interfaces |
509 if 'include_path' in interfaces_info[interface]] | 292 if 'include_path' in interfaces_info[interface]] |
510 except KeyError as key_name: | 293 except KeyError as key_name: |
511 raise IdlInterfaceFileNotFoundError('Could not find the IDL file whe
re the following implemented interface is defined: %s' % key_name) | 294 raise IdlInterfaceFileNotFoundError('Could not find the IDL file whe
re the following implemented interface is defined: %s' % key_name) |
512 | 295 |
513 interface_info['dependencies_full_paths'] = ( | 296 interface_info['dependencies_full_paths'] = ( |
514 partial_interfaces_full_paths + | 297 partial_interfaces_full_paths + |
515 implemented_interfaces_full_paths) | 298 implemented_interfaces_full_paths) |
516 interface_info['dependencies_include_paths'] = ( | 299 interface_info['dependencies_include_paths'] = ( |
517 partial_interfaces_include_paths + | 300 partial_interfaces_include_paths + |
518 implemented_interfaces_include_paths) | 301 implemented_interfaces_include_paths) |
519 | 302 |
520 return global_constructors | |
521 | |
522 | 303 |
523 ################################################################################ | 304 ################################################################################ |
524 | 305 |
525 def main(): | 306 def main(): |
526 options, args = parse_options() | 307 options, args = parse_options() |
527 | 308 |
528 # Static IDL files are passed in a file (generated at GYP time), due to OS | 309 # Static IDL files are passed in a file (generated at GYP time), due to OS |
529 # command line length limits | 310 # command line length limits |
530 with open(options.idl_files_list) as idl_files_list: | 311 with open(options.idl_files_list) as idl_files_list: |
531 idl_files = [line.rstrip('\n') for line in idl_files_list] | 312 idl_files = [line.rstrip('\n') for line in idl_files_list] |
532 # Generated IDL files are passed at the command line, since these are in the | 313 # Generated IDL files are passed at the command line, since these are in the |
533 # build directory, which is determined at build time, not GYP time, so these | 314 # build directory, which is determined at build time, not GYP time, so these |
534 # cannot be included in the file listing static files | 315 # cannot be included in the file listing static files |
535 idl_files.extend(args) | 316 idl_files.extend(args) |
536 | 317 |
537 only_if_changed = options.write_file_only_if_changed | 318 only_if_changed = options.write_file_only_if_changed |
538 global_constructors_filenames = { | |
539 'Window': options.window_constructors_file, | |
540 'WorkerGlobalScope': options.workerglobalscope_constructors_file, | |
541 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_
file, | |
542 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constru
ctors_file, | |
543 'ServiceWorkerGlobalScope': options.serviceworkerglobalscope_constructor
s_file, | |
544 } | |
545 | 319 |
546 global_constructors = parse_idl_files(idl_files, global_constructors_filenam
es) | 320 parse_idl_files(idl_files) |
547 | 321 write_pickle_file(options.interfaces_info_file, interfaces_info, only_if_cha
nged) |
548 write_dependencies_file(options.interface_dependencies_file, only_if_changed
) | 322 write_dependencies_file(options.interface_dependencies_file, only_if_changed
) |
549 write_pickle_file(options.interfaces_info_file, interfaces_info, only_if_cha
nged) | |
550 for interface_name, filename in global_constructors_filenames.iteritems(): | |
551 if interface_name in interfaces_info: | |
552 write_global_constructors_partial_interface(interface_name, filename
, global_constructors[interface_name], only_if_changed) | |
553 write_event_names_file(options.event_names_file, only_if_changed) | 323 write_event_names_file(options.event_names_file, only_if_changed) |
554 | 324 |
555 | 325 |
556 if __name__ == '__main__': | 326 if __name__ == '__main__': |
557 main() | 327 main() |
OLD | NEW |