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

Side by Side Diff: tools/json_schema_compiler/idl_schema.py

Issue 9617010: Move chrome.downloads out of experimental to dev (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 6 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
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
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 17 matching lines...) Expand all
68 68
69 class Param(object): 69 class Param(object):
70 ''' 70 '''
71 Given a Param node representing a function parameter, converts into a Python 71 Given a Param node representing a function parameter, converts into a Python
72 dictionary that the JSON schema compiler expects to see. 72 dictionary that the JSON schema compiler expects to see.
73 ''' 73 '''
74 def __init__(self, param_node): 74 def __init__(self, param_node):
75 self.node = param_node 75 self.node = param_node
76 76
77 def process(self, callbacks): 77 def process(self, callbacks):
78 return Typeref(self.node.GetProperty( 'TYPEREF'), 78 return Typeref(self.node.GetProperty('TYPEREF'),
79 self.node, 79 self.node,
80 { 'name': self.node.GetName() }).process(callbacks) 80 {'name': self.node.GetName()}).process(callbacks)
81 81
82 class Dictionary(object): 82 class Dictionary(object):
83 ''' 83 '''
84 Given an IDL Dictionary node, converts into a Python dictionary that the JSON 84 Given an IDL Dictionary node, converts into a Python dictionary that the JSON
85 schema compiler expects to see. 85 schema compiler expects to see.
86 ''' 86 '''
87 def __init__(self, dictionary_node): 87 def __init__(self, dictionary_node):
88 self.node = dictionary_node 88 self.node = dictionary_node
89 89
90 def process(self, callbacks): 90 def process(self, callbacks):
91 properties = {} 91 properties = {}
92 for node in self.node.children: 92 for node in self.node.children:
93 if node.cls == 'Member': 93 if node.cls == 'Member':
94 k, v = Member(node).process(callbacks) 94 k, v = Member(node).process(callbacks)
95 properties[k] = v 95 properties[k] = v
96 return { 'id': self.node.GetName(), 96 result = {'id': self.node.GetName(),
97 'properties': properties, 97 'properties': properties,
98 'type': 'object' } 98 'type': 'object'}
99 99 if self.node.GetProperty('nodoc'):
100 class Enum(object): 100 result['nodoc'] = True
101 ''' 101 return result
102 Given an IDL Enum node, converts into a Python dictionary that the JSON
103 schema compiler expects to see.
104 '''
105 def __init__(self, enum_node):
106 self.node = enum_node
107
108 def process(self, callbacks):
109 enum = []
110 for node in self.node.children:
111 if node.cls == 'EnumItem':
112 name = node.GetName()
113 enum.append(name)
114 else:
115 sys.exit("Did not process %s %s" % (node.cls, node))
116 return { "id" : self.node.GetName(),
117 'enum': enum,
118 'type': 'string' }
119
120
121 102
122 class Member(object): 103 class Member(object):
123 ''' 104 '''
124 Given an IDL dictionary or interface member, converts into a name/value pair 105 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 106 where the value is a Python dictionary that the JSON schema compiler expects
126 to see. 107 to see.
127 ''' 108 '''
128 def __init__(self, member_node): 109 def __init__(self, member_node):
129 self.node = member_node 110 self.node = member_node
130 111
131 def process(self, callbacks): 112 def process(self, callbacks):
132 properties = {} 113 properties = {}
133 name = self.node.GetName() 114 name = self.node.GetName()
134 for property_name in ('OPTIONAL', 'nodoc', 'nocompile'): 115 for property_name in ('OPTIONAL', 'nodoc', 'nocompile', 'inline_doc'):
135 if self.node.GetProperty(property_name): 116 if self.node.GetProperty(property_name):
136 properties[property_name.lower()] = True 117 properties[property_name.lower()] = True
137 is_function = False 118 is_function = False
138 parameter_comments = {} 119 parameter_comments = {}
139 for node in self.node.children: 120 for node in self.node.children:
140 if node.cls == 'Comment': 121 if node.cls == 'Comment':
141 (parent_comment, parameter_comments) = ProcessComment(node.GetName()) 122 (parent_comment, parameter_comments) = ProcessComment(node.GetName())
142 properties['description'] = parent_comment 123 properties['description'] = parent_comment
143 for node in self.node.children: 124 elif node.cls == 'Callspec':
144 if node.cls == 'Callspec':
145 is_function = True 125 is_function = True
146 name, parameters = Callspec(node, parameter_comments).process(callbacks) 126 name, parameters = Callspec(node, parameter_comments).process(callbacks)
147 properties['parameters'] = parameters 127 properties['parameters'] = parameters
148 properties['name'] = name 128 properties['name'] = name
149 if is_function: 129 if is_function:
150 properties['type'] = 'function' 130 properties['type'] = 'function'
151 else: 131 else:
152 properties = Typeref(self.node.GetProperty('TYPEREF'), 132 properties = Typeref(self.node.GetProperty('TYPEREF'),
153 self.node, properties).process(callbacks) 133 self.node, properties).process(callbacks)
134 enum_values = self.node.GetProperty('legalValues')
135 if enum_values:
136 if properties['type'] == 'integer':
137 enum_values = map(int, enum_values)
138 elif properties['type'] == 'double':
139 enum_values = map(float, enum_values)
140 properties['enum'] = enum_values
154 return name, properties 141 return name, properties
155 142
156 class Typeref(object): 143 class Typeref(object):
157 ''' 144 '''
158 Given a TYPEREF property representing the type of dictionary member or 145 Given a TYPEREF property representing the type of dictionary member or
159 function parameter, converts into a Python dictionary that the JSON schema 146 function parameter, converts into a Python dictionary that the JSON schema
160 compiler expects to see. 147 compiler expects to see.
161 ''' 148 '''
162 def __init__(self, typeref, parent, additional_properties={}): 149 def __init__(self, typeref, parent, additional_properties={}):
163 self.typeref = typeref 150 self.typeref = typeref
164 self.parent = parent 151 self.parent = parent
165 self.additional_properties = additional_properties 152 self.additional_properties = additional_properties
166 153
167 def process(self, callbacks): 154 def process(self, callbacks):
168 properties = self.additional_properties 155 properties = self.additional_properties
169 result = properties 156 result = properties
170 157
171 if self.parent.GetProperty('OPTIONAL', False): 158 if self.parent.GetProperty('OPTIONAL', False):
172 properties['optional'] = True 159 properties['optional'] = True
160 if self.parent.GetProperty('inline_doc', False):
161 properties['inline_doc'] = True
173 162
174 # The IDL parser denotes array types by adding a child 'Array' node onto 163 # The IDL parser denotes array types by adding a child 'Array' node onto
175 # the Param node in the Callspec. 164 # the Param node in the Callspec.
176 for sibling in self.parent.GetChildren(): 165 for sibling in self.parent.GetChildren():
177 if sibling.cls == 'Array' and sibling.GetName() == self.parent.GetName(): 166 if sibling.cls == 'Array' and sibling.GetName() == self.parent.GetName():
178 properties['type'] = 'array' 167 properties['type'] = 'array'
179 properties['items'] = {} 168 properties['items'] = {}
180 properties = properties['items'] 169 properties = properties['items']
181 break 170 break
182 171
(...skipping 20 matching lines...) Expand all
203 elif self.typeref is None: 192 elif self.typeref is None:
204 properties['type'] = 'function' 193 properties['type'] = 'function'
205 else: 194 else:
206 if self.typeref in callbacks: 195 if self.typeref in callbacks:
207 properties.update(callbacks[self.typeref]) 196 properties.update(callbacks[self.typeref])
208 else: 197 else:
209 properties['$ref'] = self.typeref 198 properties['$ref'] = self.typeref
210 199
211 return result 200 return result
212 201
202
203 class Enum(object):
204 '''
205 Given an IDL Enum node, converts into a Python dictionary that the JSON
206 schema compiler expects to see.
207 '''
208 def __init__(self, enum_node):
209 self.node = enum_node
210 self.description = ''
211
212 def process(self, callbacks):
213 enum = []
214 for node in self.node.children:
215 if node.cls == 'EnumItem':
216 enum.append(node.GetName())
217 elif node.cls == 'Comment':
218 self.description = ProcessComment(node.GetName())[0]
219 else:
220 sys.exit('Did not process %s %s' % (node.cls, node))
221 return {'id' : self.node.GetName(),
222 'description': self.description,
223 'type': 'string',
224 'enum': enum}
225
226
213 class Namespace(object): 227 class Namespace(object):
214 ''' 228 '''
215 Given an IDLNode representing an IDL namespace, converts into a Python 229 Given an IDLNode representing an IDL namespace, converts into a Python
216 dictionary that the JSON schema compiler expects to see. 230 dictionary that the JSON schema compiler expects to see.
217 ''' 231 '''
218 232
219 def __init__(self, namespace_node, nodoc=False): 233 def __init__(self, namespace_node, nodoc=False,
234 permissions=None):
220 self.namespace = namespace_node 235 self.namespace = namespace_node
221 self.nodoc = nodoc 236 self.nodoc = nodoc
222 self.events = [] 237 self.events = []
223 self.functions = [] 238 self.functions = []
224 self.types = [] 239 self.types = []
225 self.callbacks = {} 240 self.callbacks = {}
241 self.permissions = permissions or []
226 242
227 def process(self): 243 def process(self):
228 for node in self.namespace.children: 244 for node in self.namespace.children:
229 cls = node.cls 245 if node.cls == 'Dictionary':
230 if cls == "Dictionary":
231 self.types.append(Dictionary(node).process(self.callbacks)) 246 self.types.append(Dictionary(node).process(self.callbacks))
232 elif cls == "Callback": 247 elif node.cls == 'Callback':
233 k, v = Member(node).process(self.callbacks) 248 k, v = Member(node).process(self.callbacks)
234 self.callbacks[k] = v 249 self.callbacks[k] = v
235 elif cls == "Interface" and node.GetName() == "Functions": 250 elif node.cls == 'Interface' and node.GetName() == 'Functions':
236 self.functions = self.process_interface(node) 251 self.functions = self.process_interface(node)
237 elif cls == "Interface" and node.GetName() == "Events": 252 elif node.cls == 'Interface' and node.GetName() == 'Events':
238 self.events = self.process_interface(node) 253 self.events = self.process_interface(node)
239 elif cls == "Enum": 254 elif node.cls == 'Enum':
240 self.types.append(Enum(node).process(self.callbacks)) 255 self.types.append(Enum(node).process(self.callbacks))
256 elif node.cls == 'Member':
257 name, properties = Member(node).process(self.callbacks)
258 self.functions.append(properties)
241 else: 259 else:
242 sys.exit("Did not process %s %s" % (node.cls, node)) 260 sys.exit('Did not process %s %s' % (node.cls, node))
243 261
244 return { 'events': self.events, 262 return {'namespace': self.namespace.GetName(),
245 'functions': self.functions, 263 'documentation_permissions_required': self.permissions,
246 'types': self.types, 264 'nodoc': self.nodoc,
247 'namespace': self.namespace.GetName(), 265 'types': self.types,
248 'nodoc': self.nodoc } 266 'events': self.events,
267 'functions': self.functions}
249 268
250 def process_interface(self, node): 269 def process_interface(self, node):
251 members = [] 270 members = []
252 for member in node.children: 271 for member in node.children:
253 if member.cls == 'Member': 272 if member.cls == 'Member':
254 name, properties = Member(member).process(self.callbacks) 273 name, properties = Member(member).process(self.callbacks)
255 members.append(properties) 274 members.append(properties)
256 return members 275 return members
257 276
258 class IDLSchema(object): 277 class IDLSchema(object):
259 ''' 278 '''
260 Given a list of IDLNodes and IDLAttributes, converts into a Python list 279 Given a list of IDLNodes and IDLAttributes, converts into a Python list
261 of api_defs that the JSON schema compiler expects to see. 280 of api_defs that the JSON schema compiler expects to see.
262 ''' 281 '''
263 282
264 def __init__(self, idl): 283 def __init__(self, idl):
265 self.idl = idl 284 self.idl = idl
266 285
267 def process(self): 286 def process(self):
268 namespaces = [] 287 namespaces = []
288 nodoc = False
289 permissions = None
269 for node in self.idl: 290 for node in self.idl:
270 nodoc = False 291 if node.cls == 'Namespace':
271 cls = node.cls 292 namespace = Namespace(node, nodoc, permissions)
272 if cls == 'Namespace':
273 namespace = Namespace(node, nodoc)
274 namespaces.append(namespace.process()) 293 namespaces.append(namespace.process())
275 elif cls == 'Copyright': 294 elif node.cls in ['Copyright', 'Comment']:
276 continue 295 continue
277 elif cls == 'Comment': 296 elif node.cls == 'ExtAttribute':
278 continue
279 elif cls == 'ExtAttribute':
280 if node.name == 'nodoc': 297 if node.name == 'nodoc':
281 nodoc = bool(node.value) 298 nodoc = bool(node.value)
299 elif node.name == 'permissions':
300 permissions = node.value.split(',')
282 else: 301 else:
283 continue 302 continue
284 else: 303 else:
285 sys.exit("Did not process %s %s" % (node.cls, node)) 304 sys.exit('Did not process %s %s' % (node.cls, node))
286 schema_util.PrefixSchemasWithNamespace(namespaces) 305 schema_util.PrefixSchemasWithNamespace(namespaces)
287 return namespaces 306 return namespaces
288 307
289 def Load(filename): 308 def Load(filename):
290 ''' 309 '''
291 Given the filename of an IDL file, parses it and returns an equivalent 310 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. 311 Python dictionary in a format that the JSON schema compiler expects to see.
293 ''' 312 '''
294 313
295 f = open(filename, 'r') 314 f = open(filename, 'r')
296 contents = f.read() 315 contents = f.read()
297 f.close() 316 f.close()
298 317
299 idl = idl_parser.IDLParser().ParseData(contents, filename) 318 idl = idl_parser.IDLParser().ParseData(contents, filename)
300 idl_schema = IDLSchema(idl) 319 idl_schema = IDLSchema(idl)
301 return idl_schema.process() 320 return idl_schema.process()
302 321
303 def Main(): 322 def Main():
304 ''' 323 '''
305 Dump a json serialization of parse result for the IDL files whose names 324 Dump a json serialization of parse result for the IDL files whose names
306 were passed in on the command line. 325 were passed in on the command line.
307 ''' 326 '''
308 for filename in sys.argv[1:]: 327 for filename in sys.argv[1:]:
309 schema = Load(filename) 328 schema = Load(filename)
310 print json.dumps(schema, indent=2) 329 print json.dumps(schema, indent=2)
311 330
312 if __name__ == '__main__': 331 if __name__ == '__main__':
313 Main() 332 Main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698