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 IdlNullableType |
| 14 |
| 15 IdlTypes are picklable because we store them in interfaces_info. |
14 """ | 16 """ |
15 | 17 |
16 from collections import defaultdict | 18 from collections import defaultdict |
17 | 19 |
18 | 20 |
19 ################################################################################ | 21 ################################################################################ |
20 # IDL types | 22 # IDL types |
21 ################################################################################ | 23 ################################################################################ |
22 | 24 |
23 INTEGER_TYPES = frozenset([ | 25 INTEGER_TYPES = frozenset([ |
(...skipping 15 matching lines...) Expand all Loading... |
39 'double', | 41 'double', |
40 'unrestricted double', | 42 'unrestricted double', |
41 ])) | 43 ])) |
42 # http://www.w3.org/TR/WebIDL/#dfn-primitive-type | 44 # http://www.w3.org/TR/WebIDL/#dfn-primitive-type |
43 PRIMITIVE_TYPES = (frozenset(['boolean']) | NUMERIC_TYPES) | 45 PRIMITIVE_TYPES = (frozenset(['boolean']) | NUMERIC_TYPES) |
44 BASIC_TYPES = (PRIMITIVE_TYPES | frozenset([ | 46 BASIC_TYPES = (PRIMITIVE_TYPES | frozenset([ |
45 # Built-in, non-composite, non-object data types | 47 # Built-in, non-composite, non-object data types |
46 # http://heycam.github.io/webidl/#idl-types | 48 # http://heycam.github.io/webidl/#idl-types |
47 'DOMString', | 49 'DOMString', |
48 'ByteString', | 50 'ByteString', |
| 51 'USVString', |
49 'Date', | 52 'Date', |
50 # http://heycam.github.io/webidl/#es-type-mapping | 53 # http://heycam.github.io/webidl/#idl-types |
51 'void', | 54 'void', |
52 # http://encoding.spec.whatwg.org/#type-scalarvaluestring | |
53 'ScalarValueString', | |
54 ])) | 55 ])) |
55 TYPE_NAMES = { | 56 TYPE_NAMES = { |
56 # http://heycam.github.io/webidl/#dfn-type-name | 57 # http://heycam.github.io/webidl/#dfn-type-name |
57 'any': 'Any', | 58 'any': 'Any', |
58 'boolean': 'Boolean', | 59 'boolean': 'Boolean', |
59 'byte': 'Byte', | 60 'byte': 'Byte', |
60 'octet': 'Octet', | 61 'octet': 'Octet', |
61 'short': 'Short', | 62 'short': 'Short', |
62 'unsigned short': 'UnsignedShort', | 63 'unsigned short': 'UnsignedShort', |
63 'long': 'Long', | 64 'long': 'Long', |
64 'unsigned long': 'UnsignedLong', | 65 'unsigned long': 'UnsignedLong', |
65 'long long': 'LongLong', | 66 'long long': 'LongLong', |
66 'unsigned long long': 'UnsignedLongLong', | 67 'unsigned long long': 'UnsignedLongLong', |
67 'float': 'Float', | 68 'float': 'Float', |
68 'unrestricted float': 'UnrestrictedFloat', | 69 'unrestricted float': 'UnrestrictedFloat', |
69 'double': 'Double', | 70 'double': 'Double', |
70 'unrestricted double': 'UnrestrictedDouble', | 71 'unrestricted double': 'UnrestrictedDouble', |
71 'DOMString': 'String', | 72 'DOMString': 'String', |
72 'ByteString': 'ByteString', | 73 'ByteString': 'ByteString', |
73 'ScalarValueString': 'ScalarValueString', | 74 'USVString': 'USVString', |
74 'object': 'Object', | 75 'object': 'Object', |
75 'Date': 'Date', | 76 'Date': 'Date', |
76 } | 77 } |
77 | 78 |
78 STRING_TYPES = frozenset([ | 79 STRING_TYPES = frozenset([ |
79 # http://heycam.github.io/webidl/#es-interface-call (step 10.11) | 80 # http://heycam.github.io/webidl/#es-interface-call (step 10.11) |
80 # (Interface object [[Call]] method's string types.) | 81 # (Interface object [[Call]] method's string types.) |
81 'String', | 82 'String', |
82 'ByteString', | 83 'ByteString', |
83 'ScalarValueString', | 84 'USVString', |
| 85 ]) |
| 86 |
| 87 STANDARD_CALLBACK_FUNCTIONS = frozenset([ |
| 88 # http://heycam.github.io/webidl/#common-Function |
| 89 'Function', |
| 90 # http://heycam.github.io/webidl/#common-VoidFunction |
| 91 'VoidFunction', |
84 ]) | 92 ]) |
85 | 93 |
86 | 94 |
87 ################################################################################ | 95 ################################################################################ |
88 # Inheritance | 96 # Inheritance |
89 ################################################################################ | 97 ################################################################################ |
90 | 98 |
91 ancestors = defaultdict(list) # interface_name -> ancestors | 99 ancestors = defaultdict(list) # interface_name -> ancestors |
92 | 100 |
93 def inherits_interface(interface_name, ancestor_name): | 101 def inherits_interface(interface_name, ancestor_name): |
(...skipping 15 matching lines...) Expand all Loading... |
109 def __getattr__(self, name): | 117 def __getattr__(self, name): |
110 # Default undefined attributes to None (analogous to Jinja variables). | 118 # Default undefined attributes to None (analogous to Jinja variables). |
111 # This allows us to not define default properties in the base class, and | 119 # This allows us to not define default properties in the base class, and |
112 # allows us to relay __getattr__ in IdlNullableType to the inner type. | 120 # allows us to relay __getattr__ in IdlNullableType to the inner type. |
113 return None | 121 return None |
114 | 122 |
115 def resolve_typedefs(self, typedefs): | 123 def resolve_typedefs(self, typedefs): |
116 raise NotImplementedError( | 124 raise NotImplementedError( |
117 'resolve_typedefs should be defined in subclasses') | 125 'resolve_typedefs should be defined in subclasses') |
118 | 126 |
| 127 def idl_types(self): |
| 128 """A generator which yields IdlTypes which are referenced from |self|, |
| 129 including itself.""" |
| 130 yield self |
| 131 |
119 | 132 |
120 ################################################################################ | 133 ################################################################################ |
121 # IdlType | 134 # IdlType |
122 ################################################################################ | 135 ################################################################################ |
123 | 136 |
124 class IdlType(IdlTypeBase): | 137 class IdlType(IdlTypeBase): |
125 # FIXME: incorporate Nullable, etc. | 138 # FIXME: incorporate Nullable, etc. |
126 # to support types like short?[] vs. short[]?, instead of treating these | 139 # to support types like short?[] vs. short[]?, instead of treating these |
127 # as orthogonal properties (via flags). | 140 # as orthogonal properties (via flags). |
128 callback_functions = set() | 141 callback_functions = set(STANDARD_CALLBACK_FUNCTIONS) |
129 callback_interfaces = set() | 142 callback_interfaces = set() |
130 dictionaries = set() | 143 dictionaries = set() |
131 enums = {} # name -> values | 144 enums = {} # name -> values |
132 | 145 |
133 def __init__(self, base_type, is_unrestricted=False): | 146 def __init__(self, base_type, is_unrestricted=False): |
134 super(IdlType, self).__init__() | 147 super(IdlType, self).__init__() |
135 if is_unrestricted: | 148 if is_unrestricted: |
136 self.base_type = 'unrestricted %s' % base_type | 149 self.base_type = 'unrestricted %s' % base_type |
137 else: | 150 else: |
138 self.base_type = base_type | 151 self.base_type = base_type |
139 | 152 |
140 def __str__(self): | 153 def __str__(self): |
141 return self.base_type | 154 return self.base_type |
142 | 155 |
| 156 def __getstate__(self): |
| 157 return { |
| 158 'base_type': self.base_type, |
| 159 } |
| 160 |
| 161 def __setstate__(self, state): |
| 162 self.base_type = state['base_type'] |
| 163 |
143 @property | 164 @property |
144 def is_basic_type(self): | 165 def is_basic_type(self): |
145 return self.base_type in BASIC_TYPES | 166 return self.base_type in BASIC_TYPES |
146 | 167 |
147 @property | 168 @property |
148 def is_callback_function(self): | 169 def is_callback_function(self): |
149 return self.base_type in IdlType.callback_functions | 170 return self.base_type in IdlType.callback_functions |
150 | 171 |
151 @property | 172 @property |
152 def is_callback_interface(self): | 173 def is_callback_interface(self): |
153 return self.base_type in IdlType.callback_interfaces | 174 return self.base_type in IdlType.callback_interfaces |
154 | 175 |
155 @property | 176 @property |
156 def is_dictionary(self): | 177 def is_dictionary(self): |
157 return self.base_type in IdlType.dictionaries | 178 return self.base_type in IdlType.dictionaries |
158 | 179 |
159 @property | 180 @property |
160 def is_enum(self): | 181 def is_enum(self): |
161 # FIXME: add an IdlEnumType class and a resolve_enums step at end of | 182 # FIXME: add an IdlEnumType class and a resolve_enums step at end of |
162 # IdlDefinitions constructor | 183 # IdlDefinitions constructor |
163 return self.name in IdlType.enums | 184 return self.name in IdlType.enums |
164 | 185 |
165 @property | 186 @property |
166 def enum_values(self): | 187 def enum_values(self): |
167 return IdlType.enums[self.name] | 188 return IdlType.enums.get(self.name) |
| 189 |
| 190 @property |
| 191 def enum_type(self): |
| 192 return self.name if self.is_enum else None |
168 | 193 |
169 @property | 194 @property |
170 def is_integer_type(self): | 195 def is_integer_type(self): |
171 return self.base_type in INTEGER_TYPES | 196 return self.base_type in INTEGER_TYPES |
172 | 197 |
173 @property | 198 @property |
174 def is_numeric_type(self): | 199 def is_numeric_type(self): |
175 return self.base_type in NUMERIC_TYPES | 200 return self.base_type in NUMERIC_TYPES |
176 | 201 |
177 @property | 202 @property |
(...skipping 12 matching lines...) Expand all Loading... |
190 self.is_enum or | 215 self.is_enum or |
191 self.name == 'Any' or | 216 self.name == 'Any' or |
192 self.name == 'Object' or | 217 self.name == 'Object' or |
193 self.name == 'Promise') # Promise will be basic in future | 218 self.name == 'Promise') # Promise will be basic in future |
194 | 219 |
195 @property | 220 @property |
196 def is_string_type(self): | 221 def is_string_type(self): |
197 return self.name in STRING_TYPES | 222 return self.name in STRING_TYPES |
198 | 223 |
199 @property | 224 @property |
200 def is_union_type(self): | |
201 return isinstance(self, IdlUnionType) | |
202 | |
203 @property | |
204 def name(self): | 225 def name(self): |
205 """Return type name | 226 """Return type name |
206 | 227 |
207 http://heycam.github.io/webidl/#dfn-type-name | 228 http://heycam.github.io/webidl/#dfn-type-name |
208 """ | 229 """ |
209 base_type = self.base_type | 230 base_type = self.base_type |
210 return TYPE_NAMES.get(base_type, base_type) | 231 return TYPE_NAMES.get(base_type, base_type) |
211 | 232 |
212 @classmethod | 233 @classmethod |
213 def set_callback_functions(cls, new_callback_functions): | 234 def set_callback_functions(cls, new_callback_functions): |
(...skipping 16 matching lines...) Expand all Loading... |
230 # FIXME: Rename typedefs_resolved(). | 251 # FIXME: Rename typedefs_resolved(). |
231 return typedefs.get(self.base_type, self) | 252 return typedefs.get(self.base_type, self) |
232 | 253 |
233 | 254 |
234 ################################################################################ | 255 ################################################################################ |
235 # IdlUnionType | 256 # IdlUnionType |
236 ################################################################################ | 257 ################################################################################ |
237 | 258 |
238 class IdlUnionType(IdlTypeBase): | 259 class IdlUnionType(IdlTypeBase): |
239 # http://heycam.github.io/webidl/#idl-union | 260 # http://heycam.github.io/webidl/#idl-union |
| 261 # IdlUnionType has __hash__() and __eq__() methods because they are stored |
| 262 # in sets. |
240 def __init__(self, member_types): | 263 def __init__(self, member_types): |
241 super(IdlUnionType, self).__init__() | 264 super(IdlUnionType, self).__init__() |
242 self.member_types = member_types | 265 self.member_types = member_types |
243 | 266 |
| 267 def __str__(self): |
| 268 return '(' + ' or '.join(str(member_type) for member_type in self.member
_types) + ')' |
| 269 |
| 270 def __hash__(self): |
| 271 return hash(self.name) |
| 272 |
| 273 def __eq__(self, rhs): |
| 274 return self.name == rhs.name |
| 275 |
| 276 def __getstate__(self): |
| 277 return { |
| 278 'member_types': self.member_types, |
| 279 } |
| 280 |
| 281 def __setstate__(self, state): |
| 282 self.member_types = state['member_types'] |
| 283 |
244 @property | 284 @property |
245 def is_union_type(self): | 285 def is_union_type(self): |
246 return True | 286 return True |
247 | 287 |
| 288 def single_matching_member_type(self, predicate): |
| 289 matching_types = filter(predicate, self.member_types) |
| 290 if len(matching_types) > 1: |
| 291 raise "%s is ambigious." % self.name |
| 292 return matching_types[0] if matching_types else None |
| 293 |
| 294 @property |
| 295 def string_member_type(self): |
| 296 return self.single_matching_member_type( |
| 297 lambda member_type: (member_type.is_string_type or |
| 298 member_type.is_enum)) |
| 299 |
| 300 @property |
| 301 def numeric_member_type(self): |
| 302 return self.single_matching_member_type( |
| 303 lambda member_type: member_type.is_numeric_type) |
| 304 |
| 305 @property |
| 306 def boolean_member_type(self): |
| 307 return self.single_matching_member_type( |
| 308 lambda member_type: member_type.base_type == 'boolean') |
| 309 |
| 310 @property |
| 311 def as_union_type(self): |
| 312 # Note: Use this to "look through" a possible IdlNullableType wrapper. |
| 313 return self |
| 314 |
248 @property | 315 @property |
249 def name(self): | 316 def name(self): |
250 """Return type name (or inner type name if nullable) | 317 """Return type name (or inner type name if nullable) |
251 | 318 |
252 http://heycam.github.io/webidl/#dfn-type-name | 319 http://heycam.github.io/webidl/#dfn-type-name |
253 """ | 320 """ |
254 return 'Or'.join(member_type.name for member_type in self.member_types) | 321 return 'Or'.join(member_type.name for member_type in self.member_types) |
255 | 322 |
256 def resolve_typedefs(self, typedefs): | 323 def resolve_typedefs(self, typedefs): |
257 self.member_types = [ | 324 self.member_types = [ |
258 typedefs.get(member_type, member_type) | 325 typedefs.get(member_type, member_type) |
259 for member_type in self.member_types] | 326 for member_type in self.member_types] |
260 return self | 327 return self |
261 | 328 |
| 329 def idl_types(self): |
| 330 yield self |
| 331 for member_type in self.member_types: |
| 332 for idl_type in member_type.idl_types(): |
| 333 yield idl_type |
| 334 |
262 | 335 |
263 ################################################################################ | 336 ################################################################################ |
264 # IdlArrayOrSequenceType, IdlArrayType, IdlSequenceType | 337 # IdlArrayOrSequenceType, IdlArrayType, IdlSequenceType |
265 ################################################################################ | 338 ################################################################################ |
266 | 339 |
267 class IdlArrayOrSequenceType(IdlTypeBase): | 340 class IdlArrayOrSequenceType(IdlTypeBase): |
268 """Base class for IdlArrayType and IdlSequenceType.""" | 341 """Base class for IdlArrayType and IdlSequenceType.""" |
269 | 342 |
270 def __init__(self, element_type): | 343 def __init__(self, element_type): |
271 super(IdlArrayOrSequenceType, self).__init__() | 344 super(IdlArrayOrSequenceType, self).__init__() |
272 self.element_type = element_type | 345 self.element_type = element_type |
273 | 346 |
| 347 def __getstate__(self): |
| 348 return { |
| 349 'element_type': self.element_type, |
| 350 } |
| 351 |
| 352 def __setstate__(self, state): |
| 353 self.element_type = state['element_type'] |
| 354 |
274 def resolve_typedefs(self, typedefs): | 355 def resolve_typedefs(self, typedefs): |
275 self.element_type = self.element_type.resolve_typedefs(typedefs) | 356 self.element_type = self.element_type.resolve_typedefs(typedefs) |
276 return self | 357 return self |
277 | 358 |
| 359 @property |
| 360 def is_array_or_sequence_type(self): |
| 361 return True |
| 362 |
| 363 @property |
| 364 def enum_values(self): |
| 365 return self.element_type.enum_values |
| 366 |
| 367 @property |
| 368 def enum_type(self): |
| 369 return self.element_type.enum_type |
| 370 |
| 371 def idl_types(self): |
| 372 yield self |
| 373 for idl_type in self.element_type.idl_types(): |
| 374 yield idl_type |
| 375 |
278 | 376 |
279 class IdlArrayType(IdlArrayOrSequenceType): | 377 class IdlArrayType(IdlArrayOrSequenceType): |
280 def __init__(self, element_type): | 378 def __init__(self, element_type): |
281 super(IdlArrayType, self).__init__(element_type) | 379 super(IdlArrayType, self).__init__(element_type) |
282 | 380 |
283 def __str__(self): | 381 def __str__(self): |
284 return '%s[]' % self.element_type | 382 return '%s[]' % self.element_type |
285 | 383 |
286 @property | 384 @property |
287 def name(self): | 385 def name(self): |
(...skipping 25 matching lines...) Expand all Loading... |
313 # FIXME: Dictionary::ConversionContext::setConversionType can't | 411 # FIXME: Dictionary::ConversionContext::setConversionType can't |
314 # handle the '?' in nullable types (passes nullability separately). | 412 # handle the '?' in nullable types (passes nullability separately). |
315 # Update that function to handle nullability from the type name, | 413 # Update that function to handle nullability from the type name, |
316 # simplifying its signature. | 414 # simplifying its signature. |
317 # return str(self.inner_type) + '?' | 415 # return str(self.inner_type) + '?' |
318 return str(self.inner_type) | 416 return str(self.inner_type) |
319 | 417 |
320 def __getattr__(self, name): | 418 def __getattr__(self, name): |
321 return getattr(self.inner_type, name) | 419 return getattr(self.inner_type, name) |
322 | 420 |
| 421 def __getstate__(self): |
| 422 return { |
| 423 'inner_type': self.inner_type, |
| 424 } |
| 425 |
| 426 def __setstate__(self, state): |
| 427 self.inner_type = state['inner_type'] |
| 428 |
323 @property | 429 @property |
324 def is_nullable(self): | 430 def is_nullable(self): |
325 return True | 431 return True |
326 | 432 |
327 @property | 433 @property |
328 def name(self): | 434 def name(self): |
329 # DartFix: Don't handle OrNull all classes generated are same regardless | 435 return self.inner_type.name + 'OrNull' |
330 # of nullable type. | |
331 # return self.inner_type.name + 'OrNull' | |
332 return self.inner_type.name | |
333 | 436 |
334 def resolve_typedefs(self, typedefs): | 437 def resolve_typedefs(self, typedefs): |
335 self.inner_type = self.inner_type.resolve_typedefs(typedefs) | 438 self.inner_type = self.inner_type.resolve_typedefs(typedefs) |
336 return self | 439 return self |
| 440 |
| 441 def idl_types(self): |
| 442 yield self |
| 443 for idl_type in self.inner_type.idl_types(): |
| 444 yield idl_type |
OLD | NEW |