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

Side by Side Diff: sdk/lib/html/scripts/htmldartgenerator.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, 11 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/go.sh ('k') | sdk/lib/html/scripts/htmleventgenerator.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) 2012, 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 """This module provides shared functionality for the system to generate
7 dart:html APIs from the IDL database."""
8
9 from generator import AnalyzeOperation, ConstantOutputOrder, \
10 DartDomNameOfAttribute, FindMatchingAttribute, IsDartCollectionType, \
11 IsPureInterface, TypeOrNothing
12
13 # Types that are accessible cross-frame in a limited fashion.
14 # In these cases, the base type (e.g., WindowBase) provides restricted access
15 # while the subtype (e.g., Window) provides full access to the
16 # corresponding objects if there are from the same frame.
17 _secure_base_types = {
18 'Window': 'WindowBase',
19 'Location': 'LocationBase',
20 'History': 'HistoryBase',
21 }
22
23 class HtmlDartGenerator(object):
24 def __init__(self, interface, options):
25 self._database = options.database
26 self._interface = interface
27 self._type_registry = options.type_registry
28 self._interface_type_info = self._type_registry.TypeInfo(self._interface.id)
29 self._renamer = options.renamer
30
31 def EmitAttributeDocumentation(self, attribute):
32 """ Emits the MDN dartdoc comment for an attribute.
33 """
34 dom_name = DartDomNameOfAttribute(attribute)
35 self._members_emitter.Emit('\n /// @domName $DOMINTERFACE.$DOMNAME;'
36 ' @docsEditable true',
37 DOMINTERFACE=attribute.doc_js_interface_name,
38 DOMNAME=dom_name)
39
40 def EmitOperationDocumentation(self, operation):
41 """ Emits the MDN dartdoc comment for an operation.
42 """
43 self._members_emitter.Emit('\n /// @domName $DOMINTERFACE.$DOMNAME;'
44 ' @docsEditable true',
45 DOMINTERFACE=operation.overloads[0].doc_js_interface_name,
46 DOMNAME=operation.name)
47
48 def EmitEventGetter(self, events_class_name):
49 self._members_emitter.Emit(
50 '\n /// @domName EventTarget.addEventListener, '
51 'EventTarget.removeEventListener, EventTarget.dispatchEvent;'
52 ' @docsEditable true'
53 '\n $TYPE get on =>\n new $TYPE(this);\n',
54 TYPE=events_class_name)
55
56 def AddMembers(self, interface, declare_only=False):
57 for const in sorted(interface.constants, ConstantOutputOrder):
58 self.AddConstant(const)
59
60 for attr in sorted(interface.attributes, ConstantOutputOrder):
61 if attr.type.id != 'EventListener':
62 self.AddAttribute(attr, declare_only)
63
64 # The implementation should define an indexer if the interface directly
65 # extends List.
66 element_type = None
67 requires_indexer = False
68 if self._interface_type_info.list_item_type():
69 self.AddIndexer(self._interface_type_info.list_item_type())
70 else:
71 for parent in self._database.Hierarchy(self._interface):
72 if parent == self._interface:
73 continue
74 parent_type_info = self._type_registry.TypeInfo(parent.id)
75 if parent_type_info.list_item_type():
76 self.AmendIndexer(parent_type_info.list_item_type())
77 break
78
79 # Group overloaded operations by id.
80 operationsById = {}
81 for operation in interface.operations:
82 if operation.id not in operationsById:
83 operationsById[operation.id] = []
84 operationsById[operation.id].append(operation)
85
86 # Generate operations.
87 for id in sorted(operationsById.keys()):
88 operations = operationsById[id]
89 info = AnalyzeOperation(interface, operations)
90 self.AddOperation(info, declare_only)
91
92 def AddSecondaryMembers(self, interface):
93 # With multiple inheritance, attributes and operations of non-first
94 # interfaces need to be added. Sometimes the attribute or operation is
95 # defined in the current interface as well as a parent. In that case we
96 # avoid making a duplicate definition and pray that the signatures match.
97 secondary_parents = self._TransitiveSecondaryParents(interface)
98 for parent_interface in sorted(secondary_parents):
99 if isinstance(parent_interface, str):
100 continue
101 for attr in sorted(parent_interface.attributes, ConstantOutputOrder):
102 if not FindMatchingAttribute(interface, attr):
103 self.SecondaryContext(parent_interface)
104 self.AddAttribute(attr)
105
106 # Group overloaded operations by id.
107 operationsById = {}
108 for operation in parent_interface.operations:
109 if operation.id not in operationsById:
110 operationsById[operation.id] = []
111 operationsById[operation.id].append(operation)
112
113 # Generate operations.
114 for id in sorted(operationsById.keys()):
115 if not any(op.id == id for op in interface.operations):
116 operations = operationsById[id]
117 info = AnalyzeOperation(interface, operations)
118 self.SecondaryContext(parent_interface)
119 self.AddOperation(info)
120
121 def AddConstant(self, constant):
122 const_name = self._renamer.RenameMember(
123 self._interface.id, constant, constant.id, dartify_name=False)
124 if not const_name:
125 return
126 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id)
127 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n',
128 NAME=const_name,
129 TYPE=type,
130 VALUE=constant.value)
131
132 def AddAttribute(self, attribute, declare_only=False):
133 """ Adds an attribute to the generated class.
134 Arguments:
135 attribute - The attribute which is to be added.
136 declare_only- True if the attribute should be declared as an abstract
137 member and not include invocation code.
138 """
139 dom_name = DartDomNameOfAttribute(attribute)
140 attr_name = self._renamer.RenameMember(
141 self._interface.id, attribute, dom_name, 'get:')
142 if not attr_name or self._IsPrivate(attr_name):
143 return
144
145 html_setter_name = self._renamer.RenameMember(
146 self._interface.id, attribute, dom_name, 'set:')
147 read_only = (attribute.is_read_only or 'Replaceable' in attribute.ext_attrs
148 or not html_setter_name)
149
150 # We don't yet handle inconsistent renames of the getter and setter yet.
151 assert(not html_setter_name or attr_name == html_setter_name)
152
153 if declare_only:
154 self.DeclareAttribute(attribute,
155 self.SecureOutputType(attribute.type.id), attr_name, read_only)
156 else:
157 self.EmitAttribute(attribute, attr_name, read_only)
158
159 def AddOperation(self, info, declare_only=False):
160 """ Adds an operation to the generated class.
161 Arguments:
162 info - The operation info of the operation to be added.
163 declare_only- True if the operation should be declared as an abstract
164 member and not include invocation code.
165 """
166 # FIXME: When we pass in operations[0] below, we're assuming all
167 # overloaded operations have the same security attributes. This
168 # is currently true, but we should consider filtering earlier or
169 # merging the relevant data into info itself.
170 method_name = self._renamer.RenameMember(self._interface.id,
171 info.operations[0],
172 info.name)
173 if not method_name:
174 if info.name == 'item':
175 # FIXME: item should be renamed to operator[], not removed.
176 self.EmitOperation(info, '_item')
177 return
178
179 if declare_only:
180 self.DeclareOperation(info,
181 self.SecureOutputType(info.type_name), method_name)
182 else:
183 self.EmitOperation(info, method_name)
184
185 def AdditionalImplementedInterfaces(self):
186 # TODO: Include all implemented interfaces, including other Lists.
187 implements = []
188 if self._interface_type_info.is_typed_array():
189 element_type = self._interface_type_info.list_item_type()
190 implements.append('List<%s>' % self._DartType(element_type))
191 if self._interface_type_info.list_item_type():
192 item_type_info = self._type_registry.TypeInfo(
193 self._interface_type_info.list_item_type())
194 implements.append('List<%s>' % item_type_info.dart_type())
195 return implements
196
197 def AddConstructors(self,
198 constructors, factory_name, factory_constructor_name):
199 """ Adds all of the constructors.
200 Arguments:
201 constructors - List of the constructors to be added.
202 factory_name - Name of the factory for this class.
203 factory_constructor_name - The name of the constructor on the
204 factory_name to call (calls an autogenerated FactoryProvider
205 if unspecified)
206 """
207 for constructor_info in constructors:
208 self._AddConstructor(
209 constructor_info, factory_name, factory_constructor_name)
210
211 typed_array_type = None
212 for interface in self._database.Hierarchy(self._interface):
213 type_info = self._type_registry.TypeInfo(interface.id)
214 if type_info.is_typed_array():
215 typed_array_type = type_info.list_item_type()
216 break
217 if typed_array_type:
218 self._members_emitter.Emit(
219 '\n'
220 ' factory $CTOR(int length) =>\n'
221 ' $FACTORY.create$(CTOR)(length);\n'
222 '\n'
223 ' factory $CTOR.fromList(List<$TYPE> list) =>\n'
224 ' $FACTORY.create$(CTOR)_fromList(list);\n'
225 '\n'
226 ' factory $CTOR.fromBuffer(ArrayBuffer buffer, '
227 '[int byteOffset, int length]) => \n'
228 ' $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n' ,
229 CTOR=self._interface.id,
230 TYPE=self._DartType(typed_array_type),
231 FACTORY=factory_name)
232
233 def _AddConstructor(self,
234 constructor_info, factory_name, factory_constructor_name):
235 self._members_emitter.Emit('\n ///@docsEditable true');
236
237 if not factory_constructor_name:
238 factory_constructor_name = '_create'
239 factory_parameters = constructor_info.ParametersAsArgumentList()
240 has_factory_provider = True
241 else:
242 factory_parameters = ', '.join(constructor_info.factory_parameters)
243 has_factory_provider = False
244
245 has_optional = any(param_info.is_optional
246 for param_info in constructor_info.param_infos)
247
248 if not has_optional:
249 self._members_emitter.Emit(
250 '\n'
251 ' factory $CTOR($PARAMS) => '
252 '$FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n',
253 CTOR=constructor_info._ConstructorFullName(self._DartType),
254 PARAMS=constructor_info.ParametersDeclaration(self._DartType),
255 FACTORY=factory_name,
256 CTOR_FACTORY_NAME=factory_constructor_name,
257 FACTORY_PARAMS=factory_parameters)
258 else:
259 if has_factory_provider:
260 dispatcher_emitter = self._members_emitter.Emit(
261 '\n'
262 ' factory $CTOR($PARAMS) {\n'
263 '$!DISPATCHER'
264 ' return $FACTORY._create($FACTORY_PARAMS);\n'
265 ' }\n',
266 CTOR=constructor_info._ConstructorFullName(self._DartType),
267 PARAMS=constructor_info.ParametersDeclaration(self._DartType),
268 FACTORY=factory_name,
269 FACTORY_PARAMS=constructor_info.ParametersAsArgumentList())
270
271 for index, param_info in enumerate(constructor_info.param_infos):
272 if param_info.is_optional:
273 dispatcher_emitter.Emit(
274 ' if (!?$OPT_PARAM_NAME) {\n'
275 ' return $FACTORY._create($FACTORY_PARAMS);\n'
276 ' }\n',
277 OPT_PARAM_NAME=constructor_info.param_infos[index].name,
278 FACTORY=factory_name,
279 FACTORY_PARAMS=constructor_info.ParametersAsArgumentList(index))
280 else:
281 inits = self._members_emitter.Emit(
282 '\n'
283 ' factory $CONSTRUCTOR($PARAMS) {\n'
284 ' var e = $FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n'
285 '$!INITS'
286 ' return e;\n'
287 ' }\n',
288 CONSTRUCTOR=constructor_info._ConstructorFullName(self._DartType),
289 FACTORY=factory_name,
290 CTOR_FACTORY_NAME=factory_constructor_name,
291 PARAMS=constructor_info.ParametersDeclaration(self._DartType),
292 FACTORY_PARAMS=factory_parameters)
293
294 for index, param_info in enumerate(constructor_info.param_infos):
295 if param_info.is_optional:
296 inits.Emit(' if ($E != null) e.$E = $E;\n',
297 E=constructor_info.param_infos[index].name)
298
299 if not constructor_info.pure_dart_constructor:
300 template_file = ('factoryprovider_%s.darttemplate' % self._interface.doc_j s_name)
301 template = self._template_loader.TryLoad(template_file)
302 if template:
303 # There is a class specific factory.
304 # TODO(antonm): should move into the class template.
305 self._members_emitter.Emit(template)
306 else:
307 self.EmitStaticFactory(constructor_info)
308
309 def EmitHelpers(self, base_class):
310 pass
311
312 def DeclareAttribute(self, attribute, type_name, attr_name, read_only):
313 """ Declares an attribute but does not include the code to invoke it.
314 """
315 self.EmitAttributeDocumentation(attribute)
316 if read_only:
317 template = '\n $TYPE get $NAME;\n'
318 else:
319 template = '\n $TYPE $NAME;\n'
320
321 self._members_emitter.Emit(template,
322 NAME=attr_name,
323 TYPE=type_name)
324
325 def DeclareOperation(self, operation, return_type_name, method_name):
326 """ Declares an operation but does not include the code to invoke it.
327 Arguments:
328 operation - The operation to be declared.
329 return_type_name - The name of the return type.
330 method_name - The name of the method.
331 """
332 self.EmitOperationDocumentation(operation)
333 self._members_emitter.Emit(
334 '\n'
335 ' $TYPE $NAME($PARAMS);\n',
336 TYPE=return_type_name,
337 NAME=method_name,
338 PARAMS=operation.ParametersDeclaration(self._DartType))
339
340 def EmitListMixin(self, element_name):
341 # TODO(sra): Use separate mixins for mutable implementations of List<T>.
342 # TODO(sra): Use separate mixins for typed array implementations of List<T>.
343 template_file = 'immutable_list_mixin.darttemplate'
344 has_contains = any(op.id == 'contains' for op in self._interface.operations)
345 has_clear = any(op.id == 'clear' for op in self._interface.operations)
346 has_length = False
347 has_length_setter = False
348 for attr in self._interface.attributes:
349 if attr.id == 'length':
350 has_length = True
351 has_length_setter = not attr.is_read_only
352
353 has_num_items = any(attr.id == 'numberOfItems'
354 for attr in self._interface.attributes)
355
356 template = self._template_loader.Load(
357 template_file,
358 {
359 'DEFINE_CONTAINS': not has_contains,
360 'DEFINE_CLEAR': not has_clear,
361 'DEFINE_LENGTH_AS_NUM_ITEMS': not has_length and has_num_items,
362 'DEFINE_LENGTH_SETTER': not has_length_setter,
363 })
364 self._members_emitter.Emit(template, E=element_name)
365
366 def SecureOutputType(self, type_name, is_dart_type=False):
367 """ Converts the type name to the secure type name for return types.
368 """
369 if is_dart_type:
370 dart_name = type_name
371 else:
372 dart_name = self._DartType(type_name)
373 # We only need to secure Window. Only local History and Location are
374 # returned in generated code.
375 assert(dart_name != 'HistoryBase' and dart_name != 'LocationBase')
376 if dart_name == 'Window':
377 return _secure_base_types[dart_name]
378 return dart_name
379
380 def SecureBaseName(self, type_name):
381 if type_name in _secure_base_types:
382 return _secure_base_types[type_name]
383
384 def _TransitiveSecondaryParents(self, interface):
385 """Returns a list of all non-primary parents.
386
387 The list contains the interface objects for interfaces defined in the
388 database, and the name for undefined interfaces.
389 """
390 def walk(parents):
391 for parent in parents:
392 parent_name = parent.type.id
393 if parent_name == 'EventTarget':
394 # Currently EventTarget is implemented as a mixin, not a proper
395 # super interface---ignore its members.
396 continue
397 if IsDartCollectionType(parent_name):
398 result.append(parent_name)
399 continue
400 if self._database.HasInterface(parent_name):
401 parent_interface = self._database.GetInterface(parent_name)
402 result.append(parent_interface)
403 walk(parent_interface.parents)
404
405 result = []
406 if interface.parents:
407 parent = interface.parents[0]
408 if IsPureInterface(parent.type.id):
409 walk(interface.parents)
410 else:
411 walk(interface.parents[1:])
412 return result
413
414 def _DartType(self, type_name):
415 return self._type_registry.DartType(type_name)
416
417 def _IsPrivate(self, name):
418 return name.startswith('_')
OLDNEW
« no previous file with comments | « sdk/lib/html/scripts/go.sh ('k') | sdk/lib/html/scripts/htmleventgenerator.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698