OLD | NEW |
---|---|
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 """IDL type handling. | 4 """IDL type handling. |
5 | 5 |
6 Classes: | 6 Classes: |
7 IdlTypeBase | 7 IdlTypeBase |
8 IdlType | 8 IdlType |
9 IdlUnionType | 9 IdlUnionType |
10 IdlArrayOrSequenceType | 10 IdlArrayOrSequenceType |
11 IdlArrayType | 11 IdlArrayType |
12 IdlSequenceType | 12 IdlSequenceType |
13 IdlNullableType | |
13 """ | 14 """ |
14 | 15 |
15 from collections import defaultdict | 16 from collections import defaultdict |
16 | 17 |
17 | 18 |
18 ################################################################################ | 19 ################################################################################ |
19 # IDL types | 20 # IDL types |
20 ################################################################################ | 21 ################################################################################ |
21 | 22 |
22 INTEGER_TYPES = frozenset([ | 23 INTEGER_TYPES = frozenset([ |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
94 ancestor_name in ancestors[interface_name]) | 95 ancestor_name in ancestors[interface_name]) |
95 | 96 |
96 | 97 |
97 def set_ancestors(new_ancestors): | 98 def set_ancestors(new_ancestors): |
98 ancestors.update(new_ancestors) | 99 ancestors.update(new_ancestors) |
99 | 100 |
100 | 101 |
101 class IdlTypeBase(object): | 102 class IdlTypeBase(object): |
102 """Base class for IdlType, IdlUnionType and IdlArrayOrSequenceType.""" | 103 """Base class for IdlType, IdlUnionType and IdlArrayOrSequenceType.""" |
103 | 104 |
104 def __init__(self, is_nullable): | |
105 self.base_type = None | |
106 self.is_nullable = is_nullable | |
107 | |
108 def __str__(self): | 105 def __str__(self): |
109 inner_string = self.inner_string | 106 raise NotImplementedError( |
110 if self.is_nullable: | 107 '__str__() should be defined in subclasses') |
111 # FIXME: Dictionary::ConversionContext::setConversionType can't | |
112 # handle the '?' in nullable types (passes nullability separately). | |
113 # Update that function to handle nullability from the type name, | |
114 # simplifying its signature. | |
115 # return inner_string + '?' | |
116 return inner_string | |
117 return inner_string | |
118 | 108 |
119 @property | 109 @property |
120 def inner_string(self): | 110 def is_nullable(self): |
121 raise NotImplementedError( | 111 return False |
122 'inner_string property should be defined in subclasses') | |
123 | 112 |
124 @property | 113 @property |
125 def is_basic_type(self): | 114 def is_basic_type(self): |
126 return False | 115 return False |
127 | 116 |
128 @property | 117 @property |
129 def is_callback_function(self): | 118 def is_callback_function(self): |
130 return False | 119 return False |
131 | 120 |
132 @property | 121 @property |
(...skipping 26 matching lines...) Expand all Loading... | |
159 | 148 |
160 @property | 149 @property |
161 def is_string_type(self): | 150 def is_string_type(self): |
162 return False | 151 return False |
163 | 152 |
164 @property | 153 @property |
165 def is_union_type(self): | 154 def is_union_type(self): |
166 return False | 155 return False |
167 | 156 |
168 @property | 157 @property |
158 def base_type(self): | |
159 return None | |
160 | |
161 @property | |
169 def may_raise_exception_on_conversion(self): | 162 def may_raise_exception_on_conversion(self): |
170 return False | 163 return False |
171 | 164 |
172 @property | 165 @property |
173 def name(self): | 166 def name(self): |
174 if self.is_nullable: | |
175 return self.inner_name + 'OrNull' | |
176 return self.inner_name | |
177 | |
178 @property | |
179 def inner_name(self): | |
180 raise NotImplementedError( | 167 raise NotImplementedError( |
181 'inner_name property should be defined in subclasses') | 168 'name property should be defined in subclasses') |
182 | 169 |
183 def resolve_typedefs(self, typedefs): | 170 def resolve_typedefs(self, typedefs): |
184 raise NotImplementedError( | 171 raise NotImplementedError( |
185 'resolve_typedefs should be defined in subclasses') | 172 'resolve_typedefs should be defined in subclasses') |
186 | 173 |
187 | 174 |
188 ################################################################################ | 175 ################################################################################ |
189 # IdlType | 176 # IdlType |
190 ################################################################################ | 177 ################################################################################ |
191 | 178 |
192 class IdlType(IdlTypeBase): | 179 class IdlType(IdlTypeBase): |
193 # FIXME: incorporate Nullable, etc. | 180 # FIXME: incorporate Nullable, etc. |
194 # to support types like short?[] vs. short[]?, instead of treating these | 181 # to support types like short?[] vs. short[]?, instead of treating these |
195 # as orthogonal properties (via flags). | 182 # as orthogonal properties (via flags). |
196 callback_functions = set() | 183 callback_functions = set() |
197 callback_interfaces = set() | 184 callback_interfaces = set() |
198 dictionaries = set() | 185 dictionaries = set() |
199 enums = {} # name -> values | 186 enums = {} # name -> values |
200 | 187 |
201 def __init__(self, base_type, is_nullable=False, is_unrestricted=False): | 188 def __init__(self, base_type, is_unrestricted=False): |
202 super(IdlType, self).__init__(is_nullable) | 189 super(IdlType, self).__init__() |
203 if is_unrestricted: | 190 if is_unrestricted: |
204 self.base_type = 'unrestricted %s' % base_type | 191 self.base_type_name = 'unrestricted %s' % base_type |
205 else: | 192 else: |
206 self.base_type = base_type | 193 self.base_type_name = base_type |
207 | 194 |
208 @property | 195 def __str__(self): |
209 def inner_string(self): | |
210 return self.base_type | 196 return self.base_type |
211 | 197 |
212 @property | 198 @property |
213 def is_basic_type(self): | 199 def is_basic_type(self): |
214 return self.base_type in BASIC_TYPES | 200 return self.base_type in BASIC_TYPES |
215 | 201 |
216 @property | 202 @property |
217 def is_callback_function(self): | 203 def is_callback_function(self): |
218 return self.base_type in IdlType.callback_functions | 204 return self.base_type in IdlType.callback_functions |
219 | 205 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
256 return not(self.is_basic_type or | 242 return not(self.is_basic_type or |
257 self.is_callback_function or | 243 self.is_callback_function or |
258 self.is_dictionary or | 244 self.is_dictionary or |
259 self.is_enum or | 245 self.is_enum or |
260 self.name == 'Any' or | 246 self.name == 'Any' or |
261 self.name == 'Object' or | 247 self.name == 'Object' or |
262 self.name == 'Promise') # Promise will be basic in future | 248 self.name == 'Promise') # Promise will be basic in future |
263 | 249 |
264 @property | 250 @property |
265 def is_string_type(self): | 251 def is_string_type(self): |
266 return self.inner_name in STRING_TYPES | 252 return self.name in STRING_TYPES |
267 | 253 |
268 @property | 254 @property |
269 def may_raise_exception_on_conversion(self): | 255 def may_raise_exception_on_conversion(self): |
270 return (self.is_integer_type or | 256 return (self.is_integer_type or |
271 self.name in ('ByteString', 'ScalarValueString')) | 257 self.name in ('ByteString', 'ScalarValueString')) |
272 | 258 |
273 @property | 259 @property |
274 def is_union_type(self): | 260 def is_union_type(self): |
275 return isinstance(self, IdlUnionType) | 261 return isinstance(self, IdlUnionType) |
276 | 262 |
277 @property | 263 @property |
278 def inner_name(self): | 264 def base_type(self): |
279 """Return type name (or inner type name if nullable) | 265 return self.base_type_name |
266 | |
267 @property | |
268 def name(self): | |
269 """Return type name | |
280 | 270 |
281 http://heycam.github.io/webidl/#dfn-type-name | 271 http://heycam.github.io/webidl/#dfn-type-name |
282 """ | 272 """ |
283 base_type = self.base_type | 273 base_type = self.base_type |
284 return TYPE_NAMES.get(base_type, base_type) | 274 return TYPE_NAMES.get(base_type, base_type) |
285 | 275 |
286 @classmethod | 276 @classmethod |
287 def set_callback_functions(cls, new_callback_functions): | 277 def set_callback_functions(cls, new_callback_functions): |
288 cls.callback_functions.update(new_callback_functions) | 278 cls.callback_functions.update(new_callback_functions) |
289 | 279 |
290 @classmethod | 280 @classmethod |
291 def set_callback_interfaces(cls, new_callback_interfaces): | 281 def set_callback_interfaces(cls, new_callback_interfaces): |
292 cls.callback_interfaces.update(new_callback_interfaces) | 282 cls.callback_interfaces.update(new_callback_interfaces) |
293 | 283 |
294 @classmethod | 284 @classmethod |
295 def set_dictionaries(cls, new_dictionaries): | 285 def set_dictionaries(cls, new_dictionaries): |
296 cls.dictionaries.update(new_dictionaries) | 286 cls.dictionaries.update(new_dictionaries) |
297 | 287 |
298 @classmethod | 288 @classmethod |
299 def set_enums(cls, new_enums): | 289 def set_enums(cls, new_enums): |
300 cls.enums.update(new_enums) | 290 cls.enums.update(new_enums) |
301 | 291 |
302 def resolve_typedefs(self, typedefs): | 292 def resolve_typedefs(self, typedefs): |
303 # This function either returns |self|, possibly mutated, or leaves this | 293 # This function either returns |self| or a different object. |
304 # object unmodified and returns a different object. | 294 # FIXME: Rename typedefs_resolved(). |
305 # FIXME: Change to never mutate |self|, and rename typedefs_resolved(). | 295 return typedefs.get(self.base_type, self) |
306 if self.base_type not in typedefs: | |
307 return self | |
308 new_type = typedefs[self.base_type] | |
309 if type(new_type) != type(self): | |
310 # If type changes, need to return a different object, | |
311 # since can't change type(self) | |
312 return new_type | |
313 # If type doesn't change, just mutate self to avoid a new object | |
314 self.__init__(new_type.base_type, self.is_nullable or new_type.is_nullab le) | |
315 return self | |
316 | 296 |
317 | 297 |
318 ################################################################################ | 298 ################################################################################ |
319 # IdlUnionType | 299 # IdlUnionType |
320 ################################################################################ | 300 ################################################################################ |
321 | 301 |
322 class IdlUnionType(IdlTypeBase): | 302 class IdlUnionType(IdlTypeBase): |
323 # http://heycam.github.io/webidl/#idl-union | 303 # http://heycam.github.io/webidl/#idl-union |
324 def __init__(self, member_types, is_nullable=False): | 304 def __init__(self, member_types): |
325 super(IdlUnionType, self).__init__(is_nullable=is_nullable) | 305 super(IdlUnionType, self).__init__() |
326 self.member_types = member_types | 306 self.member_types = member_types |
327 | 307 |
328 @property | 308 @property |
329 def is_union_type(self): | 309 def is_union_type(self): |
330 return True | 310 return True |
331 | 311 |
332 @property | 312 @property |
333 def inner_name(self): | 313 def name(self): |
334 """Return type name (or inner type name if nullable) | 314 """Return type name (or inner type name if nullable) |
335 | 315 |
336 http://heycam.github.io/webidl/#dfn-type-name | 316 http://heycam.github.io/webidl/#dfn-type-name |
337 """ | 317 """ |
338 return 'Or'.join(member_type.name for member_type in self.member_types) | 318 return 'Or'.join(member_type.name for member_type in self.member_types) |
339 | 319 |
340 def resolve_typedefs(self, typedefs): | 320 def resolve_typedefs(self, typedefs): |
341 self.member_types = [ | 321 self.member_types = [ |
342 typedefs.get(member_type, member_type) | 322 typedefs.get(member_type, member_type) |
343 for member_type in self.member_types] | 323 for member_type in self.member_types] |
344 return self | 324 return self |
345 | 325 |
346 | 326 |
347 ################################################################################ | 327 ################################################################################ |
348 # IdlArrayOrSequenceType, IdlArrayType, IdlSequenceType | 328 # IdlArrayOrSequenceType, IdlArrayType, IdlSequenceType |
349 ################################################################################ | 329 ################################################################################ |
350 | 330 |
351 class IdlArrayOrSequenceType(IdlTypeBase): | 331 class IdlArrayOrSequenceType(IdlTypeBase): |
352 """Base class for IdlArrayType and IdlSequenceType.""" | 332 """Base class for IdlArrayType and IdlSequenceType.""" |
353 | 333 |
354 def __init__(self, element_type, is_nullable=False): | 334 def __init__(self, element_type): |
355 super(IdlArrayOrSequenceType, self).__init__(is_nullable) | 335 super(IdlArrayOrSequenceType, self).__init__() |
356 self.element_type = element_type | 336 self.element_type = element_type |
357 | 337 |
358 def resolve_typedefs(self, typedefs): | 338 def resolve_typedefs(self, typedefs): |
359 self.element_type = self.element_type.resolve_typedefs(typedefs) | 339 self.element_type = self.element_type.resolve_typedefs(typedefs) |
360 return self | 340 return self |
361 | 341 |
362 | 342 |
363 class IdlArrayType(IdlArrayOrSequenceType): | 343 class IdlArrayType(IdlArrayOrSequenceType): |
364 def __init__(self, element_type, is_nullable=False): | 344 def __init__(self, element_type): |
365 super(IdlArrayType, self).__init__(element_type, is_nullable) | 345 super(IdlArrayType, self).__init__(element_type) |
366 | 346 |
367 @property | 347 def __str__(self): |
368 def inner_string(self): | |
369 return '%s[]' % self.element_type | 348 return '%s[]' % self.element_type |
370 | 349 |
371 @property | 350 @property |
372 def inner_name(self): | 351 def name(self): |
373 return self.element_type.name + 'Array' | 352 return self.element_type.name + 'Array' |
374 | 353 |
375 | 354 |
376 class IdlSequenceType(IdlArrayOrSequenceType): | 355 class IdlSequenceType(IdlArrayOrSequenceType): |
377 def __init__(self, element_type, is_nullable=False): | 356 def __init__(self, element_type): |
378 super(IdlSequenceType, self).__init__(element_type, is_nullable) | 357 super(IdlSequenceType, self).__init__(element_type) |
379 | 358 |
380 @property | 359 def __str__(self): |
381 def inner_string(self): | |
382 return 'sequence<%s>' % self.element_type | 360 return 'sequence<%s>' % self.element_type |
383 | 361 |
384 @property | 362 @property |
385 def inner_name(self): | 363 def name(self): |
386 return self.element_type.name + 'Sequence' | 364 return self.element_type.name + 'Sequence' |
365 | |
366 | |
367 ################################################################################ | |
368 # IdlNullableType | |
369 ################################################################################ | |
370 | |
371 class IdlNullableType(IdlTypeBase): | |
372 def __init__(self, inner_type): | |
373 super(IdlNullableType, self).__init__() | |
374 self.inner_type = inner_type | |
375 | |
376 def __str__(self): | |
377 # FIXME: Dictionary::ConversionContext::setConversionType can't | |
378 # handle the '?' in nullable types (passes nullability separately). | |
379 # Update that function to handle nullability from the type name, | |
380 # simplifying its signature. | |
381 # return str(self.inner_type) + '?' | |
382 return str(self.inner_type) | |
383 | |
384 def __getattr__(self, name): | |
385 return getattr(self.inner_type, name) | |
386 | |
387 @property | |
388 def is_nullable(self): | |
389 return True | |
390 | |
391 @property | |
392 def is_basic_type(self): | |
393 return self.inner_type.is_basic_type | |
haraken
2014/08/15 07:43:57
Just a question about Python: Even if we have the
Jens Widell
2014/08/15 08:00:09
Yes, __getattr__ is called as a last resort, if th
haraken
2014/08/15 08:11:07
Makes sense.
| |
394 | |
395 @property | |
396 def is_callback_function(self): | |
397 return self.inner_type.is_callback_function | |
398 | |
399 @property | |
400 def is_callback_interface(self): | |
401 return self.inner_type.is_callback_interface | |
402 | |
403 @property | |
404 def is_dictionary(self): | |
405 return self.inner_type.is_dictionary | |
406 | |
407 @property | |
408 def is_enum(self): | |
409 return self.inner_type.is_enum | |
410 | |
411 @property | |
412 def is_integer_type(self): | |
413 return self.inner_type.is_integer_type | |
414 | |
415 @property | |
416 def is_numeric_type(self): | |
417 return self.inner_type.is_numeric_type | |
418 | |
419 @property | |
420 def is_primitive_type(self): | |
421 return self.inner_type.is_primitive_type | |
422 | |
423 @property | |
424 def is_interface_type(self): | |
425 return self.inner_type.is_interface_type | |
426 | |
427 @property | |
428 def is_string_type(self): | |
429 return self.inner_type.is_string_type | |
430 | |
431 @property | |
432 def is_union_type(self): | |
433 return self.inner_type.is_union_type | |
434 | |
435 @property | |
436 def base_type(self): | |
437 return self.inner_type.base_type | |
438 | |
439 @property | |
440 def may_raise_exception_on_conversion(self): | |
441 return self.inner_type.may_raise_exception_on_conversion | |
442 | |
443 @property | |
444 def name(self): | |
445 return self.inner_type.name + 'OrNull' | |
446 | |
447 def resolve_typedefs(self, typedefs): | |
448 self.inner_type = self.inner_type.resolve_typedefs(typedefs) | |
449 return self | |
OLD | NEW |