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

Side by Side Diff: lib/dom/scripts/idlnode.py

Issue 10913125: Remove lib/dom directory! (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
3 # for details. All rights reserved. Use of this source code is governed by a
4 # BSD-style license that can be found in the LICENSE file.
5
6 import sys
7
8
9 class IDLNode(object):
10 """Base class for all IDL elements.
11 IDLNode may contain various child nodes, and have properties. Examples
12 of IDLNode are modules, interfaces, interface members, function arguments,
13 etc.
14 """
15
16 def __init__(self, ast):
17 """Initializes an IDLNode from a PegParser AST output."""
18 self.id = self._find_first(ast, 'Id') if ast is not None else None
19
20 def __repr__(self):
21 """Generates string of the form <class id extra extra ... 0x12345678>."""
22 extras = self._extra_repr()
23 if isinstance(extras, list):
24 extras = ' '.join([str(e) for e in extras])
25 try:
26 if self.id:
27 return '<%s %s 0x%x>' % (
28 type(self).__name__,
29 ('%s %s' % (self.id, extras)).strip(),
30 hash(self))
31 return '<%s %s 0x%x>' % (
32 type(self).__name__,
33 extras,
34 hash(self))
35 except Exception, e:
36 return "can't convert to string: %s" % e
37
38 def _extra_repr(self):
39 """Returns string of extra info for __repr__()."""
40 return ''
41
42 def __cmp__(self, other):
43 """Override default compare operation.
44 IDLNodes are equal if all their properties are equal."""
45 if other is None or not isinstance(other, IDLNode):
46 return 1
47 return self.__dict__.__cmp__(other.__dict__)
48
49 def all(self, type_filter=None):
50 """Returns a list containing this node and all it child nodes
51 (recursive).
52
53 Args:
54 type_filter -- can be used to limit the results to a specific
55 node type (e.g. IDLOperation).
56 """
57 res = []
58 if type_filter is None or isinstance(self, type_filter):
59 res.append(self)
60 for v in self._all_subnodes():
61 if isinstance(v, IDLNode):
62 res.extend(v.all(type_filter))
63 elif isinstance(v, list):
64 for item in v:
65 if isinstance(item, IDLNode):
66 res.extend(item.all(type_filter))
67 return res
68
69 def _all_subnodes(self):
70 """Accessor used by all() to find subnodes."""
71 return self.__dict__.values()
72
73 def to_dict(self):
74 """Converts the IDLNode and its children into a dictionary.
75 This method is useful mostly for debugging and pretty printing.
76 """
77 res = {}
78 for (k, v) in self.__dict__.items():
79 if v == None or v == False or v == [] or v == {}:
80 # Skip empty/false members.
81 continue
82 elif isinstance(v, IDLDictNode) and not len(v):
83 # Skip empty dict sub-nodes.
84 continue
85 elif isinstance(v, list):
86 # Convert lists:
87 new_v = []
88 for sub_node in v:
89 if isinstance(sub_node, IDLNode):
90 # Convert sub-node:
91 new_v.append(sub_node.to_dict())
92 else:
93 new_v.append(sub_node)
94 v = new_v
95 elif isinstance(v, IDLNode):
96 # Convert sub-node:
97 v = v.to_dict()
98 res[k] = v
99 return res
100
101 def _find_all(self, ast, label, max_results=sys.maxint):
102 """Searches the AST for tuples with a given label. The PegParser
103 output is composed of lists and tuples, where the tuple 1st argument
104 is a label. If ast root is a list, will search recursively inside each
105 member in the list.
106
107 Args:
108 ast -- the AST to search.
109 label -- the label to look for.
110 res -- results are put into this list.
111 max_results -- maximum number of results.
112 """
113 res = []
114 if max_results <= 0:
115 return res
116
117 if isinstance(ast, list):
118 for childAst in ast:
119 sub_res = self._find_all(childAst, label,
120 max_results - len(res))
121 res.extend(sub_res)
122 elif isinstance(ast, tuple):
123 (nodeLabel, value) = ast
124 if nodeLabel == label:
125 res.append(value)
126 return res
127
128 def _find_first(self, ast, label):
129 """Convenience method for _find_all(..., max_results=1).
130 Returns a single element instead of a list, or None if nothing
131 is found."""
132 res = self._find_all(ast, label, max_results=1)
133 if len(res):
134 return res[0]
135 return None
136
137 def _has(self, ast, label):
138 """Returns true if an element with the given label is
139 in the AST by searching for it."""
140 return len(self._find_all(ast, label, max_results=1)) == 1
141
142 def _convert_all(self, ast, label, idlnode_ctor):
143 """Converts AST elements into IDLNode elements.
144 Uses _find_all to find elements with a given label and converts
145 them into IDLNodes with a given constructor.
146 Returns:
147 A list of the converted nodes.
148 Args:
149 ast -- the ast element to start a search at.
150 label -- the element label to look for.
151 idlnode_ctor -- a constructor function of one of the IDLNode
152 sub-classes.
153 """
154 res = []
155 found = self._find_all(ast, label)
156 if not found:
157 return res
158 if not isinstance(found, list):
159 raise RuntimeError("Expected list but %s found" % type(found))
160 for childAst in found:
161 converted = idlnode_ctor(childAst)
162 res.append(converted)
163 return res
164
165 def _convert_first(self, ast, label, idlnode_ctor):
166 """Like _convert_all, but only converts the first found results."""
167 childAst = self._find_first(ast, label)
168 if not childAst:
169 return None
170 return idlnode_ctor(childAst)
171
172 def _convert_ext_attrs(self, ast):
173 """Helper method for uniform conversion of extended attributes."""
174 self.ext_attrs = IDLExtAttrs(ast)
175
176 def _convert_annotations(self, ast):
177 """Helper method for uniform conversion of annotations."""
178 self.annotations = IDLAnnotations(ast)
179
180
181 class IDLDictNode(IDLNode):
182 """Base class for dictionary-like IDL nodes such as extended attributes
183 and annotations. The base class implements various dict interfaces."""
184
185 def __init__(self, ast):
186 IDLNode.__init__(self, None)
187 if ast is not None and isinstance(ast, dict):
188 self.__map = ast
189 else:
190 self.__map = {}
191
192 def __len__(self):
193 return len(self.__map)
194
195 def __getitem__(self, key):
196 return self.__map[key]
197
198 def __setitem__(self, key, value):
199 self.__map[key] = value
200
201 def __delitem__(self, key):
202 del self.__map[key]
203
204 def __contains__(self, key):
205 return key in self.__map
206
207 def __iter__(self):
208 return self.__map.__iter__()
209
210 def get(self, key, default=None):
211 return self.__map.get(key, default)
212
213 def items(self):
214 return self.__map.items()
215
216 def keys(self):
217 return self.__map.keys()
218
219 def values(self):
220 return self.__map.values()
221
222 def clear(self):
223 self.__map = {}
224
225 def to_dict(self):
226 """Overrides the default IDLNode.to_dict behavior.
227 The IDLDictNode members are copied into a new dictionary, and
228 IDLNode members are recursively converted into dicts as well.
229 """
230 res = {}
231 for (k, v) in self.__map.items():
232 if isinstance(v, IDLNode):
233 v = v.to_dict()
234 res[k] = v
235 return res
236
237 def _all_subnodes(self):
238 # Usually an IDLDictNode does not contain further IDLNodes.
239 return []
240
241
242 class IDLFile(IDLNode):
243 """IDLFile is the top-level node in each IDL file. It may contain
244 modules or interfaces."""
245
246 def __init__(self, ast, filename=None):
247 IDLNode.__init__(self, ast)
248 self.filename = filename
249 self.modules = self._convert_all(ast, 'Module', IDLModule)
250 self.interfaces = self._convert_all(ast, 'Interface', IDLInterface)
251
252
253 class IDLModule(IDLNode):
254 """IDLModule has an id, and may contain interfaces, type defs and
255 implements statements."""
256 def __init__(self, ast):
257 IDLNode.__init__(self, ast)
258 self._convert_ext_attrs(ast)
259 self._convert_annotations(ast)
260 self.interfaces = self._convert_all(ast, 'Interface', IDLInterface)
261 self.typeDefs = self._convert_all(ast, 'TypeDef', IDLTypeDef)
262 self.implementsStatements = self._convert_all(ast, 'ImplStmt',
263 IDLImplementsStatement)
264
265
266 class IDLExtAttrs(IDLDictNode):
267 """IDLExtAttrs is an IDLDictNode that stores IDL Extended Attributes.
268 Modules, interfaces, members and arguments can all own IDLExtAttrs."""
269 def __init__(self, ast=None):
270 IDLDictNode.__init__(self, None)
271 if not ast:
272 return
273 ext_attrs_ast = self._find_first(ast, 'ExtAttrs')
274 if not ext_attrs_ast:
275 return
276 for ext_attr in self._find_all(ext_attrs_ast, 'ExtAttr'):
277 name = self._find_first(ext_attr, 'Id')
278 value = self._find_first(ext_attr, 'ExtAttrValue')
279
280 func_value = self._find_first(value, 'ExtAttrFunctionValue')
281 if func_value:
282 # E.g. NamedConstructor=Audio(in [Optional] DOMString src)
283 self[name] = IDLExtAttrFunctionValue(
284 func_value,
285 self._find_first(func_value, 'ExtAttrArgList'))
286 continue
287
288 ctor_args = not value and self._find_first(ext_attr, 'ExtAttrArgList')
289 if ctor_args:
290 # E.g. Constructor(Element host)
291 self[name] = IDLExtAttrFunctionValue(None, ctor_args)
292 continue
293
294 self[name] = value
295
296 def _all_subnodes(self):
297 # Extended attributes may contain IDLNodes, e.g. IDLExtAttrFunctionValue
298 return self.values()
299
300
301 class IDLExtAttrFunctionValue(IDLNode):
302 """IDLExtAttrFunctionValue."""
303 def __init__(self, func_value_ast, arg_list_ast):
304 IDLNode.__init__(self, func_value_ast)
305 self.arguments = self._convert_all(arg_list_ast, 'Argument', IDLArgument)
306
307
308 class IDLType(IDLNode):
309 """IDLType is used to describe constants, attributes and operations'
310 return and input types. IDLType matches AST labels such as ScopedName,
311 StringType, VoidType, IntegerType, etc."""
312
313 def __init__(self, ast):
314 IDLNode.__init__(self, ast)
315 # Search for a 'ScopedName' or any label ending with 'Type'.
316 if isinstance(ast, list):
317 self.id = self._find_first(ast, 'ScopedName')
318 if not self.id:
319 # FIXME: use regexp search instead
320 for childAst in ast:
321 (label, childAst) = childAst
322 if label.endswith('Type'):
323 self.id = self._label_to_type(label, ast)
324 break
325 array_modifiers = self._find_first(ast, 'ArrayModifiers')
326 if array_modifiers:
327 self.id += array_modifiers
328 elif isinstance(ast, tuple):
329 (label, value) = ast
330 if label == 'ScopedName':
331 self.id = value
332 else:
333 self.id = self._label_to_type(label, ast)
334 elif isinstance(ast, str):
335 self.id = ast
336 if not self.id:
337 raise SyntaxError('Could not parse type %s' % (ast))
338
339 def _label_to_type(self, label, ast):
340 if label == 'LongLongType':
341 label = 'long long'
342 elif label.endswith('Type'):
343 # Omit 'Type' suffix and lowercase the rest.
344 label = '%s%s' % (label[0].lower(), label[1:-4])
345
346 # Add unsigned qualifier.
347 if self._has(ast, 'Unsigned'):
348 label = 'unsigned %s' % label
349 return label
350
351
352 class IDLTypeDef(IDLNode):
353 """IDLNode for 'typedef [type] [id]' declarations."""
354 def __init__(self, ast):
355 IDLNode.__init__(self, ast)
356 self._convert_annotations(ast)
357 self.type = self._convert_first(ast, 'Type', IDLType)
358
359
360 class IDLInterface(IDLNode):
361 """IDLInterface node contains operations, attributes, constants,
362 as well as parent references."""
363
364 def __init__(self, ast):
365 IDLNode.__init__(self, ast)
366 self._convert_ext_attrs(ast)
367 self._convert_annotations(ast)
368 self.parents = self._convert_all(ast, 'ParentInterface',
369 IDLParentInterface)
370 self.javascript_binding_name = self.id
371 self.doc_js_name = self.id
372 self.operations = self._convert_all(ast, 'Operation',
373 lambda ast: IDLOperation(ast, self.doc_js_name))
374 self.attributes = self._convert_all(ast, 'Attribute',
375 lambda ast: IDLAttribute(ast, self.doc_js_name))
376 self.constants = self._convert_all(ast, 'Const',
377 lambda ast: IDLConstant(ast, self.doc_js_name))
378 self.is_supplemental = 'Supplemental' in self.ext_attrs
379 self.is_no_interface_object = 'NoInterfaceObject' in self.ext_attrs
380 self.is_fc_suppressed = 'Suppressed' in self.ext_attrs
381
382 def has_attribute(self, candidate):
383 for attribute in self.attributes:
384 if (attribute.id == candidate.id and
385 attribute.is_read_only == candidate.is_read_only):
386 return True
387 return False
388
389
390 class IDLParentInterface(IDLNode):
391 """This IDLNode specialization is for 'Interface Child : Parent {}'
392 declarations."""
393 def __init__(self, ast):
394 IDLNode.__init__(self, ast)
395 self._convert_annotations(ast)
396 self.type = self._convert_first(ast, 'InterfaceType', IDLType)
397
398
399 class IDLMember(IDLNode):
400 """A base class for constants, attributes and operations."""
401
402 def __init__(self, ast, doc_js_interface_name):
403 IDLNode.__init__(self, ast)
404 self.type = self._convert_first(ast, 'Type', IDLType)
405 self._convert_ext_attrs(ast)
406 self._convert_annotations(ast)
407 self.doc_js_interface_name = doc_js_interface_name
408 self.is_fc_suppressed = 'Suppressed' in self.ext_attrs
409 self.is_static = self._has(ast, 'Static')
410
411
412 class IDLOperation(IDLMember):
413 """IDLNode specialization for 'type name(args)' declarations."""
414 def __init__(self, ast, doc_js_interface_name):
415 IDLMember.__init__(self, ast, doc_js_interface_name)
416 self.type = self._convert_first(ast, 'ReturnType', IDLType)
417 self.arguments = self._convert_all(ast, 'Argument', IDLArgument)
418 self.raises = self._convert_first(ast, 'Raises', IDLType)
419 self.specials = self._find_all(ast, 'Special')
420 self.is_stringifier = self._has(ast, 'Stringifier')
421 def _extra_repr(self):
422 return [self.arguments]
423
424
425 class IDLAttribute(IDLMember):
426 """IDLNode specialization for 'attribute type name' declarations."""
427 def __init__(self, ast, doc_js_interface_name):
428 IDLMember.__init__(self, ast, doc_js_interface_name)
429 self.is_read_only = self._has(ast, 'ReadOnly')
430 # There are various ways to define exceptions for attributes:
431 self.raises = self._convert_first(ast, 'Raises', IDLType)
432 self.get_raises = self.raises \
433 or self._convert_first(ast, 'GetRaises', IDLType)
434 self.set_raises = self.raises \
435 or self._convert_first(ast, 'SetRaises', IDLType)
436 def _extra_repr(self):
437 extra = []
438 if self.is_read_only: extra.append('readonly')
439 if self.raises: extra.append('raises')
440 return extra
441
442 class IDLConstant(IDLMember):
443 """IDLNode specialization for 'const type name = value' declarations."""
444 def __init__(self, ast, doc_js_interface_name):
445 IDLMember.__init__(self, ast, doc_js_interface_name)
446 self.value = self._find_first(ast, 'ConstExpr')
447
448
449 class IDLArgument(IDLNode):
450 """IDLNode specialization for operation arguments."""
451 def __init__(self, ast):
452 IDLNode.__init__(self, ast)
453 self.type = self._convert_first(ast, 'Type', IDLType)
454 self._convert_ext_attrs(ast)
455
456 def __repr__(self):
457 return '<IDLArgument(type = %s, id = %s)>' % (self.type, self.id)
458
459
460 class IDLImplementsStatement(IDLNode):
461 """IDLNode specialization for 'X implements Y' declarations."""
462 def __init__(self, ast):
463 IDLNode.__init__(self, ast)
464 self.implementor = self._convert_first(ast, 'ImplStmtImplementor',
465 IDLType)
466 self.implemented = self._convert_first(ast, 'ImplStmtImplemented',
467 IDLType)
468
469
470 class IDLAnnotations(IDLDictNode):
471 """IDLDictNode specialization for a list of FremontCut annotations."""
472 def __init__(self, ast=None):
473 IDLDictNode.__init__(self, ast)
474 self.id = None
475 if not ast:
476 return
477 for annotation in self._find_all(ast, 'Annotation'):
478 name = self._find_first(annotation, 'Id')
479 value = IDLAnnotation(annotation)
480 self[name] = value
481
482
483 class IDLAnnotation(IDLDictNode):
484 """IDLDictNode specialization for one annotation."""
485 def __init__(self, ast=None):
486 IDLDictNode.__init__(self, ast)
487 self.id = None
488 if not ast:
489 return
490 for arg in self._find_all(ast, 'AnnotationArg'):
491 name = self._find_first(arg, 'Id')
492 value = self._find_first(arg, 'AnnotationArgValue')
493 self[name] = value
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698