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

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

Issue 9845043: Rename client/{dom,html} to lib/{dom,html} . (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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
« no previous file with comments | « client/dom/scripts/generator.py ('k') | client/dom/scripts/idlnode_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 elif isinstance(ast, tuple):
326 (label, value) = ast
327 if label == 'ScopedName':
328 self.id = value
329 else:
330 self.id = self._label_to_type(label, ast)
331 elif isinstance(ast, str):
332 self.id = ast
333 if not self.id:
334 raise SyntaxError('Could not parse type %s' % (ast))
335
336 def _label_to_type(self, label, ast):
337 if label == 'AnyArrayType':
338 return 'any[]'
339 if label == 'DOMStringArrayType':
340 return 'DOMString[]'
341 if label == 'LongLongType':
342 label = 'long long'
343 elif label.endswith('Type'):
344 # Omit 'Type' suffix and lowercase the rest.
345 label = '%s%s' % (label[0].lower(), label[1:-4])
346
347 # Add unsigned qualifier.
348 if self._has(ast, 'Unsigned'):
349 label = 'unsigned %s' % label
350 return label
351
352
353 class IDLTypeDef(IDLNode):
354 """IDLNode for 'typedef [type] [id]' declarations."""
355 def __init__(self, ast):
356 IDLNode.__init__(self, ast)
357 self._convert_annotations(ast)
358 self.type = self._convert_first(ast, 'Type', IDLType)
359
360
361 class IDLInterface(IDLNode):
362 """IDLInterface node contains operations, attributes, constants,
363 as well as parent references."""
364
365 def __init__(self, ast):
366 IDLNode.__init__(self, ast)
367 self._convert_ext_attrs(ast)
368 self._convert_annotations(ast)
369 self.parents = self._convert_all(ast, 'ParentInterface',
370 IDLParentInterface)
371 self.operations = self._convert_all(ast, 'Operation', IDLOperation)
372 self.attributes = self._convert_all(ast, 'Attribute', IDLAttribute)
373 self.constants = self._convert_all(ast, 'Const', IDLConstant)
374 self.is_supplemental = 'Supplemental' in self.ext_attrs
375 self.is_no_interface_object = 'NoInterfaceObject' in self.ext_attrs
376 self.is_fc_suppressed = 'Suppressed' in self.ext_attrs
377 self.javascript_binding_name = self.id
378
379 def has_attribute(self, candidate):
380 for attribute in self.attributes:
381 if (attribute.id == candidate.id and
382 attribute.is_fc_getter == candidate.is_fc_getter and
383 attribute.is_fc_setter == candidate.is_fc_setter):
384 return True
385 return False
386
387
388 class IDLParentInterface(IDLNode):
389 """This IDLNode specialization is for 'Interface Child : Parent {}'
390 declarations."""
391 def __init__(self, ast):
392 IDLNode.__init__(self, ast)
393 self._convert_annotations(ast)
394 self.type = self._convert_first(ast, 'InterfaceType', IDLType)
395
396
397 class IDLMember(IDLNode):
398 """A base class for constants, attributes and operations."""
399
400 def __init__(self, ast):
401 IDLNode.__init__(self, ast)
402 self.type = self._convert_first(ast, 'Type', IDLType)
403 self._convert_ext_attrs(ast)
404 self._convert_annotations(ast)
405 self.is_fc_suppressed = 'Suppressed' in self.ext_attrs
406
407
408 class IDLOperation(IDLMember):
409 """IDLNode specialization for 'type name(args)' declarations."""
410 def __init__(self, ast):
411 IDLMember.__init__(self, ast)
412 self.type = self._convert_first(ast, 'ReturnType', IDLType)
413 self.arguments = self._convert_all(ast, 'Argument', IDLArgument)
414 self.raises = self._convert_first(ast, 'Raises', IDLType)
415 self.specials = self._find_all(ast, 'Special')
416 self.is_stringifier = self._has(ast, 'Stringifier')
417 self.is_static = self._has(ast, 'Static')
418 def _extra_repr(self):
419 return [self.arguments]
420
421
422 class IDLAttribute(IDLMember):
423 """IDLNode specialization for 'attribute type name' declarations."""
424 def __init__(self, ast):
425 IDLMember.__init__(self, ast)
426 self.is_read_only = self._has(ast, 'ReadOnly')
427 # There are various ways to define exceptions for attributes:
428 self.raises = self._convert_first(ast, 'Raises', IDLType)
429 self.get_raises = self.raises \
430 or self._convert_first(ast, 'GetRaises', IDLType)
431 self.set_raises = self.raises \
432 or self._convert_first(ast, 'SetRaises', IDLType)
433 # FremontCut IDL syntax defines getters and setters separately:
434 self.is_fc_getter = self._has(ast, 'AttrGetter')
435 self.is_fc_setter = self._has(ast, 'AttrSetter')
436 def _extra_repr(self):
437 extra = []
438 if self.is_fc_getter: extra.append('get')
439 if self.is_fc_setter: extra.append('set')
440 if self.is_read_only: extra.append('readonly')
441 if self.raises: extra.append('raises')
442 return extra
443
444 class IDLConstant(IDLMember):
445 """IDLNode specialization for 'const type name = value' declarations."""
446 def __init__(self, ast):
447 IDLMember.__init__(self, ast)
448 self.value = self._find_first(ast, 'ConstExpr')
449
450
451 class IDLArgument(IDLNode):
452 """IDLNode specialization for operation arguments."""
453 def __init__(self, ast):
454 IDLNode.__init__(self, ast)
455 self.type = self._convert_first(ast, 'Type', IDLType)
456 self._convert_ext_attrs(ast)
457 # WebKit and Web IDL differ in how Optional is declared:
458 self.is_optional = self._has(ast, 'Optional') \
459 or ('Optional' in self.ext_attrs)
460
461
462 class IDLImplementsStatement(IDLNode):
463 """IDLNode specialization for 'X implements Y' declarations."""
464 def __init__(self, ast):
465 IDLNode.__init__(self, ast)
466 self.implementor = self._convert_first(ast, 'ImplStmtImplementor',
467 IDLType)
468 self.implemented = self._convert_first(ast, 'ImplStmtImplemented',
469 IDLType)
470
471
472 class IDLAnnotations(IDLDictNode):
473 """IDLDictNode specialization for a list of FremontCut annotations."""
474 def __init__(self, ast=None):
475 IDLDictNode.__init__(self, ast)
476 self.id = None
477 if not ast:
478 return
479 for annotation in self._find_all(ast, 'Annotation'):
480 name = self._find_first(annotation, 'Id')
481 value = IDLAnnotation(annotation)
482 self[name] = value
483
484
485 class IDLAnnotation(IDLDictNode):
486 """IDLDictNode specialization for one annotation."""
487 def __init__(self, ast=None):
488 IDLDictNode.__init__(self, ast)
489 self.id = None
490 if not ast:
491 return
492 for arg in self._find_all(ast, 'AnnotationArg'):
493 name = self._find_first(arg, 'Id')
494 value = self._find_first(arg, 'AnnotationArgValue')
495 self[name] = value
OLDNEW
« no previous file with comments | « client/dom/scripts/generator.py ('k') | client/dom/scripts/idlnode_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698