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

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

Issue 10080014: Fix a bug in IDL parsing related to arrays of callbacks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added in test file Created 8 years, 8 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
« no previous file with comments | « no previous file | tools/json_schema_compiler/idl_schema_test.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/env python
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # 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
3 # found in the LICENSE file. 4 # found in the LICENSE file.
4 5
6 import json
5 import os.path 7 import os.path
6 import sys 8 import sys
7 9
8 # This file is a peer to json_schema.py. Each of these files understands a 10 # This file is a peer to json_schema.py. Each of these files understands a
9 # certain format describing APIs (either JSON or IDL), reads files written 11 # certain format describing APIs (either JSON or IDL), reads files written
10 # in that format into memory, and emits them as a Python array of objects 12 # in that format into memory, and emits them as a Python array of objects
11 # corresponding to those APIs, where the objects are formatted in a way that 13 # corresponding to those APIs, where the objects are formatted in a way that
12 # the JSON schema compiler understands. compiler.py drives both idl_schema.py 14 # the JSON schema compiler understands. compiler.py drives both idl_schema.py
13 # and json_schema.py. 15 # and json_schema.py.
14 16
15 # idl_parser expects to be able to import certain files in its directory, 17 # idl_parser expects to be able to import certain files in its directory,
16 # so let's set things up the way it wants. 18 # so let's set things up the way it wants.
17 idl_generators_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 19 idl_generators_path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
18 os.pardir, os.pardir, 'ppapi', 'generators') 20 os.pardir, os.pardir, 'ppapi', 'generators')
19 if idl_generators_path not in sys.path: 21 if idl_generators_path not in sys.path:
20 sys.path.insert(0, idl_generators_path) 22 sys.path.insert(0, idl_generators_path)
21 import idl_parser 23 import idl_parser
22 24
23 class Callspec(object): 25 class Callspec(object):
24 ''' 26 '''
25 Given a Callspec node representing an IDL function declaration, converts into 27 Given a Callspec node representing an IDL function declaration, converts into
26 a name/value pair where the value is a list of function parameters. 28 a name/value pair where the value is a list of function parameters.
27 ''' 29 '''
28 def __init__(self, callspec_node): 30 def __init__(self, callspec_node):
29 self.node = callspec_node 31 self.node = callspec_node
30 32
31 def process(self, refs): 33 def process(self, callbacks):
32 parameters = [] 34 parameters = []
33 for node in self.node.children: 35 for node in self.node.children:
34 parameters.append(Param(node).process(refs)) 36 parameters.append(Param(node).process(callbacks))
35 return self.node.GetName(), parameters 37 return self.node.GetName(), parameters
36 38
37 class Param(object): 39 class Param(object):
38 ''' 40 '''
39 Given a Param node representing a function parameter, converts into a Python 41 Given a Param node representing a function parameter, converts into a Python
40 dictionary that the JSON schema compiler expects to see. 42 dictionary that the JSON schema compiler expects to see.
41 ''' 43 '''
42 def __init__(self, param_node): 44 def __init__(self, param_node):
43 self.node = param_node 45 self.node = param_node
44 46
45 def process(self, refs): 47 def process(self, callbacks):
46 return Typeref(self.node.GetProperty( 'TYPEREF'), 48 return Typeref(self.node.GetProperty( 'TYPEREF'),
47 self.node, 49 self.node,
48 { 'name': self.node.GetName() }).process(refs) 50 { 'name': self.node.GetName() }).process(callbacks)
49 51
50 class Dictionary(object): 52 class Dictionary(object):
51 ''' 53 '''
52 Given an IDL Dictionary node, converts into a Python dictionary that the JSON 54 Given an IDL Dictionary node, converts into a Python dictionary that the JSON
53 schema compiler expects to see. 55 schema compiler expects to see.
54 ''' 56 '''
55 def __init__(self, dictionary_node): 57 def __init__(self, dictionary_node):
56 self.node = dictionary_node 58 self.node = dictionary_node
57 59
58 def process(self, refs): 60 def process(self, callbacks):
59 properties = {} 61 properties = {}
60 for node in self.node.children: 62 for node in self.node.children:
61 if node.cls == 'Member': 63 if node.cls == 'Member':
62 k, v = Member(node).process(refs) 64 k, v = Member(node).process(callbacks)
63 properties[k] = v 65 properties[k] = v
64 return { 'id': self.node.GetName(), 66 return { 'id': self.node.GetName(),
65 'properties': properties, 67 'properties': properties,
66 'type': 'object' } 68 'type': 'object' }
67 69
68 class Member(object): 70 class Member(object):
69 ''' 71 '''
70 Given an IDL dictionary or interface member, converts into a name/value pair 72 Given an IDL dictionary or interface member, converts into a name/value pair
71 where the value is a Python dictionary that the JSON schema compiler expects 73 where the value is a Python dictionary that the JSON schema compiler expects
72 to see. 74 to see.
73 ''' 75 '''
74 def __init__(self, member_node): 76 def __init__(self, member_node):
75 self.node = member_node 77 self.node = member_node
76 78
77 def process(self, refs): 79 def process(self, callbacks):
78 properties = {} 80 properties = {}
79 name = self.node.GetName() 81 name = self.node.GetName()
80 if self.node.GetProperty('OPTIONAL'): 82 if self.node.GetProperty('OPTIONAL'):
81 properties['optional'] = True 83 properties['optional'] = True
82 if self.node.GetProperty('nodoc'): 84 if self.node.GetProperty('nodoc'):
83 properties['nodoc'] = True 85 properties['nodoc'] = True
84 is_function = False 86 is_function = False
85 for node in self.node.children: 87 for node in self.node.children:
86 if node.cls == 'Callspec': 88 if node.cls == 'Callspec':
87 is_function = True 89 is_function = True
88 name, parameters = Callspec(node).process(refs) 90 name, parameters = Callspec(node).process(callbacks)
89 properties['parameters'] = parameters 91 properties['parameters'] = parameters
90 properties['name'] = name 92 properties['name'] = name
91 if is_function: 93 if is_function:
92 properties['type'] = 'function' 94 properties['type'] = 'function'
93 else: 95 else:
94 properties = Typeref(self.node.GetProperty('TYPEREF'), 96 properties = Typeref(self.node.GetProperty('TYPEREF'),
95 self.node, properties).process(refs) 97 self.node, properties).process(callbacks)
96 return name, properties 98 return name, properties
97 99
98 class Typeref(object): 100 class Typeref(object):
99 ''' 101 '''
100 Given a TYPEREF property representing the type of dictionary member or 102 Given a TYPEREF property representing the type of dictionary member or
101 function parameter, converts into a Python dictionary that the JSON schema 103 function parameter, converts into a Python dictionary that the JSON schema
102 compiler expects to see. 104 compiler expects to see.
103 ''' 105 '''
104 def __init__(self, typeref, parent, additional_properties={}): 106 def __init__(self, typeref, parent, additional_properties={}):
105 self.typeref = typeref 107 self.typeref = typeref
106 self.parent = parent 108 self.parent = parent
107 self.additional_properties = additional_properties 109 self.additional_properties = additional_properties
108 110
109 def process(self, refs): 111 def process(self, callbacks):
110 properties = self.additional_properties 112 properties = self.additional_properties
111 result = properties 113 result = properties
112 114
113 if self.parent.GetProperty('OPTIONAL', False): 115 if self.parent.GetProperty('OPTIONAL', False):
114 properties['optional'] = True 116 properties['optional'] = True
115 117
116 # The IDL parser denotes array types by adding a child 'Array' node onto 118 # The IDL parser denotes array types by adding a child 'Array' node onto
117 # the Param node in the Callspec. 119 # the Param node in the Callspec.
118 for sibling in self.parent.GetChildren(): 120 for sibling in self.parent.GetChildren():
119 if sibling.cls == 'Array' and sibling.GetName() == self.parent.GetName(): 121 if sibling.cls == 'Array' and sibling.GetName() == self.parent.GetName():
(...skipping 14 matching lines...) Expand all
134 properties['type'] = 'object' 136 properties['type'] = 'object'
135 if 'additionalProperties' not in properties: 137 if 'additionalProperties' not in properties:
136 properties['additionalProperties'] = {} 138 properties['additionalProperties'] = {}
137 properties['additionalProperties']['type'] = 'any' 139 properties['additionalProperties']['type'] = 'any'
138 instance_of = self.parent.GetProperty('instanceOf') 140 instance_of = self.parent.GetProperty('instanceOf')
139 if instance_of: 141 if instance_of:
140 properties['isInstanceOf'] = instance_of 142 properties['isInstanceOf'] = instance_of
141 elif self.typeref is None: 143 elif self.typeref is None:
142 properties['type'] = 'function' 144 properties['type'] = 'function'
143 else: 145 else:
144 try: 146 if self.typeref in callbacks:
145 result = refs[self.typeref] 147 properties.update(callbacks[self.typeref])
146 except KeyError, e: 148 else:
147 properties['$ref'] = self.typeref 149 properties['$ref'] = self.typeref
148 150
149 return result 151 return result
150 152
151 class Namespace(object): 153 class Namespace(object):
152 ''' 154 '''
153 Given an IDLNode representing an IDL namespace, converts into a Python 155 Given an IDLNode representing an IDL namespace, converts into a Python
154 dictionary that the JSON schema compiler expects to see. 156 dictionary that the JSON schema compiler expects to see.
155 ''' 157 '''
156 158
157 def __init__(self, namespace_node, nodoc=False): 159 def __init__(self, namespace_node, nodoc=False):
158 self.namespace = namespace_node 160 self.namespace = namespace_node
159 self.nodoc = nodoc 161 self.nodoc = nodoc
160 self.events = [] 162 self.events = []
161 self.functions = [] 163 self.functions = []
162 self.types = [] 164 self.types = []
163 self.refs = {} 165 self.callbacks = {}
164 166
165 def process(self): 167 def process(self):
166 for node in self.namespace.children: 168 for node in self.namespace.children:
167 cls = node.cls 169 cls = node.cls
168 if cls == "Dictionary": 170 if cls == "Dictionary":
169 self.types.append(Dictionary(node).process(self.refs)) 171 self.types.append(Dictionary(node).process(self.callbacks))
170 elif cls == "Callback": 172 elif cls == "Callback":
171 k, v = Member(node).process(self.refs) 173 k, v = Member(node).process(self.callbacks)
172 self.refs[k] = v 174 self.callbacks[k] = v
173 elif cls == "Interface" and node.GetName() == "Functions": 175 elif cls == "Interface" and node.GetName() == "Functions":
174 self.functions = self.process_interface(node) 176 self.functions = self.process_interface(node)
175 elif cls == "Interface" and node.GetName() == "Events": 177 elif cls == "Interface" and node.GetName() == "Events":
176 self.events = self.process_interface(node) 178 self.events = self.process_interface(node)
177 else: 179 else:
178 sys.exit("Did not process %s %s" % (node.cls, node)) 180 sys.exit("Did not process %s %s" % (node.cls, node))
179 181
180 return { 'events': self.events, 182 return { 'events': self.events,
181 'functions': self.functions, 183 'functions': self.functions,
182 'types': self.types, 184 'types': self.types,
183 'namespace': self.namespace.GetName(), 185 'namespace': self.namespace.GetName(),
184 'nodoc': self.nodoc } 186 'nodoc': self.nodoc }
185 187
186 def process_interface(self, node): 188 def process_interface(self, node):
187 members = [] 189 members = []
188 for member in node.children: 190 for member in node.children:
189 if member.cls == 'Member': 191 if member.cls == 'Member':
190 name, properties = Member(member).process(self.refs) 192 name, properties = Member(member).process(self.callbacks)
191 members.append(properties) 193 members.append(properties)
192 return members 194 return members
193 195
194 class IDLSchema(object): 196 class IDLSchema(object):
195 ''' 197 '''
196 Given a list of IDLNodes and IDLAttributes, converts into a Python list 198 Given a list of IDLNodes and IDLAttributes, converts into a Python list
197 of api_defs that the JSON schema compiler expects to see. 199 of api_defs that the JSON schema compiler expects to see.
198 ''' 200 '''
199 201
200 def __init__(self, idl): 202 def __init__(self, idl):
(...skipping 26 matching lines...) Expand all
227 Python dictionary in a format that the JSON schema compiler expects to see. 229 Python dictionary in a format that the JSON schema compiler expects to see.
228 ''' 230 '''
229 231
230 f = open(filename, 'r') 232 f = open(filename, 'r')
231 contents = f.read() 233 contents = f.read()
232 f.close() 234 f.close()
233 235
234 idl = idl_parser.IDLParser().ParseData(contents, filename) 236 idl = idl_parser.IDLParser().ParseData(contents, filename)
235 idl_schema = IDLSchema(idl) 237 idl_schema = IDLSchema(idl)
236 return idl_schema.process() 238 return idl_schema.process()
239
240 def Main():
241 '''
242 Dump a json serialization of parse result for the IDL files whose names
243 were passed in on the command line.
244 '''
245 for filename in sys.argv[1:]:
246 schema = Load(filename)
247 print json.dumps(schema, indent=2)
248
249 if __name__ == '__main__':
250 Main()
OLDNEW
« no previous file with comments | « no previous file | tools/json_schema_compiler/idl_schema_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698