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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 def inherits_interface(interface_name, ancestor_name): | 93 def inherits_interface(interface_name, ancestor_name): |
93 return (interface_name == ancestor_name or | 94 return (interface_name == ancestor_name or |
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, IdlArrayOrSequenceType and IdlNulla
bleType.""" |
103 | |
104 def __init__(self, is_nullable): | |
105 self.base_type = None | |
106 self.is_nullable = is_nullable | |
107 | 104 |
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 def __getattr__(self, name): |
120 def inner_string(self): | 110 # Default undefined attributes to None (analogous to Jinja variables). |
121 raise NotImplementedError( | 111 # This allows us to not define default properties in the base class, and |
122 'inner_string property should be defined in subclasses') | 112 # allows us to relay __getattr__ in IdlNullableType to the inner type. |
123 | 113 return None |
124 @property | |
125 def is_basic_type(self): | |
126 return False | |
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 | 114 |
183 def resolve_typedefs(self, typedefs): | 115 def resolve_typedefs(self, typedefs): |
184 raise NotImplementedError( | 116 raise NotImplementedError( |
185 'resolve_typedefs should be defined in subclasses') | 117 'resolve_typedefs should be defined in subclasses') |
186 | 118 |
187 | 119 |
188 ################################################################################ | 120 ################################################################################ |
189 # IdlType | 121 # IdlType |
190 ################################################################################ | 122 ################################################################################ |
191 | 123 |
192 class IdlType(IdlTypeBase): | 124 class IdlType(IdlTypeBase): |
193 # FIXME: incorporate Nullable, etc. | 125 # FIXME: incorporate Nullable, etc. |
194 # to support types like short?[] vs. short[]?, instead of treating these | 126 # to support types like short?[] vs. short[]?, instead of treating these |
195 # as orthogonal properties (via flags). | 127 # as orthogonal properties (via flags). |
196 callback_functions = set() | 128 callback_functions = set() |
197 callback_interfaces = set() | 129 callback_interfaces = set() |
198 dictionaries = set() | 130 dictionaries = set() |
199 enums = {} # name -> values | 131 enums = {} # name -> values |
200 | 132 |
201 def __init__(self, base_type, is_nullable=False, is_unrestricted=False): | 133 def __init__(self, base_type, is_unrestricted=False): |
202 super(IdlType, self).__init__(is_nullable) | 134 super(IdlType, self).__init__() |
203 if is_unrestricted: | 135 if is_unrestricted: |
204 self.base_type = 'unrestricted %s' % base_type | 136 self.base_type = 'unrestricted %s' % base_type |
205 else: | 137 else: |
206 self.base_type = base_type | 138 self.base_type = base_type |
207 | 139 |
208 @property | 140 def __str__(self): |
209 def inner_string(self): | |
210 return self.base_type | 141 return self.base_type |
211 | 142 |
212 @property | 143 @property |
213 def is_basic_type(self): | 144 def is_basic_type(self): |
214 return self.base_type in BASIC_TYPES | 145 return self.base_type in BASIC_TYPES |
215 | 146 |
216 @property | 147 @property |
217 def is_callback_function(self): | 148 def is_callback_function(self): |
218 return self.base_type in IdlType.callback_functions | 149 return self.base_type in IdlType.callback_functions |
219 | 150 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 return not(self.is_basic_type or | 187 return not(self.is_basic_type or |
257 self.is_callback_function or | 188 self.is_callback_function or |
258 self.is_dictionary or | 189 self.is_dictionary or |
259 self.is_enum or | 190 self.is_enum or |
260 self.name == 'Any' or | 191 self.name == 'Any' or |
261 self.name == 'Object' or | 192 self.name == 'Object' or |
262 self.name == 'Promise') # Promise will be basic in future | 193 self.name == 'Promise') # Promise will be basic in future |
263 | 194 |
264 @property | 195 @property |
265 def is_string_type(self): | 196 def is_string_type(self): |
266 return self.inner_name in STRING_TYPES | 197 return self.name in STRING_TYPES |
267 | |
268 @property | |
269 def may_raise_exception_on_conversion(self): | |
270 return (self.is_integer_type or | |
271 self.name in ('ByteString', 'ScalarValueString')) | |
272 | 198 |
273 @property | 199 @property |
274 def is_union_type(self): | 200 def is_union_type(self): |
275 return isinstance(self, IdlUnionType) | 201 return isinstance(self, IdlUnionType) |
276 | 202 |
277 @property | 203 @property |
278 def inner_name(self): | 204 def name(self): |
279 """Return type name (or inner type name if nullable) | 205 """Return type name |
280 | 206 |
281 http://heycam.github.io/webidl/#dfn-type-name | 207 http://heycam.github.io/webidl/#dfn-type-name |
282 """ | 208 """ |
283 base_type = self.base_type | 209 base_type = self.base_type |
284 return TYPE_NAMES.get(base_type, base_type) | 210 return TYPE_NAMES.get(base_type, base_type) |
285 | 211 |
286 @classmethod | 212 @classmethod |
287 def set_callback_functions(cls, new_callback_functions): | 213 def set_callback_functions(cls, new_callback_functions): |
288 cls.callback_functions.update(new_callback_functions) | 214 cls.callback_functions.update(new_callback_functions) |
289 | 215 |
290 @classmethod | 216 @classmethod |
291 def set_callback_interfaces(cls, new_callback_interfaces): | 217 def set_callback_interfaces(cls, new_callback_interfaces): |
292 cls.callback_interfaces.update(new_callback_interfaces) | 218 cls.callback_interfaces.update(new_callback_interfaces) |
293 | 219 |
294 @classmethod | 220 @classmethod |
295 def set_dictionaries(cls, new_dictionaries): | 221 def set_dictionaries(cls, new_dictionaries): |
296 cls.dictionaries.update(new_dictionaries) | 222 cls.dictionaries.update(new_dictionaries) |
297 | 223 |
298 @classmethod | 224 @classmethod |
299 def set_enums(cls, new_enums): | 225 def set_enums(cls, new_enums): |
300 cls.enums.update(new_enums) | 226 cls.enums.update(new_enums) |
301 | 227 |
302 def resolve_typedefs(self, typedefs): | 228 def resolve_typedefs(self, typedefs): |
303 # This function either returns |self|, possibly mutated, or leaves this | 229 # This function either returns |self| or a different object. |
304 # object unmodified and returns a different object. | 230 # FIXME: Rename typedefs_resolved(). |
305 # FIXME: Change to never mutate |self|, and rename typedefs_resolved(). | 231 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 | 232 |
317 | 233 |
318 ################################################################################ | 234 ################################################################################ |
319 # IdlUnionType | 235 # IdlUnionType |
320 ################################################################################ | 236 ################################################################################ |
321 | 237 |
322 class IdlUnionType(IdlTypeBase): | 238 class IdlUnionType(IdlTypeBase): |
323 # http://heycam.github.io/webidl/#idl-union | 239 # http://heycam.github.io/webidl/#idl-union |
324 def __init__(self, member_types, is_nullable=False): | 240 def __init__(self, member_types): |
325 super(IdlUnionType, self).__init__(is_nullable=is_nullable) | 241 super(IdlUnionType, self).__init__() |
326 self.member_types = member_types | 242 self.member_types = member_types |
327 | 243 |
328 @property | 244 @property |
329 def is_union_type(self): | 245 def is_union_type(self): |
330 return True | 246 return True |
331 | 247 |
332 @property | 248 @property |
333 def inner_name(self): | 249 def name(self): |
334 """Return type name (or inner type name if nullable) | 250 """Return type name (or inner type name if nullable) |
335 | 251 |
336 http://heycam.github.io/webidl/#dfn-type-name | 252 http://heycam.github.io/webidl/#dfn-type-name |
337 """ | 253 """ |
338 return 'Or'.join(member_type.name for member_type in self.member_types) | 254 return 'Or'.join(member_type.name for member_type in self.member_types) |
339 | 255 |
340 def resolve_typedefs(self, typedefs): | 256 def resolve_typedefs(self, typedefs): |
341 self.member_types = [ | 257 self.member_types = [ |
342 typedefs.get(member_type, member_type) | 258 typedefs.get(member_type, member_type) |
343 for member_type in self.member_types] | 259 for member_type in self.member_types] |
344 return self | 260 return self |
345 | 261 |
346 | 262 |
347 ################################################################################ | 263 ################################################################################ |
348 # IdlArrayOrSequenceType, IdlArrayType, IdlSequenceType | 264 # IdlArrayOrSequenceType, IdlArrayType, IdlSequenceType |
349 ################################################################################ | 265 ################################################################################ |
350 | 266 |
351 class IdlArrayOrSequenceType(IdlTypeBase): | 267 class IdlArrayOrSequenceType(IdlTypeBase): |
352 """Base class for IdlArrayType and IdlSequenceType.""" | 268 """Base class for IdlArrayType and IdlSequenceType.""" |
353 | 269 |
354 def __init__(self, element_type, is_nullable=False): | 270 def __init__(self, element_type): |
355 super(IdlArrayOrSequenceType, self).__init__(is_nullable) | 271 super(IdlArrayOrSequenceType, self).__init__() |
356 self.element_type = element_type | 272 self.element_type = element_type |
357 | 273 |
358 def resolve_typedefs(self, typedefs): | 274 def resolve_typedefs(self, typedefs): |
359 self.element_type = self.element_type.resolve_typedefs(typedefs) | 275 self.element_type = self.element_type.resolve_typedefs(typedefs) |
360 return self | 276 return self |
361 | 277 |
362 | 278 |
363 class IdlArrayType(IdlArrayOrSequenceType): | 279 class IdlArrayType(IdlArrayOrSequenceType): |
364 def __init__(self, element_type, is_nullable=False): | 280 def __init__(self, element_type): |
365 super(IdlArrayType, self).__init__(element_type, is_nullable) | 281 super(IdlArrayType, self).__init__(element_type) |
366 | 282 |
367 @property | 283 def __str__(self): |
368 def inner_string(self): | |
369 return '%s[]' % self.element_type | 284 return '%s[]' % self.element_type |
370 | 285 |
371 @property | 286 @property |
372 def inner_name(self): | 287 def name(self): |
373 return self.element_type.name + 'Array' | 288 return self.element_type.name + 'Array' |
374 | 289 |
375 | 290 |
376 class IdlSequenceType(IdlArrayOrSequenceType): | 291 class IdlSequenceType(IdlArrayOrSequenceType): |
377 def __init__(self, element_type, is_nullable=False): | 292 def __init__(self, element_type): |
378 super(IdlSequenceType, self).__init__(element_type, is_nullable) | 293 super(IdlSequenceType, self).__init__(element_type) |
379 | 294 |
380 @property | 295 def __str__(self): |
381 def inner_string(self): | |
382 return 'sequence<%s>' % self.element_type | 296 return 'sequence<%s>' % self.element_type |
383 | 297 |
384 @property | 298 @property |
385 def inner_name(self): | 299 def name(self): |
386 return self.element_type.name + 'Sequence' | 300 return self.element_type.name + 'Sequence' |
| 301 |
| 302 |
| 303 ################################################################################ |
| 304 # IdlNullableType |
| 305 ################################################################################ |
| 306 |
| 307 class IdlNullableType(IdlTypeBase): |
| 308 def __init__(self, inner_type): |
| 309 super(IdlNullableType, self).__init__() |
| 310 self.inner_type = inner_type |
| 311 |
| 312 def __str__(self): |
| 313 # FIXME: Dictionary::ConversionContext::setConversionType can't |
| 314 # handle the '?' in nullable types (passes nullability separately). |
| 315 # Update that function to handle nullability from the type name, |
| 316 # simplifying its signature. |
| 317 # return str(self.inner_type) + '?' |
| 318 return str(self.inner_type) |
| 319 |
| 320 def __getattr__(self, name): |
| 321 return getattr(self.inner_type, name) |
| 322 |
| 323 @property |
| 324 def is_nullable(self): |
| 325 return True |
| 326 |
| 327 @property |
| 328 def name(self): |
| 329 # DartFix: Don't handle OrNull all classes generated are same regardless |
| 330 # of nullable type. |
| 331 # return self.inner_type.name + 'OrNull' |
| 332 return self.inner_type.name |
| 333 |
| 334 def resolve_typedefs(self, typedefs): |
| 335 self.inner_type = self.inner_type.resolve_typedefs(typedefs) |
| 336 return self |
OLD | NEW |