OLD | NEW |
---|---|
1 #! /usr/bin/env python | 1 #! /usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import json | 6 import json |
7 import os.path | 7 import os.path |
8 import re | 8 import re |
9 import sys | 9 import sys |
10 | 10 |
(...skipping 19 matching lines...) Expand all Loading... | |
30 Given the string from a Comment node, parse it into a tuple that looks | 30 Given the string from a Comment node, parse it into a tuple that looks |
31 like: | 31 like: |
32 ( | 32 ( |
33 "The processed comment, minus all |parameter| mentions.", | 33 "The processed comment, minus all |parameter| mentions.", |
34 { | 34 { |
35 'parameter_name_1': "The comment that followed |parameter_name_1|:", | 35 'parameter_name_1': "The comment that followed |parameter_name_1|:", |
36 ... | 36 ... |
37 } | 37 } |
38 ) | 38 ) |
39 ''' | 39 ''' |
40 # Find all the parameter comments of the form "|name|: comment". | 40 # Find all the parameter comments of the form '|name|: comment'. |
41 parameter_comments = re.findall(r'\n *\|([^|]*)\| *: *(.*)', comment) | 41 parameter_comments = re.findall(r'\n *\|([^|]*)\| *: *(.*)', comment) |
42 # Get the parent comment (everything before the first parameter comment. | 42 # Get the parent comment (everything before the first parameter comment. |
43 parent_comment = re.sub(r'\n *\|.*', '', comment) | 43 parent_comment = re.sub(r'\n *\|.*', '', comment) |
44 parent_comment = parent_comment.replace('\n', '').strip() | 44 parent_comment = parent_comment.replace('\n', '').strip() |
45 | 45 |
46 parsed = {} | 46 parsed = {} |
47 for (name, comment) in parameter_comments: | 47 for (name, comment) in parameter_comments: |
48 parsed[name] = comment.replace('\n', '').strip() | 48 parsed[name] = comment.replace('\n', '').strip() |
49 return (parent_comment, parsed) | 49 return (parent_comment, parsed) |
50 | 50 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
97 'properties': properties, | 97 'properties': properties, |
98 'type': 'object' } | 98 'type': 'object' } |
99 | 99 |
100 class Enum(object): | 100 class Enum(object): |
101 ''' | 101 ''' |
102 Given an IDL Enum node, converts into a Python dictionary that the JSON | 102 Given an IDL Enum node, converts into a Python dictionary that the JSON |
103 schema compiler expects to see. | 103 schema compiler expects to see. |
104 ''' | 104 ''' |
105 def __init__(self, enum_node): | 105 def __init__(self, enum_node): |
106 self.node = enum_node | 106 self.node = enum_node |
107 self.description = '' | |
107 | 108 |
108 def process(self, callbacks): | 109 def process(self, callbacks): |
109 enum = [] | 110 enum = [] |
111 enum_type = 'integer' | |
asargent_no_longer_on_chrome
2012/06/07 00:18:08
As I mentioned in another comment, the WebIDL spec
benjhayden
2012/06/08 16:41:52
Done.
| |
110 for node in self.node.children: | 112 for node in self.node.children: |
111 if node.cls == 'EnumItem': | 113 if node.cls == 'EnumItem': |
112 name = node.GetName() | 114 value = node.GetProperty('VALUE') |
113 enum.append(name) | 115 if value: |
116 try: | |
117 value = int(value) | |
118 except ValueError: | |
119 try: | |
120 value = float(value) | |
121 enum_type = 'double' | |
122 except ValueError: | |
123 enum_type = 'string' | |
124 else: | |
125 value = node.GetName() | |
126 enum_type = 'string' | |
127 enum.append(value) | |
128 elif node.cls == 'Comment': | |
129 self.description = ProcessComment(node.GetName())[0] | |
114 else: | 130 else: |
115 sys.exit("Did not process %s %s" % (node.cls, node)) | 131 sys.exit('Did not process %s %s' % (node.cls, node)) |
116 return { "id" : self.node.GetName(), | 132 return {'id' : self.node.GetName(), |
117 'enum': enum, | 133 'description': self.description, |
118 'type': 'string' } | 134 'type': enum_type, |
119 | 135 'enum': enum} |
120 | 136 |
121 | 137 |
122 class Member(object): | 138 class Member(object): |
123 ''' | 139 ''' |
124 Given an IDL dictionary or interface member, converts into a name/value pair | 140 Given an IDL dictionary or interface member, converts into a name/value pair |
125 where the value is a Python dictionary that the JSON schema compiler expects | 141 where the value is a Python dictionary that the JSON schema compiler expects |
126 to see. | 142 to see. |
127 ''' | 143 ''' |
128 def __init__(self, member_node): | 144 def __init__(self, member_node): |
129 self.node = member_node | 145 self.node = member_node |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 properties['$ref'] = self.typeref | 225 properties['$ref'] = self.typeref |
210 | 226 |
211 return result | 227 return result |
212 | 228 |
213 class Namespace(object): | 229 class Namespace(object): |
214 ''' | 230 ''' |
215 Given an IDLNode representing an IDL namespace, converts into a Python | 231 Given an IDLNode representing an IDL namespace, converts into a Python |
216 dictionary that the JSON schema compiler expects to see. | 232 dictionary that the JSON schema compiler expects to see. |
217 ''' | 233 ''' |
218 | 234 |
219 def __init__(self, namespace_node, nodoc=False): | 235 def __init__(self, namespace_node, nodoc=False, |
236 permissions=None): | |
220 self.namespace = namespace_node | 237 self.namespace = namespace_node |
221 self.nodoc = nodoc | 238 self.nodoc = nodoc |
222 self.events = [] | 239 self.events = [] |
223 self.functions = [] | 240 self.functions = [] |
224 self.types = [] | 241 self.types = [] |
225 self.callbacks = {} | 242 self.callbacks = {} |
243 self.permissions = permissions or [] | |
226 | 244 |
227 def process(self): | 245 def process(self): |
228 for node in self.namespace.children: | 246 for node in self.namespace.children: |
229 cls = node.cls | 247 cls = node.cls |
230 if cls == "Dictionary": | 248 if cls == 'Dictionary': |
231 self.types.append(Dictionary(node).process(self.callbacks)) | 249 self.types.append(Dictionary(node).process(self.callbacks)) |
232 elif cls == "Callback": | 250 elif cls == 'Callback': |
233 k, v = Member(node).process(self.callbacks) | 251 k, v = Member(node).process(self.callbacks) |
234 self.callbacks[k] = v | 252 self.callbacks[k] = v |
235 elif cls == "Interface" and node.GetName() == "Functions": | 253 elif cls == 'Interface' and node.GetName() == 'Functions': |
236 self.functions = self.process_interface(node) | 254 self.functions = self.process_interface(node) |
237 elif cls == "Interface" and node.GetName() == "Events": | 255 elif cls == 'Interface' and node.GetName() == 'Events': |
238 self.events = self.process_interface(node) | 256 self.events = self.process_interface(node) |
239 elif cls == "Enum": | 257 elif cls == 'Enum': |
240 self.types.append(Enum(node).process(self.callbacks)) | 258 self.types.append(Enum(node).process(self.callbacks)) |
259 elif cls == 'Member': | |
260 name, properties = Member(node).process(self.callbacks) | |
261 self.functions.append(properties) | |
241 else: | 262 else: |
242 sys.exit("Did not process %s %s" % (node.cls, node)) | 263 sys.exit('Did not process %s %s' % (node.cls, node)) |
243 | 264 |
244 return { 'events': self.events, | 265 return {'namespace': self.namespace.GetName(), |
245 'functions': self.functions, | 266 'documentation_permissions_required': self.permissions, |
246 'types': self.types, | 267 'nodoc': self.nodoc, |
247 'namespace': self.namespace.GetName(), | 268 'types': self.types, |
248 'nodoc': self.nodoc } | 269 'events': self.events, |
270 'functions': self.functions} | |
249 | 271 |
250 def process_interface(self, node): | 272 def process_interface(self, node): |
251 members = [] | 273 members = [] |
252 for member in node.children: | 274 for member in node.children: |
253 if member.cls == 'Member': | 275 if member.cls == 'Member': |
254 name, properties = Member(member).process(self.callbacks) | 276 name, properties = Member(member).process(self.callbacks) |
255 members.append(properties) | 277 members.append(properties) |
256 return members | 278 return members |
257 | 279 |
258 class IDLSchema(object): | 280 class IDLSchema(object): |
259 ''' | 281 ''' |
260 Given a list of IDLNodes and IDLAttributes, converts into a Python list | 282 Given a list of IDLNodes and IDLAttributes, converts into a Python list |
261 of api_defs that the JSON schema compiler expects to see. | 283 of api_defs that the JSON schema compiler expects to see. |
262 ''' | 284 ''' |
263 | 285 |
264 def __init__(self, idl): | 286 def __init__(self, idl): |
265 self.idl = idl | 287 self.idl = idl |
266 | 288 |
267 def process(self): | 289 def process(self): |
268 namespaces = [] | 290 namespaces = [] |
291 nodoc = False | |
292 permissions = None | |
269 for node in self.idl: | 293 for node in self.idl: |
270 nodoc = False | |
271 cls = node.cls | 294 cls = node.cls |
272 if cls == 'Namespace': | 295 if cls == 'Namespace': |
273 namespace = Namespace(node, nodoc) | 296 namespace = Namespace(node, nodoc, permissions) |
274 namespaces.append(namespace.process()) | 297 namespaces.append(namespace.process()) |
275 elif cls == 'Copyright': | 298 elif cls in ['Copyright', 'Comment']: |
276 continue | |
277 elif cls == 'Comment': | |
278 continue | 299 continue |
279 elif cls == 'ExtAttribute': | 300 elif cls == 'ExtAttribute': |
280 if node.name == 'nodoc': | 301 if node.name == 'nodoc': |
281 nodoc = bool(node.value) | 302 nodoc = bool(node.value) |
303 elif node.name == 'permissions': | |
304 permissions = node.value.split(',') | |
282 else: | 305 else: |
283 continue | 306 continue |
284 else: | 307 else: |
285 sys.exit("Did not process %s %s" % (node.cls, node)) | 308 sys.exit('Did not process %s %s' % (node.cls, node)) |
286 schema_util.PrefixSchemasWithNamespace(namespaces) | 309 schema_util.PrefixSchemasWithNamespace(namespaces) |
287 return namespaces | 310 return namespaces |
288 | 311 |
289 def Load(filename): | 312 def Load(filename): |
290 ''' | 313 ''' |
291 Given the filename of an IDL file, parses it and returns an equivalent | 314 Given the filename of an IDL file, parses it and returns an equivalent |
292 Python dictionary in a format that the JSON schema compiler expects to see. | 315 Python dictionary in a format that the JSON schema compiler expects to see. |
293 ''' | 316 ''' |
294 | 317 |
295 f = open(filename, 'r') | 318 f = open(filename, 'r') |
296 contents = f.read() | 319 contents = f.read() |
297 f.close() | 320 f.close() |
298 | 321 |
299 idl = idl_parser.IDLParser().ParseData(contents, filename) | 322 idl = idl_parser.IDLParser().ParseData(contents, filename) |
300 idl_schema = IDLSchema(idl) | 323 idl_schema = IDLSchema(idl) |
301 return idl_schema.process() | 324 return idl_schema.process() |
302 | 325 |
303 def Main(): | 326 def Main(): |
304 ''' | 327 ''' |
305 Dump a json serialization of parse result for the IDL files whose names | 328 Dump a json serialization of parse result for the IDL files whose names |
306 were passed in on the command line. | 329 were passed in on the command line. |
307 ''' | 330 ''' |
308 for filename in sys.argv[1:]: | 331 for filename in sys.argv[1:]: |
309 schema = Load(filename) | 332 schema = Load(filename) |
310 print json.dumps(schema, indent=2) | 333 print json.dumps(schema, indent=2) |
311 | 334 |
312 if __name__ == '__main__': | 335 if __name__ == '__main__': |
313 Main() | 336 Main() |
OLD | NEW |