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

Side by Side Diff: bindings/scripts/compute_interfaces_info_overall.py

Issue 540533002: Roll IDL to Dartium37 (r181268) (Closed) Base URL: https://dart.googlecode.com/svn/third_party/WebCore
Patch Set: Created 6 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2013 Google Inc. All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
14 # distribution.
15 # * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
30
31 """Compute global interface information, including public information, dependenc ies, and inheritance.
32
33 Computed data is stored in a global variable, |interfaces_info|, and written as
34 output (concretely, exported as a pickle). This is then used by the IDL compiler
35 itself, so it does not need to compute global information itself, and so that
36 inter-IDL dependencies are clear, since they are all computed here.
37
38 The |interfaces_info| pickle is a *global* dependency: any changes cause a full
39 rebuild. This is to avoid having to compute which public data is visible by
40 which IDL files on a file-by-file basis, which is very complex for little
41 benefit.
42 |interfaces_info| should thus only contain data about an interface that
43 contains paths or is needed by *other* interfaces, e.g., path data (to abstract
44 the compiler from OS-specific file paths) or public data (to avoid having to
45 read other interfaces unnecessarily).
46 It should *not* contain full information about an interface (e.g., all
47 extended attributes), as this would cause unnecessary rebuilds.
48
49 |interfaces_info| is a dict, keyed by |interface_name|.
50
51 Current keys are:
52 * dependencies:
53 'implements_interfaces': targets of 'implements' statements
54 'referenced_interfaces': reference interfaces that are introspected
55 (currently just targets of [PutForwards])
56
57 * inheritance:
58 'ancestors': all ancestor interfaces
59 'inherited_extended_attributes': inherited extended attributes
60 (all controlling memory management)
61
62 * public:
63 'is_callback_interface': bool, callback interface or not
64 'implemented_as': value of [ImplementedAs=...] on interface (C++ class name)
65
66 * paths:
67 'full_path': path to the IDL file, so can lookup an IDL by interface name
68 'include_path': path for use in C++ #include directives
69 'dependencies_full_paths': paths to dependencies (for merging into main)
70 'dependencies_include_paths': paths for use in C++ #include directives
71
72 Note that all of these are stable information, unlikely to change without
73 moving or deleting files (hence requiring a full rebuild anyway) or significant
74 code changes (for inherited extended attributes).
75
76 Design doc: http://www.chromium.org/developers/design-documents/idl-build
77 """
78
79 from collections import defaultdict
80 import cPickle as pickle
81 import optparse
82 import sys
83
84 from utilities import read_pickle_files, write_pickle_file
85
86 INHERITED_EXTENDED_ATTRIBUTES = set([
87 'ActiveDOMObject',
88 'DependentLifetime',
89 'GarbageCollected',
90 'WillBeGarbageCollected',
91 ])
92
93 # Main variable (filled in and exported)
94 interfaces_info = {}
95
96 # Auxiliary variables (not visible to future build steps)
97 partial_interface_files = defaultdict(lambda: {
98 'full_paths': [],
99 'include_paths': [],
100 })
101 parent_interfaces = {}
102 inherited_extended_attributes_by_interface = {} # interface name -> extended at tributes
103
104
105 class IdlInterfaceFileNotFoundError(Exception):
106 """Raised if the IDL file implementing an interface cannot be found."""
107 pass
108
109
110 def parse_options():
111 usage = 'Usage: %prog [InfoIndividual.pickle]... [Info.pickle]'
112 parser = optparse.OptionParser(usage=usage)
113 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')
114
115 options, args = parser.parse_args()
116 if options.write_file_only_if_changed is None:
117 parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.')
118 options.write_file_only_if_changed = bool(options.write_file_only_if_changed )
119 return options, args
120
121
122 def dict_of_dicts_of_lists_update_or_append(existing, other):
123 """Updates an existing dict of dicts of lists, or appends to lists if key al ready present.
124
125 Needed for merging partial_interface_files across components.
126 """
127 for key, value in other.iteritems():
128 if key not in existing:
129 existing[key] = value
130 continue
131 existing_value = existing[key]
132 for inner_key, inner_value in value.iteritems():
133 existing_value[inner_key].extend(inner_value)
134
135
136 ################################################################################
137 # Computations
138 ################################################################################
139
140 def compute_inheritance_info(interface_name):
141 """Compute inheritance information, namely ancestors and inherited extended attributes."""
142 def generate_ancestors(interface_name):
143 while interface_name in parent_interfaces:
144 interface_name = parent_interfaces[interface_name]
145 yield interface_name
146
147 ancestors = list(generate_ancestors(interface_name))
148 inherited_extended_attributes = inherited_extended_attributes_by_interface[i nterface_name]
149 for ancestor in ancestors:
150 # Ancestors may not be present, notably if an ancestor is a generated
151 # IDL file and we are running this script from run-bindings-tests,
152 # where we don't generate these files.
153 ancestor_extended_attributes = inherited_extended_attributes_by_interfac e.get(ancestor, {})
154 inherited_extended_attributes.update(ancestor_extended_attributes)
155
156 interfaces_info[interface_name].update({
157 'ancestors': ancestors,
158 'inherited_extended_attributes': inherited_extended_attributes,
159 })
160
161
162 def compute_interfaces_info_overall(info_individuals):
163 """Compute information about IDL files.
164
165 Information is stored in global interfaces_info.
166 """
167 for info in info_individuals:
168 # No overlap between interface names, so ok to use dict.update
169 interfaces_info.update(info['interfaces_info'])
170 # Interfaces in one component may have partial interfaces in
171 # another component. This is ok (not a layering violation), since
172 # partial interfaces are used to *extend* interfaces.
173 # We thus need to update or append if already present
174 dict_of_dicts_of_lists_update_or_append(
175 partial_interface_files, info['partial_interface_files'])
176
177 # Record inheritance information individually
178 for interface_name, interface_info in interfaces_info.iteritems():
179 extended_attributes = interface_info['extended_attributes']
180 inherited_extended_attributes_by_interface[interface_name] = dict(
181 (key, value)
182 for key, value in extended_attributes.iteritems()
183 if key in INHERITED_EXTENDED_ATTRIBUTES)
184 parent = interface_info['parent']
185 if parent:
186 parent_interfaces[interface_name] = parent
187
188 # Once all individual files handled, can compute inheritance information
189 # and dependencies
190
191 # Compute inheritance info
192 for interface_name in interfaces_info:
193 compute_inheritance_info(interface_name)
194
195 # Compute dependencies
196 # Move implements info from implement*ed* interface (rhs of 'implements')
197 # to implement*ing* interface (lhs of 'implements').
198 # Note that moving an 'implements' statement between implementing and
199 # implemented files does not change the info (or hence cause a rebuild)!
200 for right_interface_name, interface_info in interfaces_info.iteritems():
201 for left_interface_name in interface_info['implemented_by_interfaces']:
202 interfaces_info[left_interface_name]['implements_interfaces'].append (right_interface_name)
203 del interface_info['implemented_by_interfaces']
204
205 # An IDL file's dependencies are partial interface files that extend it,
206 # and files for other interfaces that this interfaces implements.
207 for interface_name, interface_info in interfaces_info.iteritems():
208 partial_interface_paths = partial_interface_files[interface_name]
209 partial_interfaces_full_paths = partial_interface_paths['full_paths']
210 # Partial interface definitions each need an include, as they are
211 # implemented in separate classes from the main interface.
212 partial_interfaces_include_paths = partial_interface_paths['include_path s']
213
214 implemented_interfaces = interface_info['implements_interfaces']
215 try:
216 implemented_interfaces_info = [
217 interfaces_info[interface]
218 for interface in implemented_interfaces]
219 except KeyError as key_name:
220 raise IdlInterfaceFileNotFoundError('Could not find the IDL file whe re the following implemented interface is defined: %s' % key_name)
221 implemented_interfaces_full_paths = [
222 implemented_interface_info['full_path']
223 for implemented_interface_info in implemented_interfaces_info]
224 # Implemented interfaces don't need includes, as this is handled in
225 # the Blink implementation (they are implemented on |impl| itself,
226 # hence header is included in implementing class).
227 # However, they are needed for legacy implemented interfaces that
228 # are being treated as partial interfaces, until we remove these.
229 # http://crbug.com/360435
230 implemented_interfaces_include_paths = [
231 implemented_interface_info['include_path']
232 for implemented_interface_info in implemented_interfaces_info
233 if implemented_interface_info['is_legacy_treat_as_partial_interface' ]]
234
235 interface_info.update({
236 'dependencies_full_paths': (partial_interfaces_full_paths +
237 implemented_interfaces_full_paths),
238 'dependencies_include_paths': (partial_interfaces_include_paths +
239 implemented_interfaces_include_paths) ,
240 })
241
242 # Clean up temporary private information
243 for interface_info in interfaces_info.itervalues():
244 del interface_info['extended_attributes']
245 del interface_info['is_legacy_treat_as_partial_interface']
246 del interface_info['parent']
247
248
249 ################################################################################
250
251 def main():
252 options, args = parse_options()
253 # args = Input1, Input2, ..., Output
254 interfaces_info_filename = args.pop()
255 info_individuals = read_pickle_files(args)
256
257 compute_interfaces_info_overall(info_individuals)
258 write_pickle_file(interfaces_info_filename,
259 interfaces_info,
260 options.write_file_only_if_changed)
261
262
263 if __name__ == '__main__':
264 sys.exit(main())
OLDNEW
« no previous file with comments | « bindings/scripts/compute_interfaces_info_individual.py ('k') | bindings/scripts/generate_event_interfaces.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698