OLD | NEW |
---|---|
(Empty) | |
1 # Copyright (C) 2013 Google Inc. All rights reserved. | |
2 # | |
3 # Redistribution and use in source and binary forms, with or without | |
4 # modification, are permitted provided that the following conditions are | |
5 # met: | |
6 # | |
7 # * Redistributions of source code must retain the above copyright | |
8 # notice, this list of conditions and the following disclaimer. | |
9 # * Redistributions in binary form must reproduce the above | |
10 # copyright notice, this list of conditions and the following disclaimer | |
11 # in the documentation and/or other materials provided with the | |
12 # distribution. | |
13 # * Neither the name of Google Inc. nor the names of its | |
14 # contributors may be used to endorse or promote products derived from | |
15 # this software without specific prior written permission. | |
16 # | |
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | |
29 """Read an IDL file or complete IDL interface, producing an IdlDefinitions objec t.""" | |
haraken
2013/07/17 02:44:49
Slightly better: "Build an IdlDefinitions object f
Nils Barth (inactive)
2013/07/17 12:05:09
Oops, you’re right (this was the idl_reader commen
| |
30 | |
31 from idl_definitions import IdlDefinitions, IdlInterface, IdlException, IdlOpera tion, IdlCallbackFunction, IdlArgument, IdlAttribute, IdlConstant, IdlEnum, IdlT ypedef, IdlUnionType | |
32 | |
33 SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER'] | |
34 | |
35 | |
36 def file_node_to_idl_definitions(node): | |
haraken
2013/07/17 02:44:49
For readability, I might want to add one more help
Nils Barth (inactive)
2013/07/17 12:05:09
You’re right, that’s clearer.
I actually had this
| |
37 if node is None: | |
38 return None | |
39 node_class = node.GetClass() | |
40 if node_class != 'File': | |
41 raise ValueError('Unrecognized node class: %s' % node_class) | |
42 callback_functions = [] | |
43 enumerations = [] | |
44 exceptions = {} | |
45 file_name = node.GetName() # FIXME: only needed for Perl, remove later | |
46 interfaces = {} | |
47 typedefs = {} | |
48 | |
49 children = node.GetChildren() | |
50 for child in children: | |
51 child_class = child.GetClass() | |
52 if child_class == 'Interface': | |
53 interface = interface_node_to_idl_interface(child) | |
54 interfaces[interface.name] = interface | |
55 elif child_class == 'Exception': | |
56 exception = exception_node_to_idl_exception(child) | |
57 exceptions[exception.name] = exception | |
58 elif child_class == 'Typedef': | |
59 type_name = child.GetName() | |
60 typedefs[type_name] = typedef_node_to_idl_typedef(child) | |
61 elif child_class == 'Enum': | |
62 enumerations.append(enum_node_to_idl_enum(child)) | |
63 elif child_class == 'Callback': | |
64 callback_functions.append(callback_node_to_idl_callback_function(chi ld)) | |
65 elif child_class == 'Implements': | |
66 # Implements is handled at the interface merging step | |
67 pass | |
haraken
2013/07/17 02:44:49
Help me understand: Why can we skip 'Implements'?
Nils Barth (inactive)
2013/07/17 12:05:09
We should probably handle Implements differently (
| |
68 else: | |
69 raise ValueError('Unrecognized node class: %s' % child_class) | |
70 | |
71 return IdlDefinitions(callback_functions=callback_functions, enumerations=en umerations, exceptions=exceptions, file_name=file_name, interfaces=interfaces, typedefs=typedefs) | |
haraken
2013/07/17 02:44:49
Nit: One unnecessary space before file_name.
Nils Barth (inactive)
2013/07/17 12:05:09
(>.<) Fixed.
| |
72 | |
73 # Interface | |
74 | |
75 | |
76 def interface_node_to_idl_interface(node): | |
77 attributes = [] | |
78 constants = [] | |
79 constructors = None | |
80 custom_constructors = None | |
81 extended_attributes = None | |
82 functions = [] | |
83 is_callback = node.GetProperty('CALLBACK') or False | |
84 # FIXME: uppercase 'Partial' in base IDL parser | |
85 is_partial = node.GetProperty('Partial') or False | |
86 name = node.GetName() | |
87 parent = None | |
88 | |
89 children = node.GetChildren() | |
90 for child in children: | |
91 child_class = child.GetClass() | |
92 if child_class == 'Attribute': | |
93 attribute = attribute_node_to_idl_attribute(child) | |
94 clear_constructor_attributes(attribute.extended_attributes) | |
haraken
2013/07/17 02:44:49
Would you add the following FIXME?
FIXME: This
Nils Barth (inactive)
2013/07/17 12:05:09
Done.
Thanks for explaining why we have this!
| |
95 attributes.append(attribute) | |
96 elif child_class == 'Const': | |
97 constants.append(constant_node_to_idl_constant(child)) | |
98 elif child_class == 'ExtAttributes': | |
99 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld) | |
haraken
2013/07/17 02:44:49
Don't you need to call clear_constructor_attribute
Nils Barth (inactive)
2013/07/17 12:05:09
The clearing is done as part of extended_attribute
| |
100 constructors, custom_constructors = extended_attributes_to_construct ors(extended_attributes) | |
101 elif child_class == 'Operation': | |
102 functions.append(operation_node_to_idl_operation(child)) | |
103 elif child_class == 'Inherit': | |
104 parent = child.GetName() | |
105 elif child_class == 'ExceptionFieldToString': | |
haraken
2013/07/17 02:44:49
I don't fully understand why this is needed.
Nils Barth (inactive)
2013/07/17 12:05:09
(See above; this is a single special-case Operatio
| |
106 functions.append(exception_field_to_string_node_to_idl_operation(chi ld)) | |
107 else: | |
108 raise ValueError('Unrecognized node class: %s' % child_class) | |
109 | |
110 return IdlInterface(name=name, attributes=attributes, constants=constants, c onstructors=constructors, custom_constructors=custom_constructors, extended_attr ibutes=extended_attributes, functions=functions, is_callback=is_callback, is_par tial=is_partial, parent=parent) | |
111 | |
112 | |
113 def attribute_node_to_idl_attribute(node): | |
114 data_type = None | |
115 extended_attributes = {} | |
116 is_nullable = False | |
117 is_read_only = node.GetProperty('READONLY') or False | |
118 is_static = node.GetProperty('STATIC') or False | |
119 name = node.GetName() | |
120 | |
121 children = node.GetChildren() | |
122 for child in children: | |
123 child_class = child.GetClass() | |
124 if child_class == 'Type': | |
125 data_type = type_node_to_type(child) | |
126 is_nullable = child.GetProperty('NULLABLE') or False | |
127 elif child_class == 'ExtAttributes': | |
128 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld) | |
129 else: | |
130 raise ValueError('Unrecognized node class: %s' % child_class) | |
131 | |
132 return IdlAttribute(data_type=data_type, extended_attributes=extended_attrib utes, is_nullable=is_nullable, is_read_only=is_read_only, is_static=is_static, n ame=name) | |
133 | |
134 | |
135 def constant_node_to_idl_constant(node): | |
136 name = node.GetName() | |
137 | |
138 children = node.GetChildren() | |
139 num_children = len(children) | |
haraken
2013/07/17 02:44:49
Shall we check that num_children > 1 ?
Nils Barth (inactive)
2013/07/17 12:05:09
Good point.
It would have thrown an error later, b
| |
140 if num_children > 3: | |
141 raise ValueError('Expected at most 3 children, got %s' % num_children) | |
142 | |
143 type_node = children[0] | |
144 data_type = type_node_inner_to_type(type_node) | |
145 | |
146 value_node = children[1] | |
147 value_node_class = value_node.GetClass() | |
148 if value_node_class != 'Value': | |
149 raise ValueError('Expected Value node, got %s' % value_node_class) | |
150 value = value_node.GetName() | |
151 | |
152 extended_attributes = None | |
153 if num_children == 3: | |
154 ext_attributes_node = children[2] | |
155 extended_attributes = ext_attributes_node_to_extended_attributes(ext_att ributes_node) | |
156 | |
157 return IdlConstant(data_type=data_type, extended_attributes=extended_attribu tes, name=name, value=value) | |
158 | |
159 | |
160 def operation_node_to_idl_operation(node): | |
161 name = node.GetName() | |
162 # FIXME: AST should use None internally | |
163 if name == '_unnamed_': | |
164 name = None | |
165 | |
166 is_static = node.GetProperty('STATIC') or False | |
167 specials = [] | |
168 property_dictionary = node.GetProperties() | |
169 for special_keyword in SPECIAL_KEYWORD_LIST: | |
haraken
2013/07/17 02:44:49
Why haven't the special keywords parsed in the par
Nils Barth (inactive)
2013/07/17 12:05:09
The special keywords are handled by the lexer and
haraken
2013/07/21 14:31:50
Got it. Given that static, const etc are stored in
| |
170 if special_keyword in property_dictionary: | |
171 specials.append(special_keyword.lower()) | |
172 | |
173 extended_attributes = None | |
174 arguments = [] | |
175 return_type = None | |
176 children = node.GetChildren() | |
177 for child in children: | |
178 child_class = child.GetClass() | |
179 if child_class == 'Arguments': | |
180 arguments = arguments_node_to_arguments(child) | |
181 elif child_class == 'Type': | |
182 return_type = type_node_to_type(child) | |
183 elif child_class == 'ExtAttributes': | |
184 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld) | |
185 else: | |
186 raise ValueError('Unrecognized node class: %s' % child_class) | |
187 | |
188 return IdlOperation(name=name, data_type=return_type, extended_attributes=ex tended_attributes, is_static=is_static, arguments=arguments, specials=specials) | |
189 | |
190 | |
191 def arguments_node_to_arguments(arguments_node): | |
haraken
2013/07/17 02:44:49
Nit: arguments_node => node (for consistency)
Nils Barth (inactive)
2013/07/17 12:05:09
(>.<) Done.
| |
192 if arguments_node is None: | |
haraken
2013/07/17 02:44:49
Is this check needed?
Nils Barth (inactive)
2013/07/17 12:05:09
It makes handling constructors much easier, since
haraken
2013/07/21 14:31:50
Makes sense. Given that the spec allows both [Cons
Nils Barth (inactive)
2013/07/22 06:32:01
Got it. Didn’t realize that [Constructor] was one
| |
193 return None | |
194 arguments = [] | |
195 argument_node_list = arguments_node.GetChildren() | |
196 for argument_node in argument_node_list: | |
197 arguments.append(argument_node_to_idl_argument(argument_node)) | |
198 return arguments | |
199 | |
200 | |
201 def argument_node_to_idl_argument(node): | |
202 name = node.GetName() | |
203 | |
204 data_type = None | |
205 extended_attributes = {} | |
206 # FIXME: Boolean values are inconsistent due to Perl compatibility. | |
207 # Make all default to False once Perl removed. | |
haraken
2013/07/17 02:44:49
You can remove this comment, as the same thing is
Nils Barth (inactive)
2013/07/17 12:05:09
Done.
(Actual delete the nested comment, so it’s c
| |
208 is_nullable = False | |
209 is_optional = node.GetProperty('OPTIONAL') | |
210 is_variadic = None | |
211 children = node.GetChildren() | |
212 for child in children: | |
213 child_class = child.GetClass() | |
214 if child_class == 'Type': | |
215 data_type = type_node_to_type(child) | |
216 # FIXME: Should end "or False", but use None instead for Perl | |
217 # compatibility. | |
218 is_nullable = child.GetProperty('NULLABLE') | |
219 elif child_class == 'ExtAttributes': | |
220 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld) | |
221 elif child_class == 'Argument': | |
222 child_name = child.GetName() | |
223 if child_name != '...': | |
224 raise ValueError('Unrecognized Argument node; expected "...", go t "%s"' % child_name) | |
225 is_variadic = child.GetProperty('ELLIPSIS') or False | |
226 else: | |
227 raise ValueError('Unrecognized node class: %s' % child_class) | |
228 | |
229 return IdlArgument(name=name, data_type=data_type, extended_attributes=exten ded_attributes, is_nullable=is_nullable, is_optional=is_optional, is_variadic=is _variadic) | |
230 | |
231 # Minor definitions | |
232 | |
233 | |
234 def callback_node_to_idl_callback_function(node): | |
235 name = node.GetName() | |
236 children = node.GetChildren() | |
237 num_children = len(children) | |
238 if num_children != 2: | |
239 raise ValueError('Expected 2 children, got %s' % num_children) | |
240 | |
241 type_node = children[0] | |
242 data_type = type_node_to_type(type_node) | |
243 | |
244 arguments_node = children[1] | |
245 arguments_node_class = arguments_node.GetClass() | |
246 if arguments_node_class != 'Arguments': | |
247 raise ValueError('Expected Value node, got %s' % arguments_node_class) | |
248 arguments = arguments_node_to_arguments(arguments_node) | |
249 | |
250 return IdlCallbackFunction(name=name, data_type=data_type, arguments=argumen ts) | |
251 | |
252 | |
253 def enum_node_to_idl_enum(node): | |
254 name = node.GetName() | |
255 values = [] | |
256 for child in node.GetChildren(): | |
257 values.append(child.GetName()) | |
258 return IdlEnum(name=name, values=values) | |
259 | |
260 | |
261 def exception_field_to_string_node_to_idl_operation(node): | |
262 extended_attributes = {} | |
263 name = node.GetName() | |
264 children = node.GetChildren() | |
haraken
2013/07/17 02:44:49
Shall we check that len(children) > 0 ?
Nils Barth (inactive)
2013/07/17 12:05:09
Done. (As above.)
| |
265 if len(children) > 2: | |
266 raise ValueError('ExceptionFieldToString node with %s children, expected at most 2' % len(children)) | |
267 | |
268 type_node = children[0] | |
269 return_type = type_node_to_type(type_node) | |
270 | |
271 if len(children) > 1: | |
272 ext_attributes_node = children[1] | |
273 extended_attributes = ext_attributes_node_to_extended_attributes(ext_att ributes_node) | |
274 | |
275 return IdlOperation(name=name, data_type=return_type, extended_attributes=ex tended_attributes) | |
276 | |
277 | |
278 def exception_node_to_idl_exception(node): | |
279 # Exceptions are similar to Interfaces, but simpler | |
280 attributes = [] | |
281 constants = [] | |
282 extended_attributes = None | |
283 functions = [] | |
284 name = node.GetName() | |
285 | |
286 children = node.GetChildren() | |
287 for child in children: | |
288 child_class = child.GetClass() | |
289 if child_class == 'Attribute': | |
290 attribute = attribute_node_to_idl_attribute(child) | |
291 attributes.append(attribute) | |
292 elif child_class == 'Const': | |
293 constants.append(constant_node_to_idl_constant(child)) | |
294 elif child_class == 'ExtAttributes': | |
295 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld) | |
296 elif child_class == 'Operation': | |
297 functions.append(operation_node_to_idl_operation(child)) | |
298 elif child_class == 'ExceptionFieldToString': | |
299 functions.append(exception_field_to_string_node_to_idl_operation(chi ld)) | |
300 else: | |
301 raise ValueError('Unrecognized node class: %s' % child_class) | |
302 | |
303 return IdlException(name=name, attributes=attributes, constants=constants, e xtended_attributes=extended_attributes, functions=functions) | |
304 | |
305 | |
306 def typedef_node_to_idl_typedef(node): | |
307 data_type = None | |
308 extended_attributes = None | |
309 | |
310 children = node.GetChildren() | |
311 for child in children: | |
312 child_class = child.GetClass() | |
313 if child_class == 'Type': | |
314 data_type = type_node_to_type(child) | |
315 elif child_class == 'ExtAttributes': | |
316 extended_attributes = ext_attributes_node_to_extended_attributes(chi ld) | |
317 raise ValueError('Extended attributes in a typedef are untested!') | |
318 else: | |
319 raise ValueError('Unrecognized node class: %s' % child_class) | |
320 | |
321 return IdlTypedef(data_type=data_type, extended_attributes=extended_attribut es) | |
322 | |
323 # Extended attributes | |
324 | |
325 | |
326 def ext_attributes_node_to_extended_attributes(node): | |
327 """ | |
328 Returns: | |
329 Dictionary of {ExtAttributeName: ExtAttributeValue}. | |
330 Value is usually a string, with three exceptions: | |
331 Constructors: value is a list of Arguments nodes, corresponding to | |
332 possibly signatures of the constructor. | |
333 CustomConstructors: value is a list of Arguments nodes, corresponding to | |
334 possibly signatures of the custom constructor. | |
335 NamedConstructor: value is a Call node, corresponding to the single | |
336 signature of the named constructor. | |
337 """ | |
338 # Primarily just make a dictionary from the children. | |
339 # The only complexity is handling various types of constructors: | |
340 # Constructors and Custom Constructors can have duplicate entries due to | |
341 # overloading, and thus are stored in temporary lists. | |
342 # However, Named Constructors cannot be overloaded, and thus do not have | |
haraken
2013/07/17 02:44:49
Actually this should be a FIXME. We want to suppor
Nils Barth (inactive)
2013/07/17 12:05:09
Added FIXME!
| |
343 # a list. | |
344 constructors = [] | |
345 custom_constructors = [] | |
346 extended_attributes = {} | |
347 | |
348 attribute_list = node.GetChildren() | |
349 for attribute in attribute_list: | |
350 name = attribute.GetName() | |
351 children = attribute.GetChildren() | |
352 if name in ['Constructor', 'CustomConstructor', 'NamedConstructor']: | |
353 child = None | |
354 child_class = None | |
355 if children: | |
356 if len(children) > 1: | |
357 raise ValueError('ExtAttributes node with %s children, expec ted at most 1' % len(children)) | |
358 child = children[0] | |
359 child_class = child.GetClass() | |
360 if name == 'Constructor': | |
361 if child_class and child_class != 'Arguments': | |
362 raise ValueError('Constructor only supports Arguments as chi ld, but has child of class: %s' % child_class) | |
363 constructors.append(child) | |
364 elif name == 'CustomConstructor': | |
365 if child_class and child_class != 'Arguments': | |
366 raise ValueError('Custom Constructor only supports Arguments as child, but has child of class: %s' % child_class) | |
367 custom_constructors.append(child) | |
368 else: # name == 'NamedConstructor' | |
369 if child_class and child_class != 'Call': | |
370 raise ValueError('Named Constructor only supports Call as ch ild, but has child of class: %s' % child_class) | |
371 extended_attributes[name] = child | |
372 elif children: | |
373 raise ValueError('Non-constructor ExtAttributes node with children: %s' % name) | |
374 else: | |
375 value = attribute.GetProperty('VALUE') | |
376 extended_attributes[name] = value | |
377 | |
378 # Store constructors and custom constructors in special list attributes, | |
379 # which are deleted later. Note plural in key. | |
380 if constructors: | |
381 extended_attributes['Constructors'] = constructors | |
382 if custom_constructors: | |
383 extended_attributes['CustomConstructors'] = custom_constructors | |
384 | |
385 return extended_attributes | |
386 | |
387 | |
388 def extended_attributes_to_constructors(extended_attributes): | |
389 """Returns constructors and custom_constructors (lists of IdlOperations), | |
390 deletes the special list attributes, and puts dummy empty value in | |
391 Constructor and CustomConstructor extended attributes. | |
392 Auxiliary function for interface_node_to_idl_interface.""" | |
393 constructors = [] | |
394 custom_constructors = [] | |
395 if 'Constructors' in extended_attributes: | |
396 constructor_list = extended_attributes['Constructors'] | |
397 # If not overloaded, have index 0, otherwise index from 1 | |
398 overloaded_index = 0 if len(constructor_list) == 1 else 1 | |
399 for arguments_node in constructor_list: | |
400 name = 'Constructor' | |
401 arguments = arguments_node_to_arguments(arguments_node) | |
402 constructor = IdlOperation(name=name, extended_attributes=extended_a ttributes, overloaded_index=overloaded_index, arguments=arguments) | |
403 constructors.append(constructor) | |
404 overloaded_index += 1 | |
405 del extended_attributes['Constructors'] | |
406 extended_attributes['Constructor'] = None | |
haraken
2013/07/17 02:44:49
You can use clear_constructor_attributes().
Nils Barth (inactive)
2013/07/17 12:05:09
Done. (As above.)
| |
407 | |
408 # Prefix 'CallWith' and 'RaisesException' with 'Constructor' | |
409 # FIXME: I have no idea why this is necessary. | |
haraken
2013/07/17 02:44:49
Yeah, I don't understand why either. We shouldn't
Nils Barth (inactive)
2013/07/17 12:05:09
Got it - thanks for the explanation!
Added FIXME.
| |
410 if 'CallWith' in extended_attributes: | |
411 extended_attributes['ConstructorCallWith'] = extended_attributes['Ca llWith'] | |
412 del extended_attributes['CallWith'] | |
413 if 'RaisesException' in extended_attributes: | |
414 extended_attributes['ConstructorRaisesException'] = extended_attribu tes['RaisesException'] | |
415 del extended_attributes['RaisesException'] | |
416 | |
417 if 'CustomConstructors' in extended_attributes: | |
418 custom_constructor_list = extended_attributes['CustomConstructors'] | |
419 # If not overloaded, have index 0, otherwise index from 1 | |
420 overloaded_index = 0 if len(custom_constructor_list) == 1 else 1 | |
421 for arguments_node in custom_constructor_list: | |
422 name = 'CustomConstructor' | |
423 arguments = arguments_node_to_arguments(arguments_node) | |
424 custom_constructor = IdlOperation(name=name, extended_attributes=ext ended_attributes, overloaded_index=overloaded_index, arguments=arguments) | |
425 custom_constructors.append(custom_constructor) | |
426 overloaded_index += 1 | |
427 del extended_attributes['CustomConstructors'] | |
428 extended_attributes['CustomConstructor'] = None | |
haraken
2013/07/17 02:44:49
You can use clear_constructor_attributes().
Nils Barth (inactive)
2013/07/17 12:05:09
Done. (As above.)
| |
429 | |
430 if 'NamedConstructor' in extended_attributes: | |
431 name = 'NamedConstructor' | |
432 call_node = extended_attributes['NamedConstructor'] | |
433 extended_attributes['NamedConstructor'] = call_node.GetName() | |
434 overloaded_index = None # named constructors are not overloaded | |
435 arguments_node = call_node.GetChildren()[0] | |
haraken
2013/07/17 02:44:49
Do you want to check that len(children) > 0 ?
Nils Barth (inactive)
2013/07/17 12:05:09
Done.
| |
436 arguments = arguments_node_to_arguments(arguments_node) | |
437 named_constructor = IdlOperation(name=name, extended_attributes=extended _attributes, overloaded_index=overloaded_index, arguments=arguments) | |
438 constructors.append(named_constructor) | |
439 | |
440 return constructors, custom_constructors | |
441 | |
442 | |
443 def clear_constructor_attributes(extended_attributes): | |
444 if 'Constructors' in extended_attributes: | |
445 del extended_attributes['Constructors'] | |
haraken
2013/07/17 02:44:49
This del won't be needed, because you're setting N
Nils Barth (inactive)
2013/07/17 12:05:09
It deletes the plural Constructor*s* and sets the
| |
446 extended_attributes['Constructor'] = None | |
haraken
2013/07/17 05:43:11
If you set None, I'm afraid that we cannot disting
Nils Barth (inactive)
2013/07/17 12:05:09
The keys of extended_attributes are the names of t
| |
447 if 'CustomConstructors' in extended_attributes: | |
448 del extended_attributes['CustomConstructors'] | |
haraken
2013/07/17 02:44:49
Ditto.
Nils Barth (inactive)
2013/07/17 12:05:09
Ditto.
| |
449 extended_attributes['CustomConstructor'] = None | |
450 | |
451 | |
452 # Types | |
453 | |
454 | |
455 def type_node_to_type(node): | |
456 children = node.GetChildren() | |
457 if not children: | |
haraken
2013/07/17 02:44:49
Instead, you can check that len(children) > 0
Nils Barth (inactive)
2013/07/17 12:05:09
In general “if not some_list:” is considered more
| |
458 raise ValueError('Type node expects children, got none.') | |
459 if len(children) > 2: | |
460 raise ValueError('Type node expects at most 2 children (type + optional array []), got %s (multi-dimensional arrays are not supported).' % len(children) ) | |
461 | |
462 type_node_child = children[0] | |
463 data_type = type_node_inner_to_type(type_node_child) | |
464 | |
465 if len(children) == 2: | |
466 array_node = children[1] | |
467 array_node_class = array_node.GetClass() | |
468 if array_node_class != 'Array': | |
469 raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class) | |
470 data_type += '[]' | |
471 | |
472 return data_type | |
473 | |
474 | |
475 def type_node_inner_to_type(node): | |
476 """Auxiliary.""" | |
haraken
2013/07/17 02:44:49
I'd remove this comment.
Nils Barth (inactive)
2013/07/17 12:05:09
Good point; not the world’s most useful comment.
| |
477 node_class = node.GetClass() | |
478 if node_class in ['PrimitiveType', 'Typeref']: | |
479 return node.GetName() | |
480 elif node_class == 'Any': | |
481 return 'any' | |
482 elif node_class == 'Sequence': | |
483 return sequence_node_to_type(node) | |
484 elif node_class == 'UnionType': | |
485 return union_type_node_to_idl_union_type(node) | |
486 raise ValueError('Unrecognized node class: %s' % node_class) | |
487 | |
488 | |
489 def sequence_node_to_type(node): | |
490 children = node.GetChildren() | |
491 if len(children) != 1: | |
492 raise ValueError('Sequence node expects exactly 1 child, got %s' % len(c hildren)) | |
493 sequence_child = children[0] | |
494 sequence_child_class = sequence_child.GetClass() | |
495 if sequence_child_class != 'Type': | |
496 raise ValueError('Unrecognized node class: %s' % sequence_child_class) | |
497 sequence_type = type_node_to_type(sequence_child) | |
498 return 'sequence<%s>' % sequence_type | |
499 | |
500 | |
501 def union_type_node_to_idl_union_type(node): | |
502 union_member_types = [] | |
503 for member_type_node in node.GetChildren(): | |
504 member_type = type_node_inner_to_type(member_type_node) | |
505 union_member_types.append(member_type) | |
506 return IdlUnionType(union_member_types=union_member_types) | |
OLD | NEW |