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

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

Issue 671863002: IDL: Avoid global variables in compute_interfaces_info_individual.py (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Don't use cache Created 6 years, 2 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
« no previous file with comments | « no previous file | Tools/Scripts/webkitpy/bindings/main.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 import os 46 import os
47 import posixpath 47 import posixpath
48 import sys 48 import sys
49 49
50 from idl_reader import IdlReader 50 from idl_reader import IdlReader
51 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 51 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
52 52
53 module_path = os.path.dirname(__file__) 53 module_path = os.path.dirname(__file__)
54 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir)) 54 source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir))
55 55
56 # Global variables (filled in and exported)
57 interfaces_info = {}
58 partial_interface_files = defaultdict(lambda: {
59 'full_paths': [],
60 'include_paths': [],
61 })
62
63 56
64 class IdlBadFilenameError(Exception): 57 class IdlBadFilenameError(Exception):
65 """Raised if an IDL filename disagrees with the interface name in the file." "" 58 """Raised if an IDL filename disagrees with the interface name in the file." ""
66 pass 59 pass
67 60
68 61
69 def parse_options(): 62 def parse_options():
70 usage = 'Usage: %prog [options] [generated1.idl]...' 63 usage = 'Usage: %prog [options] [generated1.idl]...'
71 parser = optparse.OptionParser(usage=usage) 64 parser = optparse.OptionParser(usage=usage)
72 parser.add_option('--cache-directory', help='cache directory') 65 parser.add_option('--cache-directory', help='cache directory')
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 """ 97 """
105 relative_dir = relative_dir_posix(idl_filename) 98 relative_dir = relative_dir_posix(idl_filename)
106 99
107 # IDL file basename is used even if only a partial interface file 100 # IDL file basename is used even if only a partial interface file
108 idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename)) 101 idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename))
109 cpp_class_name = implemented_as or idl_file_basename 102 cpp_class_name = implemented_as or idl_file_basename
110 103
111 return posixpath.join(relative_dir, cpp_class_name + '.h') 104 return posixpath.join(relative_dir, cpp_class_name + '.h')
112 105
113 106
114 def add_paths_to_partials_dict(partial_interface_name, full_path, this_include_p ath=None):
115 paths_dict = partial_interface_files[partial_interface_name]
116 paths_dict['full_paths'].append(full_path)
117 if this_include_path:
118 paths_dict['include_paths'].append(this_include_path)
119
120
121 def get_implements_from_definitions(definitions, definition_name): 107 def get_implements_from_definitions(definitions, definition_name):
122 left_interfaces = [] 108 left_interfaces = []
123 right_interfaces = [] 109 right_interfaces = []
124 for implement in definitions.implements: 110 for implement in definitions.implements:
125 if definition_name == implement.left_interface: 111 if definition_name == implement.left_interface:
126 right_interfaces.append(implement.right_interface) 112 right_interfaces.append(implement.right_interface)
127 elif definition_name == implement.right_interface: 113 elif definition_name == implement.right_interface:
128 left_interfaces.append(implement.left_interface) 114 left_interfaces.append(implement.left_interface)
129 else: 115 else:
130 raise IdlBadFilenameError( 116 raise IdlBadFilenameError(
131 'implements statement found in unrelated IDL file.\n' 117 'implements statement found in unrelated IDL file.\n'
132 'Statement is:\n' 118 'Statement is:\n'
133 ' %s implements %s;\n' 119 ' %s implements %s;\n'
134 'but filename is unrelated "%s.idl"' % 120 'but filename is unrelated "%s.idl"' %
135 (implement.left_interface, implement.right_interface, definition _name)) 121 (implement.left_interface, implement.right_interface, definition _name))
136 return left_interfaces, right_interfaces 122 return left_interfaces, right_interfaces
137 123
138 124
139 def get_put_forward_interfaces_from_definition(definition): 125 def get_put_forward_interfaces_from_definition(definition):
140 return sorted(set(attribute.idl_type.base_type 126 return sorted(set(attribute.idl_type.base_type
141 for attribute in definition.attributes 127 for attribute in definition.attributes
142 if 'PutForwards' in attribute.extended_attributes)) 128 if 'PutForwards' in attribute.extended_attributes))
143 129
144 130
145 def compute_info_individual(idl_filename, reader): 131 class InterfaceInfoCollector(object):
146 definitions = reader.read_idl_file(idl_filename) 132 """A class that collects interface information from idl files."""
147 if len(definitions.interfaces) > 0: 133 def __init__(self, cache_directory=None):
148 definition = next(definitions.interfaces.itervalues()) 134 self.reader = IdlReader(interfaces_info=None, outputdir=cache_directory)
149 interface_info = { 135 self.interfaces_info = {}
150 'is_callback_interface': definition.is_callback, 136 self.partial_interface_files = defaultdict(lambda: {
151 'is_dictionary': False, 137 'full_paths': [],
152 # Interfaces that are referenced (used as types) and that we introsp ect 138 'include_paths': [],
153 # during code generation (beyond interface-level data ([ImplementedA s], 139 })
154 # is_callback_interface, ancestors, and inherited extended attribute s): 140
155 # deep dependencies. 141 def add_paths_to_partials_dict(self, partial_interface_name, full_path,
156 # These cause rebuilds of referrers, due to the dependency, so these 142 this_include_path=None):
157 # should be minimized; currently only targets of [PutForwards]. 143 paths_dict = self.partial_interface_files[partial_interface_name]
158 'referenced_interfaces': get_put_forward_interfaces_from_definition( definition), 144 paths_dict['full_paths'].append(full_path)
145 if this_include_path:
146 paths_dict['include_paths'].append(this_include_path)
147
148 def collect_info(self, idl_filename):
149 """Reads an idl file and collects information which is required by the
150 binding code generation."""
151 definitions = self.reader.read_idl_file(idl_filename)
152 if len(definitions.interfaces) > 0:
153 definition = next(definitions.interfaces.itervalues())
154 interface_info = {
155 'is_callback_interface': definition.is_callback,
156 'is_dictionary': False,
157 # Interfaces that are referenced (used as types) and that we
158 # introspect during code generation (beyond interface-level
159 # data ([ImplementedAs], is_callback_interface, ancestors, and
160 # inherited extended attributes): deep dependencies.
161 # These cause rebuilds of referrers, due to the dependency,
162 # so these should be minimized; currently only targets of
163 # [PutForwards].
164 'referenced_interfaces': get_put_forward_interfaces_from_definit ion(definition),
165 }
166 elif len(definitions.dictionaries) > 0:
167 definition = next(definitions.dictionaries.itervalues())
168 interface_info = {
169 'is_callback_interface': False,
170 'is_dictionary': True,
171 'referenced_interfaces': None,
172 }
173 else:
174 raise Exception('IDL file must contain one interface or dictionary')
175
176 extended_attributes = definition.extended_attributes
177 implemented_as = extended_attributes.get('ImplementedAs')
178 full_path = os.path.realpath(idl_filename)
179 this_include_path = None if 'NoImplHeader' in extended_attributes else i nclude_path(idl_filename, implemented_as)
180 if definition.is_partial:
181 # We don't create interface_info for partial interfaces, but
182 # adds paths to another dict.
183 self.add_paths_to_partials_dict(definition.name, full_path, this_inc lude_path)
184 return
185
186 # 'implements' statements can be included in either the file for the
187 # implement*ing* interface (lhs of 'implements') or implement*ed* interf ace
188 # (rhs of 'implements'). Store both for now, then merge to implement*ing *
189 # interface later.
190 left_interfaces, right_interfaces = get_implements_from_definitions(
191 definitions, definition.name)
192
193 interface_info.update({
194 'extended_attributes': extended_attributes,
195 'full_path': full_path,
196 'implemented_as': implemented_as,
197 'implemented_by_interfaces': left_interfaces,
198 'implements_interfaces': right_interfaces,
199 'include_path': this_include_path,
200 # FIXME: temporary private field, while removing old treatement of
201 # 'implements': http://crbug.com/360435
202 'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterfa ce' in extended_attributes,
203 'parent': definition.parent,
204 'relative_dir': relative_dir_posix(idl_filename),
205 })
206 self.interfaces_info[definition.name] = interface_info
207
208 def get_info_as_dict(self):
209 """Returns info packaged as a dict."""
210 return {
211 'interfaces_info': self.interfaces_info,
212 # Can't pickle defaultdict, convert to dict
213 'partial_interface_files': dict(self.partial_interface_files),
159 } 214 }
160 elif len(definitions.dictionaries) > 0:
161 definition = next(definitions.dictionaries.itervalues())
162 interface_info = {
163 'is_callback_interface': False,
164 'is_dictionary': True,
165 'referenced_interfaces': None,
166 }
167 else:
168 raise Exception('IDL file must contain one interface or dictionary')
169
170 extended_attributes = definition.extended_attributes
171 implemented_as = extended_attributes.get('ImplementedAs')
172 full_path = os.path.realpath(idl_filename)
173 this_include_path = None if 'NoImplHeader' in extended_attributes else inclu de_path(idl_filename, implemented_as)
174 if definition.is_partial:
175 # We don't create interface_info for partial interfaces, but
176 # adds paths to another dict.
177 add_paths_to_partials_dict(definition.name, full_path, this_include_path )
178 return
179
180 # 'implements' statements can be included in either the file for the
181 # implement*ing* interface (lhs of 'implements') or implement*ed* interface
182 # (rhs of 'implements'). Store both for now, then merge to implement*ing*
183 # interface later.
184 left_interfaces, right_interfaces = get_implements_from_definitions(definiti ons, definition.name)
185
186 interface_info.update({
187 'extended_attributes': extended_attributes,
188 'full_path': full_path,
189 'implemented_as': implemented_as,
190 'implemented_by_interfaces': left_interfaces,
191 'implements_interfaces': right_interfaces,
192 'include_path': this_include_path,
193 # FIXME: temporary private field, while removing old treatement of
194 # 'implements': http://crbug.com/360435
195 'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterface' in extended_attributes,
196 'parent': definition.parent,
197 'relative_dir': relative_dir_posix(idl_filename),
198 })
199 interfaces_info[definition.name] = interface_info
200
201
202 def info_individual():
203 """Returns info packaged as a dict."""
204 return {
205 'interfaces_info': interfaces_info,
206 # Can't pickle defaultdict, convert to dict
207 'partial_interface_files': dict(partial_interface_files),
208 }
209 215
210 216
211 ################################################################################ 217 ################################################################################
212 218
213 def main(): 219 def main():
214 options, args = parse_options() 220 options, args = parse_options()
215 221
216 # Static IDL files are passed in a file (generated at GYP time), due to OS 222 # Static IDL files are passed in a file (generated at GYP time), due to OS
217 # command line length limits 223 # command line length limits
218 idl_files = read_file_to_list(options.idl_files_list) 224 idl_files = read_file_to_list(options.idl_files_list)
219 # Generated IDL files are passed at the command line, since these are in the 225 # Generated IDL files are passed at the command line, since these are in the
220 # build directory, which is determined at build time, not GYP time, so these 226 # build directory, which is determined at build time, not GYP time, so these
221 # cannot be included in the file listing static files 227 # cannot be included in the file listing static files
222 idl_files.extend(args) 228 idl_files.extend(args)
223 229
224 # Compute information for individual files 230 # Compute information for individual files
225 # Information is stored in global variables interfaces_info and 231 # Information is stored in global variables interfaces_info and
226 # partial_interface_files. 232 # partial_interface_files.
227 reader = IdlReader(interfaces_info=None, outputdir=options.cache_directory) 233 info_collector = InterfaceInfoCollector(options.cache_directory)
228 for idl_filename in idl_files: 234 for idl_filename in idl_files:
229 compute_info_individual(idl_filename, reader) 235 info_collector.collect_info(idl_filename)
230 236
231 write_pickle_file(options.interfaces_info_file, 237 write_pickle_file(options.interfaces_info_file,
232 info_individual(), 238 info_collector.get_info_as_dict(),
233 options.write_file_only_if_changed) 239 options.write_file_only_if_changed)
234 240
235 241
236 if __name__ == '__main__': 242 if __name__ == '__main__':
237 sys.exit(main()) 243 sys.exit(main())
OLDNEW
« no previous file with comments | « no previous file | Tools/Scripts/webkitpy/bindings/main.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698