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

Side by Side Diff: sdk/lib/html/scripts/idlnode.py

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

Powered by Google App Engine
This is Rietveld 408576698