Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
dartgenerator.py
Go to the documentation of this file.
1#!/usr/bin/env python3
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"""This module generates Dart APIs from the IDL database."""
6
7import emitter
8import idlnode
9import logging
10import os
11import re
12import shutil
13from generator import *
14from idlnode import IDLType, IDLInterface, resolveTypedef
15
16_logger = logging.getLogger('dartgenerator')
17
18
19def MergeNodes(node, other):
20 node.operations.extend(other.operations)
21 for attribute in other.attributes:
22 if not node.has_attribute(attribute):
23 node.attributes.append(attribute)
24
25 node.constants.extend(other.constants)
26
27
28class DartGenerator(object):
29 """Utilities to generate Dart APIs and corresponding JavaScript."""
30
31 def __init__(self, logging_level=logging.WARNING):
33 self._dart_templates_re = re.compile(r'[\w.:]+<([\w \.<>:]+)>')
34 _logger.setLevel(logging_level)
35
36 def _StripModules(self, type_name):
37 return type_name.split('::')[-1]
38
39 def _IsCompoundType(self, database, type_name):
40 if IsRegisteredType(type_name):
41 return True
42
43 # References a typedef - normally a union type.
44 if database.HasTypeDef(type_name):
45 return True
46
47 if type_name.endswith('?'):
48 return self._IsCompoundType(database, type_name[:-len('?')])
49
50 if type_name.endswith('[]'):
51 return self._IsCompoundType(database, type_name[:-len('[]')])
52
53 stripped_type_name = self._StripModules(type_name)
54 if (database.HasInterface(stripped_type_name) or
55 database.HasDictionary(stripped_type_name)):
56 return True
57
58 if database.HasEnum(stripped_type_name):
59 return True
60
61 dart_template_match = self._dart_templates_re.match(type_name)
62 if dart_template_match:
63 # Dart templates
64 parent_type_name = type_name[0:dart_template_match.start(1) - 1]
65 sub_type_name = dart_template_match.group(1)
66 return (self._IsCompoundType(database, parent_type_name) and
67 self._IsCompoundType(database, sub_type_name))
68 return False
69
70 def _IsDartType(self, type_name):
71 return '.' in type_name
72
73 def LoadAuxiliary(self, auxiliary_dir):
74
75 for (dirname, _, names) in os.walk(auxiliary_dir):
76 for name in names:
77 if name.endswith('.dart'):
78 name = name[0:-5] # strip off ".dart"
79 self._auxiliary_files[name] = os.path.join(dirname, name)
80
82 """Removes unidentified types.
83
84 Removes constants, attributes, operations and parents with unidentified
85 types.
86 """
87
88 for interface in database.GetInterfaces():
89
90 def IsIdentified(idl_node):
91 node_name = idl_node.id if idl_node.id else 'parent'
92 for idl_type in idl_node.all(idlnode.IDLType):
93 type_name = idl_type.id
94 if (type_name is not None and
95 self._IsCompoundType(database, type_name)):
96 continue
97 # Ignore constructor warnings.
98 if not (interface.id in [
99 'Window', 'WorkerContext', 'WorkerGlobalScope'
100 ] and type_name.endswith('Constructor')):
101 _logger.warn(
102 'removing %s in %s which has unidentified type %s' %
103 (node_name, interface.id, type_name))
104 return False
105 return True
106
107 interface.constants = list(filter(IsIdentified,
108 interface.constants))
109 interface.attributes = list(
110 filter(IsIdentified, interface.attributes))
111 interface.operations = list(
112 filter(IsIdentified, interface.operations))
113 interface.parents = list(filter(IsIdentified, interface.parents))
114
116 database,
117 and_annotations=[],
118 or_annotations=[],
119 exclude_displaced=[],
120 exclude_suppressed=[]):
121 """Filters a database to remove interfaces and members that are missing
122 annotations.
123
124 The FremontCut IDLs use annotations to specify implementation
125 status in various platforms. For example, if a member is annotated
126 with @WebKit, this means that the member is supported by WebKit.
127
128 Args:
129 database -- the database to filter
130 all_annotations -- a list of annotation names a member has to
131 have or it will be filtered.
132 or_annotations -- if a member has one of these annotations, it
133 won't be filtered even if it is missing some of the
134 all_annotations.
135 exclude_displaced -- if a member has this annotation and it
136 is marked as displaced it will always be filtered.
137 exclude_suppressed -- if a member has this annotation and it
138 is marked as suppressed it will always be filtered.
139 """
140
141 # Filter interfaces and members whose annotations don't match.
142 for interface in database.GetInterfaces():
143
144 def HasAnnotations(idl_node):
145 """Utility for determining if an IDLNode has all
146 the required annotations"""
147 for a in exclude_displaced:
148 if (a in idl_node.annotations and
149 'via' in idl_node.annotations[a]):
150 return False
151 for a in exclude_suppressed:
152 if (a in idl_node.annotations and
153 'suppressed' in idl_node.annotations[a]):
154 return False
155 for a in or_annotations:
156 if a in idl_node.annotations:
157 return True
158 if and_annotations == []:
159 return False
160 for a in and_annotations:
161 if a not in idl_node.annotations:
162 return False
163 return True
164
165 if HasAnnotations(interface):
166 interface.constants = filter(HasAnnotations,
167 interface.constants)
168 interface.attributes = filter(HasAnnotations,
169 interface.attributes)
170 interface.operations = filter(HasAnnotations,
171 interface.operations)
172 interface.parents = filter(HasAnnotations, interface.parents)
173 else:
174 database.DeleteInterface(interface.id)
175
177
178 def Generate(self, database, super_database, generate_interface):
179 self._database = database
180
181 # Collect interfaces
182 interfaces = []
183 for interface in database.GetInterfaces():
184 if not MatchSourceFilter(interface):
185 # Skip this interface since it's not present in the required source
186 _logger.info('Omitting interface - %s' % interface.id)
187 continue
188 interfaces.append(interface)
189
190 # All web_gl constants from WebGLRenderingContextBase, WebGL2RenderingContextBase, WebGLDrawBuffers are generated
191 # in a synthesized class WebGL. Those IDLConstants are in web_gl_constants.
192 web_gl_constants = []
193
194 # Render all interfaces into Dart and save them in files.
195 for interface in self._PreOrderInterfaces(interfaces):
196 interface_name = interface.id
197 auxiliary_file = self._auxiliary_files.get(interface_name)
198 if auxiliary_file is not None:
199 _logger.info('Skipping %s because %s exists' % (interface_name,
200 auxiliary_file))
201 continue
202
203 _logger.info('Generating %s' % interface.id)
204 generate_interface(interface, gl_constants=web_gl_constants)
205
206 # Generate the WEB_GL constants
207 web_gl_constants_interface = IDLInterface(None, "WebGL")
208 web_gl_constants_interface.constants = web_gl_constants
209 self._database._all_interfaces['WebGL'] = web_gl_constants_interface
210 generate_interface(web_gl_constants_interface)
211
212 def _PreOrderInterfaces(self, interfaces):
213 """Returns the interfaces in pre-order, i.e. parents first."""
214 seen = set()
215 ordered = []
216
217 def visit(interface):
218 if interface.id in seen:
219 return
220 seen.add(interface.id)
221 for parent in interface.parents:
222 if IsDartCollectionType(parent.type.id):
223 continue
224 if self._database.HasInterface(parent.type.id):
225 parent_interface = self._database.GetInterface(
226 parent.type.id)
227 visit(parent_interface)
228 ordered.append(interface)
229
230 for interface in interfaces:
231 visit(interface)
232 return ordered
233
234 def IsEventTarget(self, database, interface):
235 if interface.id == 'EventTarget':
236 return True
237 for parent in interface.parents:
238 parent_name = parent.type.id
239 if database.HasInterface(parent_name):
240 parent_interface = database.GetInterface(parent.type.id)
241 if self.IsEventTarget(database, parent_interface):
242 return True
243 return False
244
245 def FixEventTargets(self, database):
246 for interface in database.GetInterfaces():
247 if self.IsEventTarget(database, interface):
248 # Add as an attribute for easy querying in generation code.
249 interface.ext_attrs['EventTarget'] = None
250 elif 'EventTarget' in interface.ext_attrs:
251 # Create fake EventTarget parent interface for interfaces that have
252 # 'EventTarget' extended attribute.
253 ast = [('Annotation', [('Id', 'WebKit')]),
254 ('InterfaceType', ('ScopedName', 'EventTarget'))]
255 interface.parents.append(idlnode.IDLParentInterface(ast))
256
257 def AddMissingArguments(self, database):
258 ARG = idlnode.IDLArgument([('Type', ('ScopedName', 'object')),
259 ('Id', 'arg')])
260 for interface in database.GetInterfaces():
261 for operation in interface.operations:
262 call_with = operation.ext_attrs.get('CallWith', [])
263 if not (isinstance(call_with, list)):
264 call_with = [call_with]
265 constructor_with = operation.ext_attrs.get(
266 'ConstructorCallWith', [])
267 if not (isinstance(constructor_with, list)):
268 constructor_with = [constructor_with]
269 call_with = call_with + constructor_with
270
271 if 'ScriptArguments' in call_with:
272 operation.arguments.append(ARG)
273
274 def CleanupOperationArguments(self, database):
275 for interface in database.GetInterfaces():
276 for operation in interface.operations:
277 # TODO(terry): Hack to remove 3rd arguments in setInterval/setTimeout.
278 if ((operation.id == 'setInterval' or operation.id == 'setTimeout') and \
279 operation.arguments[0].type.id == 'any'):
280 operation.arguments.pop(2)
281
282 # Massage any operation argument type that is IDLEnum to String.
283 for index, argument in enumerate(operation.arguments):
284 type_name = argument.type.id
285 if database.HasEnum(type_name):
286 operation.arguments[index].type = IDLType('DOMString')
static bool match(const char *needle, const char *haystack)
Definition DM.cpp:1132
Generate(self, database, super_database, generate_interface)
FilterInterfaces(self, database, and_annotations=[], or_annotations=[], exclude_displaced=[], exclude_suppressed=[])
FilterMembersWithUnidentifiedTypes(self, database)
_IsCompoundType(self, database, type_name)
IsEventTarget(self, database, interface)
__init__(self, logging_level=logging.WARNING)
MergeNodes(node, other)