Chromium Code Reviews| 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 def __str__(self): |
| 105 self.base_type = None | 106 raise NotImplementedError( |
| 106 self.is_nullable = is_nullable | 107 '__str__() should be defined in subclasses') |
| 107 | 108 |
| 108 def __str__(self): | 109 def __getattr__(self, name): |
|
Nils Barth (inactive)
2014/08/19 13:44:14
Rather than hacky, how about considering this "ele
Jens Widell
2014/08/19 14:30:12
Done. :-)
| |
| 109 inner_string = self.inner_string | 110 # This __getattr__() ensures that all properties supported by any of |
| 110 if self.is_nullable: | 111 # IdlType, IdlUnionType, IdlArrayOrSequenceType and IdlNullableType can |
| 111 # FIXME: Dictionary::ConversionContext::setConversionType can't | 112 # be accessed without errors on any type object, but returns None if the |
| 112 # handle the '?' in nullable types (passes nullability separately). | 113 # actual type object doesn't support it. |
| 113 # Update that function to handle nullability from the type name, | 114 # |
| 114 # simplifying its signature. | 115 # Note: This only applies to properties defined using the @property |
| 115 # return inner_string + '?' | 116 # decorator, not properties set in __init__(); the latter form of |
| 116 return inner_string | 117 # property will only be accessible on objects of types that support it. |
| 117 return inner_string | 118 # |
| 118 | 119 # We have this hack to avoid the need to explicitly support all |
| 119 @property | 120 # properties on IdlNullableType, relaying the access to the inner type. |
| 120 def inner_string(self): | 121 if not name.startswith('_'): |
|
Nils Barth (inactive)
2014/08/19 13:44:14
Do you need this?
__getattr__ is only called if an
Jens Widell
2014/08/19 14:30:12
What I meant to avoid with this was Python looking
Nils Barth (inactive)
2014/08/19 15:25:15
Thanks for explaining; AFAICT Python doesn't need
| |
| 121 raise NotImplementedError( | 122 if (hasattr(IdlType, name) or |
| 122 'inner_string property should be defined in subclasses') | 123 hasattr(IdlUnionType, name) or |
| 123 | 124 hasattr(IdlArrayOrSequenceType, name) or |
| 124 @property | 125 hasattr(IdlNullableType, name)): |
| 125 def is_basic_type(self): | 126 return None |
| 126 return False | 127 raise AttributeError(name) |
| 127 | |
| 128 @property | |
| 129 def is_callback_function(self): | |
| 130 return False | |
| 131 | |
| 132 @property | |
| 133 def is_callback_interface(self): | |
| 134 return False | |
| 135 | |
| 136 @property | |
| 137 def is_dictionary(self): | |
| 138 return False | |
| 139 | |
| 140 @property | |
| 141 def is_enum(self): | |
| 142 return False | |
| 143 | |
| 144 @property | |
| 145 def is_integer_type(self): | |
| 146 return False | |
| 147 | |
| 148 @property | |
| 149 def is_numeric_type(self): | |
| 150 return False | |
| 151 | |
| 152 @property | |
| 153 def is_primitive_type(self): | |
| 154 return False | |
| 155 | |
| 156 @property | |
| 157 def is_interface_type(self): | |
| 158 return False | |
| 159 | |
| 160 @property | |
| 161 def is_string_type(self): | |
| 162 return False | |
| 163 | |
| 164 @property | |
| 165 def is_union_type(self): | |
| 166 return False | |
| 167 | |
| 168 @property | |
| 169 def may_raise_exception_on_conversion(self): | |
| 170 return False | |
| 171 | |
| 172 @property | |
| 173 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( | |
| 181 'inner_name property should be defined in subclasses') | |
| 182 | 128 |
| 183 def resolve_typedefs(self, typedefs): | 129 def resolve_typedefs(self, typedefs): |
| 184 raise NotImplementedError( | 130 raise NotImplementedError( |
| 185 'resolve_typedefs should be defined in subclasses') | 131 'resolve_typedefs should be defined in subclasses') |
| 186 | 132 |
| 187 | 133 |
| 188 ################################################################################ | 134 ################################################################################ |
| 189 # IdlType | 135 # IdlType |
| 190 ################################################################################ | 136 ################################################################################ |
| 191 | 137 |
| 192 class IdlType(IdlTypeBase): | 138 class IdlType(IdlTypeBase): |
| 193 # FIXME: incorporate Nullable, etc. | 139 # FIXME: incorporate Nullable, etc. |
| 194 # to support types like short?[] vs. short[]?, instead of treating these | 140 # to support types like short?[] vs. short[]?, instead of treating these |
| 195 # as orthogonal properties (via flags). | 141 # as orthogonal properties (via flags). |
| 196 callback_functions = set() | 142 callback_functions = set() |
| 197 callback_interfaces = set() | 143 callback_interfaces = set() |
| 198 dictionaries = set() | 144 dictionaries = set() |
| 199 enums = {} # name -> values | 145 enums = {} # name -> values |
| 200 | 146 |
| 201 def __init__(self, base_type, is_nullable=False, is_unrestricted=False): | 147 def __init__(self, base_type, is_unrestricted=False): |
| 202 super(IdlType, self).__init__(is_nullable) | 148 super(IdlType, self).__init__() |
| 203 if is_unrestricted: | 149 if is_unrestricted: |
| 204 self.base_type = 'unrestricted %s' % base_type | 150 self.base_type_name = 'unrestricted %s' % base_type |
| 205 else: | 151 else: |
| 206 self.base_type = base_type | 152 self.base_type_name = base_type |
| 207 | 153 |
| 208 @property | 154 def __str__(self): |
| 209 def inner_string(self): | |
| 210 return self.base_type | 155 return self.base_type |
| 211 | 156 |
| 212 @property | 157 @property |
| 213 def is_basic_type(self): | 158 def is_basic_type(self): |
| 214 return self.base_type in BASIC_TYPES | 159 return self.base_type in BASIC_TYPES |
| 215 | 160 |
| 216 @property | 161 @property |
| 217 def is_callback_function(self): | 162 def is_callback_function(self): |
| 218 return self.base_type in IdlType.callback_functions | 163 return self.base_type in IdlType.callback_functions |
| 219 | 164 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 return not(self.is_basic_type or | 201 return not(self.is_basic_type or |
| 257 self.is_callback_function or | 202 self.is_callback_function or |
| 258 self.is_dictionary or | 203 self.is_dictionary or |
| 259 self.is_enum or | 204 self.is_enum or |
| 260 self.name == 'Any' or | 205 self.name == 'Any' or |
| 261 self.name == 'Object' or | 206 self.name == 'Object' or |
| 262 self.name == 'Promise') # Promise will be basic in future | 207 self.name == 'Promise') # Promise will be basic in future |
| 263 | 208 |
| 264 @property | 209 @property |
| 265 def is_string_type(self): | 210 def is_string_type(self): |
| 266 return self.inner_name in STRING_TYPES | 211 return self.name in STRING_TYPES |
| 267 | 212 |
| 268 @property | 213 @property |
| 269 def may_raise_exception_on_conversion(self): | 214 def may_raise_exception_on_conversion(self): |
| 270 return (self.is_integer_type or | 215 return (self.is_integer_type or |
| 271 self.name in ('ByteString', 'ScalarValueString')) | 216 self.name in ('ByteString', 'ScalarValueString')) |
| 272 | 217 |
| 273 @property | 218 @property |
| 274 def is_union_type(self): | 219 def is_union_type(self): |
| 275 return isinstance(self, IdlUnionType) | 220 return isinstance(self, IdlUnionType) |
| 276 | 221 |
| 277 @property | 222 @property |
| 278 def inner_name(self): | 223 def base_type(self): |
| 279 """Return type name (or inner type name if nullable) | 224 return self.base_type_name |
| 225 | |
| 226 @property | |
| 227 def name(self): | |
| 228 """Return type name | |
| 280 | 229 |
| 281 http://heycam.github.io/webidl/#dfn-type-name | 230 http://heycam.github.io/webidl/#dfn-type-name |
| 282 """ | 231 """ |
| 283 base_type = self.base_type | 232 base_type = self.base_type |
| 284 return TYPE_NAMES.get(base_type, base_type) | 233 return TYPE_NAMES.get(base_type, base_type) |
| 285 | 234 |
| 286 @classmethod | 235 @classmethod |
| 287 def set_callback_functions(cls, new_callback_functions): | 236 def set_callback_functions(cls, new_callback_functions): |
| 288 cls.callback_functions.update(new_callback_functions) | 237 cls.callback_functions.update(new_callback_functions) |
| 289 | 238 |
| 290 @classmethod | 239 @classmethod |
| 291 def set_callback_interfaces(cls, new_callback_interfaces): | 240 def set_callback_interfaces(cls, new_callback_interfaces): |
| 292 cls.callback_interfaces.update(new_callback_interfaces) | 241 cls.callback_interfaces.update(new_callback_interfaces) |
| 293 | 242 |
| 294 @classmethod | 243 @classmethod |
| 295 def set_dictionaries(cls, new_dictionaries): | 244 def set_dictionaries(cls, new_dictionaries): |
| 296 cls.dictionaries.update(new_dictionaries) | 245 cls.dictionaries.update(new_dictionaries) |
| 297 | 246 |
| 298 @classmethod | 247 @classmethod |
| 299 def set_enums(cls, new_enums): | 248 def set_enums(cls, new_enums): |
| 300 cls.enums.update(new_enums) | 249 cls.enums.update(new_enums) |
| 301 | 250 |
| 302 def resolve_typedefs(self, typedefs): | 251 def resolve_typedefs(self, typedefs): |
| 303 # This function either returns |self|, possibly mutated, or leaves this | 252 # This function either returns |self| or a different object. |
| 304 # object unmodified and returns a different object. | 253 # FIXME: Rename typedefs_resolved(). |
| 305 # FIXME: Change to never mutate |self|, and rename typedefs_resolved(). | 254 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 | 255 |
| 317 | 256 |
| 318 ################################################################################ | 257 ################################################################################ |
| 319 # IdlUnionType | 258 # IdlUnionType |
| 320 ################################################################################ | 259 ################################################################################ |
| 321 | 260 |
| 322 class IdlUnionType(IdlTypeBase): | 261 class IdlUnionType(IdlTypeBase): |
| 323 # http://heycam.github.io/webidl/#idl-union | 262 # http://heycam.github.io/webidl/#idl-union |
| 324 def __init__(self, member_types, is_nullable=False): | 263 def __init__(self, member_types): |
| 325 super(IdlUnionType, self).__init__(is_nullable=is_nullable) | 264 super(IdlUnionType, self).__init__() |
| 326 self.member_types = member_types | 265 self.member_types = member_types |
| 327 | 266 |
| 328 @property | 267 @property |
| 329 def is_union_type(self): | 268 def is_union_type(self): |
| 330 return True | 269 return True |
| 331 | 270 |
| 332 @property | 271 @property |
| 333 def inner_name(self): | 272 def name(self): |
| 334 """Return type name (or inner type name if nullable) | 273 """Return type name (or inner type name if nullable) |
| 335 | 274 |
| 336 http://heycam.github.io/webidl/#dfn-type-name | 275 http://heycam.github.io/webidl/#dfn-type-name |
| 337 """ | 276 """ |
| 338 return 'Or'.join(member_type.name for member_type in self.member_types) | 277 return 'Or'.join(member_type.name for member_type in self.member_types) |
| 339 | 278 |
| 340 def resolve_typedefs(self, typedefs): | 279 def resolve_typedefs(self, typedefs): |
| 341 self.member_types = [ | 280 self.member_types = [ |
| 342 typedefs.get(member_type, member_type) | 281 typedefs.get(member_type, member_type) |
| 343 for member_type in self.member_types] | 282 for member_type in self.member_types] |
| 344 return self | 283 return self |
| 345 | 284 |
| 346 | 285 |
| 347 ################################################################################ | 286 ################################################################################ |
| 348 # IdlArrayOrSequenceType, IdlArrayType, IdlSequenceType | 287 # IdlArrayOrSequenceType, IdlArrayType, IdlSequenceType |
| 349 ################################################################################ | 288 ################################################################################ |
| 350 | 289 |
| 351 class IdlArrayOrSequenceType(IdlTypeBase): | 290 class IdlArrayOrSequenceType(IdlTypeBase): |
| 352 """Base class for IdlArrayType and IdlSequenceType.""" | 291 """Base class for IdlArrayType and IdlSequenceType.""" |
| 353 | 292 |
| 354 def __init__(self, element_type, is_nullable=False): | 293 def __init__(self, element_type): |
| 355 super(IdlArrayOrSequenceType, self).__init__(is_nullable) | 294 super(IdlArrayOrSequenceType, self).__init__() |
| 356 self.element_type = element_type | 295 self.element_type = element_type |
| 357 | 296 |
| 358 def resolve_typedefs(self, typedefs): | 297 def resolve_typedefs(self, typedefs): |
| 359 self.element_type = self.element_type.resolve_typedefs(typedefs) | 298 self.element_type = self.element_type.resolve_typedefs(typedefs) |
| 360 return self | 299 return self |
| 361 | 300 |
| 362 | 301 |
| 363 class IdlArrayType(IdlArrayOrSequenceType): | 302 class IdlArrayType(IdlArrayOrSequenceType): |
| 364 def __init__(self, element_type, is_nullable=False): | 303 def __init__(self, element_type): |
| 365 super(IdlArrayType, self).__init__(element_type, is_nullable) | 304 super(IdlArrayType, self).__init__(element_type) |
| 366 | 305 |
| 367 @property | 306 def __str__(self): |
| 368 def inner_string(self): | |
| 369 return '%s[]' % self.element_type | 307 return '%s[]' % self.element_type |
| 370 | 308 |
| 371 @property | 309 @property |
| 372 def inner_name(self): | 310 def name(self): |
| 373 return self.element_type.name + 'Array' | 311 return self.element_type.name + 'Array' |
| 374 | 312 |
| 375 | 313 |
| 376 class IdlSequenceType(IdlArrayOrSequenceType): | 314 class IdlSequenceType(IdlArrayOrSequenceType): |
| 377 def __init__(self, element_type, is_nullable=False): | 315 def __init__(self, element_type): |
| 378 super(IdlSequenceType, self).__init__(element_type, is_nullable) | 316 super(IdlSequenceType, self).__init__(element_type) |
| 379 | 317 |
| 380 @property | 318 def __str__(self): |
| 381 def inner_string(self): | |
| 382 return 'sequence<%s>' % self.element_type | 319 return 'sequence<%s>' % self.element_type |
| 383 | 320 |
| 384 @property | 321 @property |
| 385 def inner_name(self): | 322 def name(self): |
| 386 return self.element_type.name + 'Sequence' | 323 return self.element_type.name + 'Sequence' |
| 324 | |
| 325 | |
| 326 ################################################################################ | |
| 327 # IdlNullableType | |
| 328 ################################################################################ | |
| 329 | |
| 330 class IdlNullableType(IdlTypeBase): | |
| 331 def __init__(self, inner_type): | |
| 332 super(IdlNullableType, self).__init__() | |
| 333 self.inner_type = inner_type | |
| 334 | |
| 335 def __str__(self): | |
| 336 # FIXME: Dictionary::ConversionContext::setConversionType can't | |
| 337 # handle the '?' in nullable types (passes nullability separately). | |
| 338 # Update that function to handle nullability from the type name, | |
| 339 # simplifying its signature. | |
| 340 # return str(self.inner_type) + '?' | |
| 341 return str(self.inner_type) | |
| 342 | |
| 343 def __getattr__(self, name): | |
| 344 return getattr(self.inner_type, name) | |
| 345 | |
| 346 @property | |
| 347 def is_nullable(self): | |
| 348 return True | |
| 349 | |
| 350 @property | |
| 351 def name(self): | |
| 352 return self.inner_type.name + 'OrNull' | |
| 353 | |
| 354 def resolve_typedefs(self, typedefs): | |
| 355 self.inner_type = self.inner_type.resolve_typedefs(typedefs) | |
| 356 return self | |
| OLD | NEW |