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

Side by Side Diff: mojo/public/tools/bindings/generators/mojom_dart_generator.py

Issue 814543006: Move //mojo/{public, edk} underneath //third_party (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 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
OLDNEW
(Empty)
1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """Generates dart source files from a mojom.Module."""
6
7 import re
8
9 import mojom.generate.generator as generator
10 import mojom.generate.module as mojom
11 import mojom.generate.pack as pack
12 from mojom.generate.template_expander import UseJinja
13
14 GENERATOR_PREFIX = 'dart'
15
16 _HEADER_SIZE = 8
17
18 _kind_to_dart_default_value = {
19 mojom.BOOL: "false",
20 mojom.INT8: "0",
21 mojom.UINT8: "0",
22 mojom.INT16: "0",
23 mojom.UINT16: "0",
24 mojom.INT32: "0",
25 mojom.UINT32: "0",
26 mojom.FLOAT: "0.0",
27 mojom.HANDLE: "null",
28 mojom.DCPIPE: "null",
29 mojom.DPPIPE: "null",
30 mojom.MSGPIPE: "null",
31 mojom.SHAREDBUFFER: "null",
32 mojom.NULLABLE_HANDLE: "null",
33 mojom.NULLABLE_DCPIPE: "null",
34 mojom.NULLABLE_DPPIPE: "null",
35 mojom.NULLABLE_MSGPIPE: "null",
36 mojom.NULLABLE_SHAREDBUFFER: "null",
37 mojom.INT64: "0",
38 mojom.UINT64: "0",
39 mojom.DOUBLE: "0.0",
40 mojom.STRING: "null",
41 mojom.NULLABLE_STRING: "null"
42 }
43
44 _kind_to_dart_decl_type = {
45 mojom.BOOL: "bool",
46 mojom.INT8: "int",
47 mojom.UINT8: "int",
48 mojom.INT16: "int",
49 mojom.UINT16: "int",
50 mojom.INT32: "int",
51 mojom.UINT32: "int",
52 mojom.FLOAT: "double",
53 mojom.HANDLE: "core.MojoHandle",
54 mojom.DCPIPE: "core.MojoDataPipeConsumer",
55 mojom.DPPIPE: "core.MojoDataPipeProducer",
56 mojom.MSGPIPE: "core.MojoMessagePipeEndpoint",
57 mojom.SHAREDBUFFER: "core.MojoSharedBuffer",
58 mojom.NULLABLE_HANDLE: "core.MojoHandle",
59 mojom.NULLABLE_DCPIPE: "core.MojoDataPipeConsumer",
60 mojom.NULLABLE_DPPIPE: "core.MojoDataPipeProducer",
61 mojom.NULLABLE_MSGPIPE: "core.MojoMessagePipeEndpoint",
62 mojom.NULLABLE_SHAREDBUFFER: "core.MojoSharedBuffer",
63 mojom.INT64: "int",
64 mojom.UINT64: "int",
65 mojom.DOUBLE: "double",
66 mojom.STRING: "String",
67 mojom.NULLABLE_STRING: "String"
68 }
69
70 _spec_to_decode_method = {
71 mojom.BOOL.spec: 'decodeBool',
72 mojom.DCPIPE.spec: 'decodeHandle',
73 mojom.DOUBLE.spec: 'decodeDouble',
74 mojom.DPPIPE.spec: 'decodeHandle',
75 mojom.FLOAT.spec: 'decodeFloat',
76 mojom.HANDLE.spec: 'decodeHandle',
77 mojom.INT16.spec: 'decodeInt16',
78 mojom.INT32.spec: 'decodeInt32',
79 mojom.INT64.spec: 'decodeInt64',
80 mojom.INT8.spec: 'decodeInt8',
81 mojom.MSGPIPE.spec: 'decodeMessagePipeHandle',
82 mojom.NULLABLE_DCPIPE.spec: 'decodeConsumerHandle',
83 mojom.NULLABLE_DPPIPE.spec: 'decodeProducerHandle',
84 mojom.NULLABLE_HANDLE.spec: 'decodeHandle',
85 mojom.NULLABLE_MSGPIPE.spec: 'decodeMessagePipeHandle',
86 mojom.NULLABLE_SHAREDBUFFER.spec: 'decodeSharedBufferHandle',
87 mojom.NULLABLE_STRING.spec: 'decodeString',
88 mojom.SHAREDBUFFER.spec: 'decodeSharedBufferHandle',
89 mojom.STRING.spec: 'decodeString',
90 mojom.UINT16.spec: 'decodeUint16',
91 mojom.UINT32.spec: 'decodeUint32',
92 mojom.UINT64.spec: 'decodeUint64',
93 mojom.UINT8.spec: 'decodeUint8',
94 }
95
96 _spec_to_encode_method = {
97 mojom.BOOL.spec: 'encodeBool',
98 mojom.DCPIPE.spec: 'encodeHandle',
99 mojom.DOUBLE.spec: 'encodeDouble',
100 mojom.DPPIPE.spec: 'encodeHandle',
101 mojom.FLOAT.spec: 'encodeFloat',
102 mojom.HANDLE.spec: 'encodeHandle',
103 mojom.INT16.spec: 'encodeInt16',
104 mojom.INT32.spec: 'encodeInt32',
105 mojom.INT64.spec: 'encodeInt64',
106 mojom.INT8.spec: 'encodeInt8',
107 mojom.MSGPIPE.spec: 'encodeMessagePipeHandle',
108 mojom.NULLABLE_DCPIPE.spec: 'encodeConsumerHandle',
109 mojom.NULLABLE_DPPIPE.spec: 'encodeProducerHandle',
110 mojom.NULLABLE_HANDLE.spec: 'encodeHandle',
111 mojom.NULLABLE_MSGPIPE.spec: 'encodeMessagePipeHandle',
112 mojom.NULLABLE_SHAREDBUFFER.spec: 'encodeSharedBufferHandle',
113 mojom.NULLABLE_STRING.spec: 'encodeString',
114 mojom.SHAREDBUFFER.spec: 'encodeSharedBufferHandle',
115 mojom.STRING.spec: 'encodeString',
116 mojom.UINT16.spec: 'encodeUint16',
117 mojom.UINT32.spec: 'encodeUint32',
118 mojom.UINT64.spec: 'encodeUint64',
119 mojom.UINT8.spec: 'encodeUint8',
120 }
121
122 def GetDartType(kind):
123 if kind.imported_from:
124 return kind.imported_from["unique_name"] + "." + kind.name
125 return kind.name
126
127 def DartDefaultValue(field):
128 if field.default:
129 if mojom.IsStructKind(field.kind):
130 assert field.default == "default"
131 return "new %s()" % GetDartType(field.kind)
132 return ExpressionToText(field.default)
133 if field.kind in mojom.PRIMITIVES:
134 return _kind_to_dart_default_value[field.kind]
135 if mojom.IsStructKind(field.kind):
136 return "null"
137 if mojom.IsArrayKind(field.kind):
138 return "null"
139 if mojom.IsMapKind(field.kind):
140 return "null"
141 if mojom.IsInterfaceKind(field.kind) or \
142 mojom.IsInterfaceRequestKind(field.kind):
143 return "null"
144 if mojom.IsEnumKind(field.kind):
145 return "0"
146
147 def DartDeclType(kind):
148 if kind in mojom.PRIMITIVES:
149 return _kind_to_dart_decl_type[kind]
150 if mojom.IsStructKind(kind):
151 return GetDartType(kind)
152 if mojom.IsArrayKind(kind):
153 array_type = DartDeclType(kind.kind)
154 return "List<" + array_type + ">"
155 if mojom.IsMapKind(kind):
156 key_type = DartDeclType(kind.key_kind)
157 value_type = DartDeclType(kind.value_kind)
158 return "Map<"+ key_type + ", " + value_type + ">"
159 if mojom.IsInterfaceKind(kind) or \
160 mojom.IsInterfaceRequestKind(kind):
161 return "Object"
162 if mojom.IsEnumKind(kind):
163 return "int"
164
165 def NameToComponent(name):
166 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar ->
167 # HTTP_Entry2_FooBar)
168 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name)
169 # insert '_' between non upper and start of upper blocks (e.g.,
170 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar)
171 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name)
172 return [x.lower() for x in name.split('_')]
173
174 def UpperCamelCase(name):
175 return ''.join([x.capitalize() for x in NameToComponent(name)])
176
177 def CamelCase(name):
178 uccc = UpperCamelCase(name)
179 return uccc[0].lower() + uccc[1:]
180
181 def ConstantStyle(name):
182 components = NameToComponent(name)
183 if components[0] == 'k' and len(components) > 1:
184 components = components[1:]
185 # variable cannot starts with a digit.
186 if components[0][0].isdigit():
187 components[0] = '_' + components[0]
188 return '_'.join([x.upper() for x in components])
189
190 def GetNameForElement(element):
191 if (mojom.IsEnumKind(element) or mojom.IsInterfaceKind(element) or
192 mojom.IsStructKind(element)):
193 return UpperCamelCase(element.name)
194 if mojom.IsInterfaceRequestKind(element):
195 return GetNameForElement(element.kind)
196 if isinstance(element, (mojom.Method,
197 mojom.Parameter,
198 mojom.Field)):
199 return CamelCase(element.name)
200 if isinstance(element, mojom.EnumValue):
201 return (GetNameForElement(element.enum) + '.' +
202 ConstantStyle(element.name))
203 if isinstance(element, (mojom.NamedValue,
204 mojom.Constant,
205 mojom.EnumField)):
206 return ConstantStyle(element.name)
207 raise Exception('Unexpected element: %s' % element)
208
209 def GetInterfaceResponseName(method):
210 return UpperCamelCase(method.name + 'Response')
211
212 def GetResponseStructFromMethod(method):
213 return generator.GetDataHeader(
214 False, generator.GetResponseStructFromMethod(method))
215
216 def GetStructFromMethod(method):
217 return generator.GetDataHeader(
218 False, generator.GetStructFromMethod(method))
219
220 def GetDartTrueFalse(value):
221 return 'true' if value else 'false'
222
223 def GetArrayNullabilityFlags(kind):
224 """Returns nullability flags for an array type, see codec.dart.
225
226 As we have dedicated decoding functions for arrays, we have to pass
227 nullability information about both the array itself, as well as the array
228 element type there.
229 """
230 assert mojom.IsArrayKind(kind)
231 ARRAY_NULLABLE = 'bindings.kArrayNullable'
232 ELEMENT_NULLABLE = 'bindings.kElementNullable'
233 NOTHING_NULLABLE = 'bindings.kNothingNullable'
234
235 flags_to_set = []
236 if mojom.IsNullableKind(kind):
237 flags_to_set.append(ARRAY_NULLABLE)
238 if mojom.IsNullableKind(kind.kind):
239 flags_to_set.append(ELEMENT_NULLABLE)
240
241 if not flags_to_set:
242 flags_to_set = [NOTHING_NULLABLE]
243 return ' | '.join(flags_to_set)
244
245 def AppendDecodeParams(initial_params, kind, bit):
246 """ Appends standard parameters for decode calls. """
247 params = list(initial_params)
248 if (kind == mojom.BOOL):
249 params.append(str(bit))
250 if mojom.IsReferenceKind(kind):
251 if mojom.IsArrayKind(kind):
252 params.append(GetArrayNullabilityFlags(kind))
253 else:
254 params.append(GetDartTrueFalse(mojom.IsNullableKind(kind)))
255 if mojom.IsInterfaceKind(kind):
256 params.append('%sClient.newFromEndpoint' % GetDartType(kind))
257 if mojom.IsArrayKind(kind) and mojom.IsInterfaceKind(kind.kind):
258 params.append('%sClient.newFromEndpoint' % GetDartType(kind.kind))
259 if mojom.IsInterfaceRequestKind(kind):
260 params.append('%sInterface.newFromEndpoint' % GetDartType(kind.kind))
261 if mojom.IsArrayKind(kind) and mojom.IsInterfaceRequestKind(kind.kind):
262 params.append('%sInterface.newFromEndpoint' % GetDartType(kind.kind.kind))
263 if mojom.IsArrayKind(kind):
264 params.append(GetArrayExpectedLength(kind))
265 return params
266
267 def AppendEncodeParams(initial_params, kind, bit):
268 """ Appends standard parameters shared between encode and decode calls. """
269 params = list(initial_params)
270 if (kind == mojom.BOOL):
271 params.append(str(bit))
272 if mojom.IsReferenceKind(kind):
273 if mojom.IsArrayKind(kind):
274 params.append(GetArrayNullabilityFlags(kind))
275 else:
276 params.append(GetDartTrueFalse(mojom.IsNullableKind(kind)))
277 if mojom.IsArrayKind(kind):
278 params.append(GetArrayExpectedLength(kind))
279 return params
280
281 def DecodeMethod(kind, offset, bit):
282 def _DecodeMethodName(kind):
283 if mojom.IsArrayKind(kind):
284 return _DecodeMethodName(kind.kind) + 'Array'
285 if mojom.IsEnumKind(kind):
286 return _DecodeMethodName(mojom.INT32)
287 if mojom.IsInterfaceRequestKind(kind):
288 return 'decodeInterfaceRequest'
289 if mojom.IsInterfaceKind(kind):
290 return 'decodeServiceInterface'
291 return _spec_to_decode_method[kind.spec]
292 methodName = _DecodeMethodName(kind)
293 params = AppendDecodeParams([ str(offset) ], kind, bit)
294 return '%s(%s)' % (methodName, ', '.join(params))
295
296 def EncodeMethod(kind, variable, offset, bit):
297 def _EncodeMethodName(kind):
298 if mojom.IsStructKind(kind):
299 return 'encodeStruct'
300 if mojom.IsArrayKind(kind):
301 return _EncodeMethodName(kind.kind) + 'Array'
302 if mojom.IsEnumKind(kind):
303 return _EncodeMethodName(mojom.INT32)
304 if mojom.IsInterfaceRequestKind(kind):
305 return 'encodeInterfaceRequest'
306 if mojom.IsInterfaceKind(kind):
307 return 'encodeInterface'
308 return _spec_to_encode_method[kind.spec]
309 methodName = _EncodeMethodName(kind)
310 params = AppendEncodeParams([ variable, str(offset) ], kind, bit)
311 return '%s(%s)' % (methodName, ', '.join(params))
312
313 def TranslateConstants(token):
314 if isinstance(token, (mojom.EnumValue, mojom.NamedValue)):
315 # Both variable and enum constants are constructed like:
316 # NamespaceUid.Struct.Enum_CONSTANT_NAME
317 name = ""
318 if token.imported_from:
319 name = token.imported_from["unique_name"] + "."
320 if token.parent_kind:
321 name = name + token.parent_kind.name + "."
322 if isinstance(token, mojom.EnumValue):
323 name = name + token.enum.name + "_"
324 return name + token.name
325
326 if isinstance(token, mojom.BuiltinValue):
327 if token.value == "double.INFINITY" or token.value == "float.INFINITY":
328 return "double.INFINITY";
329 if token.value == "double.NEGATIVE_INFINITY" or \
330 token.value == "float.NEGATIVE_INFINITY":
331 return "double.NEGATIVE_INFINITY";
332 if token.value == "double.NAN" or token.value == "float.NAN":
333 return "double.NAN";
334
335 # Strip leading '+'.
336 if token[0] == '+':
337 token = token[1:]
338
339 return token
340
341 def ExpressionToText(value):
342 return TranslateConstants(value)
343
344 def GetArrayKind(kind, size = None):
345 if size is None:
346 return mojom.Array(kind)
347 else:
348 array = mojom.Array(kind, 0)
349 array.dart_map_size = size
350 return array
351
352 def GetArrayExpectedLength(kind):
353 if mojom.IsArrayKind(kind) and kind.length is not None:
354 return getattr(kind, 'dart_map_size', str(kind.length))
355 else:
356 return 'bindings.kUnspecifiedArrayLength'
357
358 def IsPointerArrayKind(kind):
359 if not mojom.IsArrayKind(kind):
360 return False
361 sub_kind = kind.kind
362 return mojom.IsObjectKind(sub_kind)
363
364 class Generator(generator.Generator):
365
366 dart_filters = {
367 'array_expected_length': GetArrayExpectedLength,
368 'array': GetArrayKind,
369 'decode_method': DecodeMethod,
370 'default_value': DartDefaultValue,
371 'encode_method': EncodeMethod,
372 'expression_to_text': ExpressionToText,
373 'is_handle': mojom.IsNonInterfaceHandleKind,
374 'is_map_kind': mojom.IsMapKind,
375 'is_nullable_kind': mojom.IsNullableKind,
376 'is_pointer_array_kind': IsPointerArrayKind,
377 'is_struct_kind': mojom.IsStructKind,
378 'dart_true_false': GetDartTrueFalse,
379 'dart_type': DartDeclType,
380 'name': GetNameForElement,
381 'interface_response_name': GetInterfaceResponseName,
382 'response_struct_from_method': GetResponseStructFromMethod,
383 'struct_from_method': GetStructFromMethod,
384 'upper_camel_case': UpperCamelCase,
385 'struct_size': lambda ps: ps.GetTotalSize() + _HEADER_SIZE,
386 }
387
388 def GetParameters(self):
389 return {
390 "namespace": self.module.namespace,
391 "imports": self.GetImports(),
392 "kinds": self.module.kinds,
393 "enums": self.module.enums,
394 "module": self.module,
395 "structs": self.GetStructs() + self.GetStructsFromMethods(),
396 "interfaces": self.module.interfaces,
397 "imported_interfaces": self.GetImportedInterfaces(),
398 "imported_from": self.ImportedFrom(),
399 }
400
401 @UseJinja("dart_templates/module.lib.tmpl", filters=dart_filters)
402 def GenerateLibModule(self):
403 return self.GetParameters()
404
405 def GenerateFiles(self, args):
406 self.Write(self.GenerateLibModule(),
407 self.MatchMojomFilePath("%s.dart" % self.module.name))
408
409 def GetImports(self):
410 used_names = set()
411 for each_import in self.module.imports:
412 simple_name = each_import["module_name"].split(".")[0]
413
414 # Since each import is assigned a library in Dart, they need to have
415 # unique names.
416 unique_name = simple_name
417 counter = 0
418 while unique_name in used_names:
419 counter += 1
420 unique_name = simple_name + str(counter)
421
422 used_names.add(unique_name)
423 each_import["unique_name"] = unique_name
424 counter += 1
425 return self.module.imports
426
427 def GetImportedInterfaces(self):
428 interface_to_import = {}
429 for each_import in self.module.imports:
430 for each_interface in each_import["module"].interfaces:
431 name = each_interface.name
432 interface_to_import[name] = each_import["unique_name"] + "." + name
433 return interface_to_import
434
435 def ImportedFrom(self):
436 interface_to_import = {}
437 for each_import in self.module.imports:
438 for each_interface in each_import["module"].interfaces:
439 name = each_interface.name
440 interface_to_import[name] = each_import["unique_name"] + "."
441 return interface_to_import
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698