OLD | NEW |
| 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 Loading... |
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 Loading... |
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() |
OLD | NEW |