OLD | NEW |
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 import emitter | 9 import emitter |
10 from generator import AnalyzeOperation, ConstantOutputOrder, \ | 10 from generator import AnalyzeOperation, ConstantOutputOrder, \ |
11 DartDomNameOfAttribute, FindMatchingAttribute, IsDartCollectionType, \ | 11 DartDomNameOfAttribute, FindMatchingAttribute, IsDartCollectionType, \ |
12 IsPureInterface, TypeOrNothing, ConvertToFuture, GetCallbackInfo | 12 IsPureInterface, TypeOrNothing, ConvertToFuture, GetCallbackInfo |
13 from copy import deepcopy | 13 from htmlrenamer import convert_to_future_members |
14 from htmlrenamer import convert_to_future_members, keep_overloaded_members, \ | |
15 private_html_members, renamed_html_members, renamed_overloads, \ | |
16 removed_html_members | |
17 import logging | |
18 import monitored | |
19 import sys | |
20 | |
21 _logger = logging.getLogger('htmldartgenerator') | |
22 | 14 |
23 # Types that are accessible cross-frame in a limited fashion. | 15 # Types that are accessible cross-frame in a limited fashion. |
24 # In these cases, the base type (e.g., WindowBase) provides restricted access | 16 # In these cases, the base type (e.g., WindowBase) provides restricted access |
25 # while the subtype (e.g., Window) provides full access to the | 17 # while the subtype (e.g., Window) provides full access to the |
26 # corresponding objects if there are from the same frame. | 18 # corresponding objects if there are from the same frame. |
27 _secure_base_types = { | 19 _secure_base_types = { |
28 'Window': 'WindowBase', | 20 'Window': 'WindowBase', |
29 'Location': 'LocationBase', | 21 'Location': 'LocationBase', |
30 'History': 'HistoryBase', | 22 'History': 'HistoryBase', |
31 } | 23 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 else: | 76 else: |
85 for parent in self._database.Hierarchy(self._interface): | 77 for parent in self._database.Hierarchy(self._interface): |
86 if parent == self._interface: | 78 if parent == self._interface: |
87 continue | 79 continue |
88 parent_type_info = self._type_registry.TypeInfo(parent.id) | 80 parent_type_info = self._type_registry.TypeInfo(parent.id) |
89 if parent_type_info.list_item_type(): | 81 if parent_type_info.list_item_type(): |
90 self.AmendIndexer(parent_type_info.list_item_type()) | 82 self.AmendIndexer(parent_type_info.list_item_type()) |
91 break | 83 break |
92 | 84 |
93 # Group overloaded operations by name. | 85 # Group overloaded operations by name. |
94 self._AddRenamedOverloads(interface) | |
95 operationsByName = self._OperationsByName(interface) | 86 operationsByName = self._OperationsByName(interface) |
96 | 87 |
97 # Generate operations. | 88 # Generate operations. |
98 for id in sorted(operationsByName.keys()): | 89 for id in sorted(operationsByName.keys()): |
99 operations = operationsByName[id] | 90 operations = operationsByName[id] |
100 info = AnalyzeOperation(interface, operations) | 91 info = AnalyzeOperation(interface, operations) |
101 self.AddOperation(info, declare_only) | 92 self.AddOperation(info, declare_only) |
102 if ('%s.%s' % (interface.id, info.declared_name) in | 93 if ('%s.%s' % (interface.id, info.declared_name) in |
103 convert_to_future_members): | 94 convert_to_future_members): |
104 self.AddOperation(ConvertToFuture(info), declare_only) | 95 self.AddOperation(ConvertToFuture(info), declare_only) |
(...skipping 16 matching lines...) Expand all Loading... |
121 operationsByName =self._OperationsByName(parent_interface) | 112 operationsByName =self._OperationsByName(parent_interface) |
122 | 113 |
123 # Generate operations. | 114 # Generate operations. |
124 for id in sorted(operationsByName.keys()): | 115 for id in sorted(operationsByName.keys()): |
125 if not any(op.id == id for op in interface.operations): | 116 if not any(op.id == id for op in interface.operations): |
126 operations = operationsByName[id] | 117 operations = operationsByName[id] |
127 info = AnalyzeOperation(interface, operations) | 118 info = AnalyzeOperation(interface, operations) |
128 self.SecondaryContext(parent_interface) | 119 self.SecondaryContext(parent_interface) |
129 self.AddOperation(info) | 120 self.AddOperation(info) |
130 | 121 |
131 def _AddRenamedOverloads(self, interface): | |
132 """The IDL has a number of functions with the same name but that accept | |
133 different types. This is fine for JavaScript, but results in vague type | |
134 signatures for Dart. We rename some of these (by adding a new identical | |
135 operation with a different DartName), and leave the original version in a | |
136 few specific instances.""" | |
137 potential_added_operations = set() | |
138 operations_by_name = self._OperationsByName(interface) | |
139 already_renamed = [operation.ext_attrs['DartName'] if 'DartName' in | |
140 operation.ext_attrs else '' for operation in interface.operations] | |
141 | |
142 for operation in interface.operations: | |
143 full_operation_str = self._GetStringRepresentation(interface, operation) | |
144 if (full_operation_str in renamed_overloads and | |
145 renamed_overloads[full_operation_str] not in already_renamed): | |
146 operation.ext_attrs['DartName'] = renamed_overloads[ | |
147 full_operation_str] | |
148 potential_added_operations.add(operation.id) | |
149 self._EnsureNoMultipleTypeSignatures(interface, operation, | |
150 operations_by_name) | |
151 self._AddDesiredOverloadedOperations(potential_added_operations, interface, | |
152 operations_by_name) | |
153 | |
154 def _AddDesiredOverloadedOperations(self, potential_added_operations, | |
155 interface, original_operations_by_name): | |
156 """For some cases we desire to keep the overloaded version in dart, for | |
157 simplicity of API, and explain the parameters accepted in documentation.""" | |
158 updated_operations_by_name = self._OperationsByName(interface) | |
159 for operation_id in potential_added_operations: | |
160 if (operation_id not in updated_operations_by_name and | |
161 '%s.%s' % (interface.id, operation_id) in keep_overloaded_members): | |
162 for operation in original_operations_by_name[operation_id]: | |
163 cloned_operation = deepcopy(operation) | |
164 cloned_operation.ext_attrs['DartName'] = operation_id | |
165 interface.operations.append(cloned_operation) | |
166 | |
167 def _EnsureNoMultipleTypeSignatures(self, interface, operation, | |
168 operations_by_name): | |
169 """Make sure that there is now at most one operation with a particular | |
170 operation.id. If not, stop library generation, and throw an error, requiring | |
171 programmer input about the best name change before proceeding.""" | |
172 operation_str = '%s.%s' % (interface.id, operation.id) | |
173 if (operation.id in operations_by_name and | |
174 len(operations_by_name[operation.id]) > 1 and | |
175 len(filter(lambda overload: overload.startswith(operation_str), | |
176 renamed_overloads.keys())) == 0 and | |
177 operation_str not in keep_overloaded_members and | |
178 operation_str not in renamed_html_members and | |
179 operation_str not in private_html_members and | |
180 operation_str not in removed_html_members and | |
181 operation.id != '__getter__' and | |
182 operation.id != '__setter__' and | |
183 operation.id != '__delete__'): | |
184 _logger.error('Multiple type signatures for %s.%s' % ( | |
185 interface.id, operation.id)) | |
186 raise Exception('Rename one of the methods in renamed_overloads or add it' | |
187 ' to keep_overloaded_members.\n' | |
188 'Generation UNsuccessful.') | |
189 | |
190 def _GetStringRepresentation(self, interface, operation): | |
191 """Given an IDLOperation, return a object-independent representation of the | |
192 operations's signature.""" | |
193 return '%s.%s(%s)' % (interface.id, operation.id, ', '.join( | |
194 ['%s %s' % (arg.type.id, arg.id) for arg in operation.arguments])) | |
195 | |
196 def _OperationsByName(self, interface): | 122 def _OperationsByName(self, interface): |
197 operationsByName = {} | 123 operationsByName = {} |
198 for operation in interface.operations: | 124 for operation in interface.operations: |
199 name = operation.ext_attrs.get('DartName', operation.id) | 125 name = operation.ext_attrs.get('DartName', operation.id) |
200 operationsByName.setdefault(name, []).append(operation) | 126 operationsByName.setdefault(name, []).append(operation) |
201 return operationsByName | 127 return operationsByName |
202 | 128 |
203 def AddConstant(self, constant): | 129 def AddConstant(self, constant): |
204 const_name = self._renamer.RenameMember( | 130 const_name = self._renamer.RenameMember( |
205 self._interface.id, constant, constant.id, 'get:', dartify_name=False) | 131 self._interface.id, constant, constant.id, 'get:', dartify_name=False) |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 if interface.parents: | 593 if interface.parents: |
668 parent = interface.parents[0] | 594 parent = interface.parents[0] |
669 if IsPureInterface(parent.type.id): | 595 if IsPureInterface(parent.type.id): |
670 walk(interface.parents) | 596 walk(interface.parents) |
671 else: | 597 else: |
672 walk(interface.parents[1:]) | 598 walk(interface.parents[1:]) |
673 return result | 599 return result |
674 | 600 |
675 def _DartType(self, type_name): | 601 def _DartType(self, type_name): |
676 return self._type_registry.DartType(type_name) | 602 return self._type_registry.DartType(type_name) |
OLD | NEW |