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 |