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

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

Issue 11363130: Cleaning up dart:html generation after interface/implementation merge. Removing most of the interfa… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Incorporating review feedback, cleaning up comments Created 8 years, 1 month 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/dartium/html_dartium.dart ('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
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 4 # BSD-style license that can be found in the LICENSE file.
5 5
6 """This module provides shared functionality for the system to generate 6 """This module provides shared functionality for the system to generate
7 dart:html APIs from the IDL database.""" 7 dart:html APIs from the IDL database."""
8 8
9 from generator import DartDomNameOfAttribute 9 from generator import AnalyzeOperation, ConstantOutputOrder, \
10 DartDomNameOfAttribute, FindMatchingAttribute, IsDartCollectionType, \
11 IsPureInterface
12
13 # Types that are accessible cross-frame in a limited fashion.
14 # In these cases, the base type (e.g., Window) provides restricted access
15 # while the subtype (e.g., LocalWindow) provides full access to the
16 # corresponding objects if there are from the same frame.
17 _secure_base_types = {
18 'LocalWindow': 'Window',
19 'LocalLocation': 'Location',
20 'LocalHistory': 'History',
21 }
10 22
11 class HtmlDartGenerator(object): 23 class HtmlDartGenerator(object):
12 def __init__(self, interface, options): 24 def __init__(self, interface, options):
25 self._database = options.database
13 self._interface = interface 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
14 30
15 def EmitAttributeDocumentation(self, attribute): 31 def EmitAttributeDocumentation(self, attribute):
32 """ Emits the MDN dartdoc comment for an attribute.
33 """
16 dom_name = DartDomNameOfAttribute(attribute) 34 dom_name = DartDomNameOfAttribute(attribute)
17 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', 35 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */',
18 DOMINTERFACE=attribute.doc_js_interface_name, 36 DOMINTERFACE=attribute.doc_js_interface_name,
19 DOMNAME=dom_name) 37 DOMNAME=dom_name)
20 38
21 def EmitOperationDocumentation(self, operation): 39 def EmitOperationDocumentation(self, operation):
40 """ Emits the MDN dartdoc comment for an operation.
41 """
22 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', 42 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */',
23 DOMINTERFACE=operation.overloads[0].doc_js_interface_name, 43 DOMINTERFACE=operation.overloads[0].doc_js_interface_name,
24 DOMNAME=operation.name) 44 DOMNAME=operation.name)
25 45
46 def EmitEventGetter(self, events_class_name):
47 self._members_emitter.Emit(
48 '\n /**'
49 '\n * @domName EventTarget.addEventListener, '
50 'EventTarget.removeEventListener, EventTarget.dispatchEvent'
51 '\n */'
52 '\n $TYPE get on =>\n new $TYPE(this);\n',
53 TYPE=events_class_name)
54
55 def AddMembers(self, interface, declare_only=False):
56 for const in sorted(interface.constants, ConstantOutputOrder):
57 self.AddConstant(const)
58
59 for attr in sorted(interface.attributes, ConstantOutputOrder):
60 if attr.type.id != 'EventListener':
61 self.AddAttribute(attr, declare_only)
62
63 # The implementation should define an indexer if the interface directly
64 # extends List.
65 element_type = None
66 requires_indexer = False
67 if self._interface_type_info.list_item_type():
68 self.AddIndexer(self._interface_type_info.list_item_type())
69 else:
70 for parent in self._database.Hierarchy(self._interface):
71 if parent == self._interface:
72 continue
73 parent_type_info = self._type_registry.TypeInfo(parent.id)
74 if parent_type_info.list_item_type():
75 self.AmendIndexer(parent_type_info.list_item_type())
76 break
77
78 # Group overloaded operations by id.
79 operationsById = {}
80 for operation in interface.operations:
81 if operation.id not in operationsById:
82 operationsById[operation.id] = []
83 operationsById[operation.id].append(operation)
84
85 # Generate operations.
86 for id in sorted(operationsById.keys()):
87 operations = operationsById[id]
88 info = AnalyzeOperation(interface, operations)
89 self.AddOperation(info, declare_only)
90
91 def AddSecondaryMembers(self, interface):
92 # With multiple inheritance, attributes and operations of non-first
93 # interfaces need to be added. Sometimes the attribute or operation is
94 # defined in the current interface as well as a parent. In that case we
95 # avoid making a duplicate definition and pray that the signatures match.
96 secondary_parents = self._TransitiveSecondaryParents(interface)
97 for parent_interface in sorted(secondary_parents):
98 if isinstance(parent_interface, str):
99 continue
100 for attr in sorted(parent_interface.attributes, ConstantOutputOrder):
101 if not FindMatchingAttribute(interface, attr):
102 self.SecondaryContext(parent_interface)
103 self.AddAttribute(attr)
104
105 # Group overloaded operations by id.
106 operationsById = {}
107 for operation in parent_interface.operations:
108 if operation.id not in operationsById:
109 operationsById[operation.id] = []
110 operationsById[operation.id].append(operation)
111
112 # Generate operations.
113 for id in sorted(operationsById.keys()):
114 if not any(op.id == id for op in interface.operations):
115 operations = operationsById[id]
116 info = AnalyzeOperation(interface, operations)
117 self.SecondaryContext(parent_interface)
118 self.AddOperation(info)
119
120 def AddAttribute(self, attribute, declare_only=False):
121 """ Adds an attribute to the generated class.
122 Arguments:
123 attribute - The attribute which is to be added.
124 declare_only- True if the attribute should be declared as an abstract
125 member and not include invocation code.
126 """
127 dom_name = DartDomNameOfAttribute(attribute)
128 attr_name = self._renamer.RenameMember(
129 self._interface.id, attribute, dom_name, 'get:')
130 if not attr_name or self._IsPrivate(attr_name):
131 return
132
133 html_setter_name = self._renamer.RenameMember(
134 self._interface.id, attribute, dom_name, 'set:')
135 read_only = (attribute.is_read_only or 'Replaceable' in attribute.ext_attrs
136 or not html_setter_name)
137
138 # We don't yet handle inconsistent renames of the getter and setter yet.
139 assert(not html_setter_name or attr_name == html_setter_name)
140
141 if declare_only:
142 self.DeclareAttribute(attribute,
143 self.SecureOutputType(attribute.type.id), attr_name, read_only)
144 else:
145 self.EmitAttribute(attribute, attr_name, read_only)
146
147 def AddOperation(self, info, declare_only=False):
148 """ Adds an operation to the generated class.
149 Arguments:
150 info - The operation info of the operation to be added.
151 declare_only- True if the operation should be declared as an abstract
152 member and not include invocation code.
153 """
154 # FIXME: When we pass in operations[0] below, we're assuming all
155 # overloaded operations have the same security attributes. This
156 # is currently true, but we should consider filtering earlier or
157 # merging the relevant data into info itself.
158 method_name = self._renamer.RenameMember(self._interface.id,
159 info.operations[0],
160 info.name)
161 if not method_name:
162 if info.name == 'item':
163 # FIXME: item should be renamed to operator[], not removed.
164 self.EmitOperation(info, '_item')
165 return
166
167 if declare_only:
168 self.DeclareOperation(info,
169 self.SecureOutputType(info.type_name), method_name)
170 else:
171 self.EmitOperation(info, method_name)
172
26 def AdditionalImplementedInterfaces(self): 173 def AdditionalImplementedInterfaces(self):
27 # TODO: Include all implemented interfaces, including other Lists. 174 # TODO: Include all implemented interfaces, including other Lists.
28 implements = [] 175 implements = []
29 if self._interface_type_info.is_typed_array(): 176 if self._interface_type_info.is_typed_array():
30 element_type = self._interface_type_info.list_item_type() 177 element_type = self._interface_type_info.list_item_type()
31 implements.append('List<%s>' % self._DartType(element_type)) 178 implements.append('List<%s>' % self._DartType(element_type))
32 if self._interface_type_info.list_item_type(): 179 if self._interface_type_info.list_item_type():
33 item_type_info = self._type_registry.TypeInfo( 180 item_type_info = self._type_registry.TypeInfo(
34 self._interface_type_info.list_item_type()) 181 self._interface_type_info.list_item_type())
35 implements.append('List<%s>' % item_type_info.dart_type()) 182 implements.append('List<%s>' % item_type_info.dart_type())
36 return implements 183 return implements
37 184
38 def AddConstructors(self, constructors, factory_provider, class_name, 185 def AddConstructors(self, constructors, factory_provider, class_name,
39 base_class): 186 base_class):
187 """ Adds all of the constructors.
188 Arguments:
189 constructors - List of the constructors to be added.
190 factory_provider - Name of the factory provider for this class.
191 class_name - The name of this class.
192 base_class - The name of the base class which this extends.
193 """
40 for constructor_info in constructors: 194 for constructor_info in constructors:
41 self._AddConstructor(constructor_info, factory_provider) 195 self._AddConstructor(constructor_info, factory_provider)
42 196
43 typed_array_type = None 197 typed_array_type = None
44 for interface in self._database.Hierarchy(self._interface): 198 for interface in self._database.Hierarchy(self._interface):
45 type_info = self._type_registry.TypeInfo(interface.id) 199 type_info = self._type_registry.TypeInfo(interface.id)
46 if type_info.is_typed_array(): 200 if type_info.is_typed_array():
47 typed_array_type = type_info.list_item_type() 201 typed_array_type = type_info.list_item_type()
48 break 202 break
49 if typed_array_type: 203 if typed_array_type:
50 self._members_emitter.Emit( 204 self._members_emitter.Emit(
51 '\n' 205 '\n'
52 ' factory $CTOR(int length) =>\n' 206 ' factory $CTOR(int length) =>\n'
53 ' $FACTORY.create$(CTOR)(length);\n' 207 ' $FACTORY.create$(CTOR)(length);\n'
54 '\n' 208 '\n'
55 ' factory $CTOR.fromList(List<$TYPE> list) =>\n' 209 ' factory $CTOR.fromList(List<$TYPE> list) =>\n'
56 ' $FACTORY.create$(CTOR)_fromList(list);\n' 210 ' $FACTORY.create$(CTOR)_fromList(list);\n'
57 '\n' 211 '\n'
58 ' factory $CTOR.fromBuffer(ArrayBuffer buffer, [int byteOffset, int l ength]) => \n' 212 ' factory $CTOR.fromBuffer(ArrayBuffer buffer, '
213 '[int byteOffset, int length]) => \n'
59 ' $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n' , 214 ' $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n' ,
60 CTOR=self._interface.id, 215 CTOR=self._interface.id,
61 TYPE=self._DartType(typed_array_type), 216 TYPE=self._DartType(typed_array_type),
62 FACTORY=factory_provider) 217 FACTORY=factory_provider)
63 218
64 def _AddConstructor(self, constructor_info, factory_provider): 219 def _AddConstructor(self, constructor_info, factory_provider):
65 constructor_info.GenerateFactoryInvocation( 220 constructor_info.GenerateFactoryInvocation(
66 self._DartType, self._members_emitter, factory_provider) 221 self._DartType, self._members_emitter, factory_provider)
67 222
68 def DeclareAttribute(self, attribute, type_name, html_name, read_only): 223 def DeclareAttribute(self, attribute, type_name, attr_name, read_only):
69 # Declares an attribute but does not include the code to invoke it. 224 """ Declares an attribute but does not include the code to invoke it.
225 """
70 self.EmitAttributeDocumentation(attribute) 226 self.EmitAttributeDocumentation(attribute)
71 if read_only: 227 if read_only:
72 template = '\n $TYPE get $NAME;\n' 228 template = '\n $TYPE get $NAME;\n'
73 else: 229 else:
74 template = '\n $TYPE $NAME;\n' 230 template = '\n $TYPE $NAME;\n'
75 231
76 self._members_emitter.Emit(template, 232 self._members_emitter.Emit(template,
77 NAME=html_name, 233 NAME=attr_name,
78 TYPE=type_name) 234 TYPE=type_name)
79 235
80 def DeclareOperation(self, operation, type_name, html_name): 236 def DeclareOperation(self, operation, return_type_name, method_name):
81 # Declares an operation but does not include the code to invoke it. 237 """ Declares an operation but does not include the code to invoke it.
238 Arguments:
239 operation - The operation to be declared.
240 return_type_name - The name of the return type.
241 method_name - The name of the method.
242 """
82 self.EmitOperationDocumentation(operation) 243 self.EmitOperationDocumentation(operation)
83 self._members_emitter.Emit( 244 self._members_emitter.Emit(
84 '\n' 245 '\n'
85 ' $TYPE $NAME($PARAMS);\n', 246 ' $TYPE $NAME($PARAMS);\n',
86 TYPE=type_name, 247 TYPE=return_type_name,
87 NAME=html_name, 248 NAME=method_name,
88 PARAMS=operation.ParametersDeclaration(self._DartType)) 249 PARAMS=operation.ParametersDeclaration(self._DartType))
250
251 def SecureOutputType(self, type_name, is_dart_type=False):
252 """ Converts the type name to the secure type name for return types.
253 """
254 if is_dart_type:
255 dart_name = type_name
256 else:
257 dart_name = self._DartType(type_name)
258 # We only need to secure Window. Only local History and Location are
259 # returned in generated code.
260 assert(dart_name != 'History' and dart_name != 'Location')
261 if dart_name == 'LocalWindow':
262 return _secure_base_types[dart_name]
263 return dart_name
264
265 def SecureBaseName(self, type_name):
266 if type_name in _secure_base_types:
267 return _secure_base_types[type_name]
268
269 def _TransitiveSecondaryParents(self, interface):
270 """Returns a list of all non-primary parents.
271
272 The list contains the interface objects for interfaces defined in the
273 database, and the name for undefined interfaces.
274 """
275 def walk(parents):
276 for parent in parents:
277 parent_name = parent.type.id
278 if parent_name == 'EventTarget':
279 # Currently EventTarget is implemented as a mixin, not a proper
280 # super interface---ignore its members.
281 continue
282 if IsDartCollectionType(parent_name):
283 result.append(parent_name)
284 continue
285 if self._database.HasInterface(parent_name):
286 parent_interface = self._database.GetInterface(parent_name)
287 result.append(parent_interface)
288 walk(parent_interface.parents)
289
290 result = []
291 if interface.parents:
292 parent = interface.parents[0]
293 if IsPureInterface(parent.type.id):
294 walk(interface.parents)
295 else:
296 walk(interface.parents[1:])
297 return result
298
299 def _DartType(self, type_name):
300 return self._type_registry.DartType(type_name)
301
302 def _IsPrivate(self, name):
303 return name.startswith('_')
OLDNEW
« no previous file with comments | « sdk/lib/html/dartium/html_dartium.dart ('k') | sdk/lib/html/scripts/htmleventgenerator.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698