Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(313)

Side by Side Diff: Source/bindings/scripts/idl_types.py

Issue 474173002: IDL: Use IdlNullableType wrapper to represent nullable types (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: alternative approach Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698