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

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

Issue 1660113002: Updated to Chrome 45 (2454) moved from SVN to git. Base URL: https://github.com/dart-lang/webcore.git@roll_45
Patch Set: Created 4 years, 10 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 | « bindings/scripts/interface_dependency_resolver.py ('k') | bindings/scripts/v8_attributes.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 # Copyright 2014 The Chromium Authors. All rights reserved. 1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Utility functions (file reading, simple IDL parsing by regexes) for IDL build . 5 """Utility functions (file reading, simple IDL parsing by regexes) for IDL build .
6 6
7 Design doc: http://www.chromium.org/developers/design-documents/idl-build 7 Design doc: http://www.chromium.org/developers/design-documents/idl-build
8 """ 8 """
9 9
10 import os 10 import os
11 import cPickle as pickle 11 import cPickle as pickle
12 import re 12 import re
13 import string 13 import string
14 import subprocess 14 import subprocess
15 15
16 16
17 KNOWN_COMPONENTS = frozenset(['core', 'modules']) 17 KNOWN_COMPONENTS = frozenset(['core', 'modules'])
18 18 KNOWN_COMPONENTS_WITH_TESTING = frozenset(['core', 'modules', 'testing'])
19
20 class IdlBadFilenameError(Exception):
21 """Raised if an IDL filename disagrees with the interface name in the file." ""
22 pass
23 19
24 20
25 def idl_filename_to_interface_name(idl_filename): 21 def idl_filename_to_interface_name(idl_filename):
26 # interface name is the root of the basename: InterfaceName.idl 22 # interface name is the root of the basename: InterfaceName.idl
27 return os.path.splitext(os.path.basename(idl_filename))[0] 23 return os.path.splitext(os.path.basename(idl_filename))[0]
28 24
29 25
30 def idl_filename_to_component(idl_filename): 26 def idl_filename_to_component_with_known_components(idl_filename, known_componen ts):
31 path = os.path.dirname(os.path.realpath(idl_filename)) 27 path = os.path.dirname(os.path.realpath(idl_filename))
32 while path: 28 while path:
33 dirname, basename = os.path.split(path) 29 dirname, basename = os.path.split(path)
34 if basename.lower() in KNOWN_COMPONENTS: 30 if not basename:
31 break
32 if basename.lower() in known_components:
35 return basename.lower() 33 return basename.lower()
36 path = dirname 34 path = dirname
37 raise 'Unknown component type for %s' % idl_filename 35 raise Exception('Unknown component type for %s' % idl_filename)
36
37
38 def idl_filename_to_component(idl_filename):
39 return idl_filename_to_component_with_known_components(idl_filename, KNOWN_C OMPONENTS)
40
41
42 def is_testing_target(idl_filename):
43 component = idl_filename_to_component_with_known_components(idl_filename, KN OWN_COMPONENTS_WITH_TESTING)
44 return component == 'testing'
45
46
47 # See whether "component" can depend on "dependency" or not:
48 # Suppose that we have interface X and Y:
49 # - if X is a partial interface and Y is the original interface,
50 # use is_valid_component_dependency(X, Y).
51 # - if X implements Y, use is_valid_component_dependency(X, Y)
52 # Suppose that X is a cpp file and Y is a header file:
53 # - if X includes Y, use is_valid_component_dependency(X, Y)
54 def is_valid_component_dependency(component, dependency):
55 assert component in KNOWN_COMPONENTS
56 assert dependency in KNOWN_COMPONENTS
57 if component == 'core' and dependency == 'modules':
58 return False
59 return True
60
61
62 class ComponentInfoProvider(object):
63 """Base class of information provider which provides component-specific
64 information.
65 """
66 def __init__(self):
67 pass
68
69 @property
70 def interfaces_info(self):
71 return {}
72
73 @property
74 def component_info(self):
75 return {}
76
77 @property
78 def enumerations(self):
79 return {}
80
81 @property
82 def typedefs(self):
83 return {}
84
85 @property
86 def union_types(self):
87 return set()
88
89 @property
90 def include_path_for_union_types(self):
91 return None
92
93
94 class ComponentInfoProviderCore(ComponentInfoProvider):
95 def __init__(self, interfaces_info, component_info):
96 super(ComponentInfoProviderCore, self).__init__()
97 self._interfaces_info = interfaces_info
98 self._component_info = component_info
99
100 @property
101 def interfaces_info(self):
102 return self._interfaces_info
103
104 @property
105 def component_info(self):
106 return self._component_info
107
108 @property
109 def enumerations(self):
110 return self._component_info['enumerations']
111
112 @property
113 def typedefs(self):
114 return self._component_info['typedefs']
115
116 @property
117 def union_types(self):
118 return self._component_info['union_types']
119
120 @property
121 def include_path_for_union_types(self):
122 return 'bindings/core/v8/UnionTypesCore.h'
123
124 @property
125 def specifier_for_export(self):
126 return 'CORE_EXPORT '
127
128 @property
129 def include_path_for_export(self):
130 return 'core/CoreExport.h'
131
132
133 class ComponentInfoProviderModules(ComponentInfoProvider):
134 def __init__(self, interfaces_info, component_info_core,
135 component_info_modules):
136 super(ComponentInfoProviderModules, self).__init__()
137 self._interfaces_info = interfaces_info
138 self._component_info_core = component_info_core
139 self._component_info_modules = component_info_modules
140
141 @property
142 def interfaces_info(self):
143 return self._interfaces_info
144
145 @property
146 def component_info(self):
147 return self._component_info_modules
148
149 @property
150 def enumerations(self):
151 enums = self._component_info_core['enumerations'].copy()
152 enums.update(self._component_info_modules['enumerations'])
153 return enums
154
155 @property
156 def typedefs(self):
157 typedefs = self._component_info_core['typedefs'].copy()
158 typedefs.update(self._component_info_modules['typedefs'])
159 return typedefs
160
161 @property
162 def union_types(self):
163 # Remove duplicate union types from component_info_modules to avoid
164 # generating multiple container generation.
165 return self._component_info_modules['union_types'] - self._component_inf o_core['union_types']
166
167 @property
168 def include_path_for_union_types(self):
169 return 'bindings/modules/v8/UnionTypesModules.h'
170
171 @property
172 def specifier_for_export(self):
173 return 'MODULES_EXPORT '
174
175 @property
176 def include_path_for_export(self):
177 return 'modules/ModulesExport.h'
178
179
180 def load_interfaces_info_overall_pickle(info_dir):
181 with open(os.path.join(info_dir, 'modules', 'InterfacesInfoOverall.pickle')) as interface_info_file:
182 return pickle.load(interface_info_file)
183
184
185 def create_component_info_provider_core(info_dir):
186 interfaces_info = load_interfaces_info_overall_pickle(info_dir)
187 with open(os.path.join(info_dir, 'core', 'ComponentInfoCore.pickle')) as com ponent_info_file:
188 component_info = pickle.load(component_info_file)
189 return ComponentInfoProviderCore(interfaces_info, component_info)
190
191
192 def create_component_info_provider_modules(info_dir):
193 interfaces_info = load_interfaces_info_overall_pickle(info_dir)
194 with open(os.path.join(info_dir, 'core', 'ComponentInfoCore.pickle')) as com ponent_info_file:
195 component_info_core = pickle.load(component_info_file)
196 with open(os.path.join(info_dir, 'modules', 'ComponentInfoModules.pickle')) as component_info_file:
197 component_info_modules = pickle.load(component_info_file)
198 return ComponentInfoProviderModules(
199 interfaces_info, component_info_core, component_info_modules)
200
201
202 def create_component_info_provider(info_dir, component):
203 if component == 'core':
204 return create_component_info_provider_core(info_dir)
205 elif component == 'modules':
206 return create_component_info_provider_modules(info_dir)
207 else:
208 return ComponentInfoProvider()
38 209
39 210
40 ################################################################################ 211 ################################################################################
41 # Basic file reading/writing 212 # Basic file reading/writing
42 ################################################################################ 213 ################################################################################
43 214
44 def get_file_contents(filename): 215 def get_file_contents(filename):
45 with open(filename) as f: 216 with open(filename) as f:
46 return f.read() 217 return f.read()
47 218
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 with open(destination_filename, 'w') as destination_file: 268 with open(destination_filename, 'w') as destination_file:
98 destination_file.write(new_text) 269 destination_file.write(new_text)
99 270
100 271
101 def write_pickle_file(pickle_filename, data, only_if_changed): 272 def write_pickle_file(pickle_filename, data, only_if_changed):
102 if only_if_changed and os.path.isfile(pickle_filename): 273 if only_if_changed and os.path.isfile(pickle_filename):
103 with open(pickle_filename) as pickle_file: 274 with open(pickle_filename) as pickle_file:
104 try: 275 try:
105 if pickle.load(pickle_file) == data: 276 if pickle.load(pickle_file) == data:
106 return 277 return
107 except (EOFError, pickle.UnpicklingError): 278 except Exception:
108 # If trouble unpickling, overwrite 279 # If trouble unpickling, overwrite
109 pass 280 pass
110 with open(pickle_filename, 'w') as pickle_file: 281 with open(pickle_filename, 'w') as pickle_file:
111 pickle.dump(data, pickle_file) 282 pickle.dump(data, pickle_file)
112 283
113 284
114 ################################################################################ 285 ################################################################################
115 # IDL parsing 286 # IDL parsing
116 # 287 #
117 # We use regular expressions for parsing; this is incorrect (Web IDL is not a 288 # We use regular expressions for parsing; this is incorrect (Web IDL is not a
118 # regular language), but simple and sufficient in practice. 289 # regular language), but simple and sufficient in practice.
119 # Leading and trailing context (e.g. following '{') used to avoid false matches. 290 # Leading and trailing context (e.g. following '{') used to avoid false matches.
120 ################################################################################ 291 ################################################################################
121 292
122 def get_partial_interface_name_from_idl(file_contents):
123 match = re.search(r'partial\s+interface\s+(\w+)\s*{', file_contents)
124 return match and match.group(1)
125
126
127 def get_implements_from_idl(file_contents, interface_name):
128 """Returns lists of implementing and implemented interfaces.
129
130 Rule is: identifier-A implements identifier-B;
131 i.e., implement*ing* implements implement*ed*;
132 http://www.w3.org/TR/WebIDL/#idl-implements-statements
133
134 Returns two lists of interfaces: identifier-As and identifier-Bs.
135 An 'implements' statements can be present in the IDL file for either the
136 implementing or the implemented interface, but not other files.
137 """
138 implements_re = (r'^\s*'
139 r'(\w+)\s+'
140 r'implements\s+'
141 r'(\w+)\s*'
142 r';')
143 implements_matches = re.finditer(implements_re, file_contents, re.MULTILINE)
144 implements_pairs = [match.groups() for match in implements_matches]
145
146 foreign_implements = [pair for pair in implements_pairs
147 if interface_name not in pair]
148 if foreign_implements:
149 left, right = foreign_implements.pop()
150 raise IdlBadFilenameError(
151 'implements statement found in unrelated IDL file.\n'
152 'Statement is:\n'
153 ' %s implements %s;\n'
154 'but filename is unrelated "%s.idl"' %
155 (left, right, interface_name))
156
157 return (
158 [left for left, right in implements_pairs if right == interface_name],
159 [right for left, right in implements_pairs if left == interface_name])
160
161
162 def is_callback_interface_from_idl(file_contents): 293 def is_callback_interface_from_idl(file_contents):
163 match = re.search(r'callback\s+interface\s+\w+\s*{', file_contents) 294 match = re.search(r'callback\s+interface\s+\w+\s*{', file_contents)
164 return bool(match) 295 return bool(match)
165 296
166 297
167 def is_dictionary_from_idl(file_contents): 298 def should_generate_impl_file_from_idl(file_contents):
168 match = re.search(r'dictionary\s+\w+\s*{', file_contents) 299 """True when a given IDL file contents could generate .h/.cpp files."""
300 # FIXME: This would be error-prone and we should use AST rather than
301 # improving the regexp pattern.
302 match = re.search(r'(interface|dictionary|exception)\s+\w+', file_contents)
169 return bool(match) 303 return bool(match)
170 304
171 305
172 def get_parent_interface(file_contents): 306 def match_interface_extended_attributes_from_idl(file_contents):
173 match = re.search(r'interface\s+'
174 r'\w+\s*'
175 r':\s*(\w+)\s*'
176 r'{',
177 file_contents)
178 return match and match.group(1)
179
180
181 def get_interface_extended_attributes_from_idl(file_contents):
182 # Strip comments 307 # Strip comments
183 # re.compile needed b/c Python 2.6 doesn't support flags in re.sub 308 # re.compile needed b/c Python 2.6 doesn't support flags in re.sub
184 single_line_comment_re = re.compile(r'//.*$', flags=re.MULTILINE) 309 single_line_comment_re = re.compile(r'//.*$', flags=re.MULTILINE)
185 block_comment_re = re.compile(r'/\*.*?\*/', flags=re.MULTILINE | re.DOTALL) 310 block_comment_re = re.compile(r'/\*.*?\*/', flags=re.MULTILINE | re.DOTALL)
186 file_contents = re.sub(single_line_comment_re, '', file_contents) 311 file_contents = re.sub(single_line_comment_re, '', file_contents)
187 file_contents = re.sub(block_comment_re, '', file_contents) 312 file_contents = re.sub(block_comment_re, '', file_contents)
188 313
189 match = re.search(r'\[(.*)\]\s*' 314 match = re.search(r'\[(.*)\]\s*'
190 r'((callback|partial)\s+)?' 315 r'((callback|partial)\s+)?'
191 r'(interface|exception)\s+' 316 r'(interface|exception)\s+'
192 r'\w+\s*' 317 r'\w+\s*'
193 r'(:\s*\w+\s*)?' 318 r'(:\s*\w+\s*)?'
194 r'{', 319 r'{',
195 file_contents, flags=re.DOTALL) 320 file_contents, flags=re.DOTALL)
321 return match
322
323
324 def get_interface_extended_attributes_from_idl(file_contents):
325 match = match_interface_extended_attributes_from_idl(file_contents)
196 if not match: 326 if not match:
197 return {} 327 return {}
198 328
199 extended_attributes_string = match.group(1) 329 extended_attributes_string = match.group(1)
200 extended_attributes = {} 330 extended_attributes = {}
201 # FIXME: this splitting is WRONG: it fails on extended attributes where list s of 331 # FIXME: this splitting is WRONG: it fails on extended attributes where list s of
202 # multiple values are used, which are seperated by a comma and a space. 332 # multiple values are used, which are seperated by a comma and a space.
203 parts = [extended_attribute.strip() 333 parts = [extended_attribute.strip()
204 for extended_attribute in re.split(',\s+', extended_attributes_stri ng) 334 for extended_attribute in re.split(',\s+', extended_attributes_stri ng)
205 # Discard empty parts, which may exist due to trailing comma 335 # Discard empty parts, which may exist due to trailing comma
206 if extended_attribute.strip()] 336 if extended_attribute.strip()]
207 for part in parts: 337 for part in parts:
208 name, _, value = map(string.strip, part.partition('=')) 338 name, _, value = map(string.strip, part.partition('='))
209 extended_attributes[name] = value 339 extended_attributes[name] = value
210 return extended_attributes 340 return extended_attributes
211 341
212 342
213 def get_put_forward_interfaces_from_idl(file_contents): 343 def get_interface_exposed_arguments(file_contents):
214 put_forwards_pattern = (r'\[[^\]]*PutForwards=[^\]]*\]\s+' 344 match = match_interface_extended_attributes_from_idl(file_contents)
215 r'readonly\s+' 345 if not match:
216 r'attribute\s+' 346 return None
217 r'(\w+)') 347
218 return sorted(set(match.group(1) 348 extended_attributes_string = match.group(1)
219 for match in re.finditer(put_forwards_pattern, 349 match = re.search(r'[^=]\bExposed\(([^)]*)\)', file_contents)
220 file_contents, 350 if not match:
221 flags=re.DOTALL))) 351 return None
352 arguments = []
353 for argument in map(string.strip, match.group(1).split(',')):
354 exposed, runtime_enabled = argument.split()
355 arguments.append({'exposed': exposed, 'runtime_enabled': runtime_enabled })
356
357 return arguments
OLDNEW
« no previous file with comments | « bindings/scripts/interface_dependency_resolver.py ('k') | bindings/scripts/v8_attributes.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698