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

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

Issue 1433183002: Generate Mojom Types for Dart (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Removed assert that breaks dart unit test Created 5 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
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Generates dart source files from a mojom.Module.""" 5 """Generates dart source files from a mojom.Module."""
6 6
7 import os 7 import os
8 import re 8 import re
9 import shutil 9 import shutil
10 import sys 10 import sys
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 mojom.NULLABLE_DPPIPE: "core.MojoDataPipeProducer", 63 mojom.NULLABLE_DPPIPE: "core.MojoDataPipeProducer",
64 mojom.NULLABLE_MSGPIPE: "core.MojoMessagePipeEndpoint", 64 mojom.NULLABLE_MSGPIPE: "core.MojoMessagePipeEndpoint",
65 mojom.NULLABLE_SHAREDBUFFER: "core.MojoSharedBuffer", 65 mojom.NULLABLE_SHAREDBUFFER: "core.MojoSharedBuffer",
66 mojom.INT64: "int", 66 mojom.INT64: "int",
67 mojom.UINT64: "int", 67 mojom.UINT64: "int",
68 mojom.DOUBLE: "double", 68 mojom.DOUBLE: "double",
69 mojom.STRING: "String", 69 mojom.STRING: "String",
70 mojom.NULLABLE_STRING: "String" 70 mojom.NULLABLE_STRING: "String"
71 } 71 }
72 72
73 _kind_to_mojom_type = {
74 mojom.BOOL: "BOOL",
75 mojom.INT8: "INT8",
76 mojom.UINT8: "UINT8",
77 mojom.INT16: "INT16",
78 mojom.UINT16: "UINT16",
79 mojom.INT32: "INT32",
80 mojom.UINT32: "UINT32",
81 mojom.FLOAT: "FLOAT",
82 mojom.HANDLE: "UNSPECIFIED",
83 mojom.DCPIPE: "DATA_PIPE_CONSUMER",
84 mojom.DPPIPE: "DATA_PIPE_PRODUCER",
85 mojom.MSGPIPE: "MESSAGE_PIPE",
86 mojom.SHAREDBUFFER: "SHARED_BUFFER",
87 mojom.NULLABLE_HANDLE: "UNSPECIFIED",
88 mojom.NULLABLE_DCPIPE: "DATA_PIPE_CONSUMER",
89 mojom.NULLABLE_DPPIPE: "DATA_PIPE_PRODUCER",
90 mojom.NULLABLE_MSGPIPE: "MESSAGE_PIPE",
91 mojom.NULLABLE_SHAREDBUFFER: "SHARED_BUFFER",
92 mojom.INT64: "INT64",
93 mojom.UINT64: "UINT64",
94 mojom.DOUBLE: "DOUBLE",
95 mojom.STRING: "STRING",
96 mojom.NULLABLE_STRING: "STRING"
97 }
98
73 _spec_to_decode_method = { 99 _spec_to_decode_method = {
74 mojom.BOOL.spec: 'decodeBool', 100 mojom.BOOL.spec: 'decodeBool',
75 mojom.DCPIPE.spec: 'decodeConsumerHandle', 101 mojom.DCPIPE.spec: 'decodeConsumerHandle',
76 mojom.DOUBLE.spec: 'decodeDouble', 102 mojom.DOUBLE.spec: 'decodeDouble',
77 mojom.DPPIPE.spec: 'decodeProducerHandle', 103 mojom.DPPIPE.spec: 'decodeProducerHandle',
78 mojom.FLOAT.spec: 'decodeFloat', 104 mojom.FLOAT.spec: 'decodeFloat',
79 mojom.HANDLE.spec: 'decodeHandle', 105 mojom.HANDLE.spec: 'decodeHandle',
80 mojom.INT16.spec: 'decodeInt16', 106 mojom.INT16.spec: 'decodeInt16',
81 mojom.INT32.spec: 'decodeInt32', 107 mojom.INT32.spec: 'decodeInt32',
82 mojom.INT64.spec: 'decodeInt64', 108 mojom.INT64.spec: 'decodeInt64',
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 mojom.NULLABLE_SHAREDBUFFER.spec: 'encodeSharedBufferHandle', 141 mojom.NULLABLE_SHAREDBUFFER.spec: 'encodeSharedBufferHandle',
116 mojom.NULLABLE_STRING.spec: 'encodeString', 142 mojom.NULLABLE_STRING.spec: 'encodeString',
117 mojom.SHAREDBUFFER.spec: 'encodeSharedBufferHandle', 143 mojom.SHAREDBUFFER.spec: 'encodeSharedBufferHandle',
118 mojom.STRING.spec: 'encodeString', 144 mojom.STRING.spec: 'encodeString',
119 mojom.UINT16.spec: 'encodeUint16', 145 mojom.UINT16.spec: 'encodeUint16',
120 mojom.UINT32.spec: 'encodeUint32', 146 mojom.UINT32.spec: 'encodeUint32',
121 mojom.UINT64.spec: 'encodeUint64', 147 mojom.UINT64.spec: 'encodeUint64',
122 mojom.UINT8.spec: 'encodeUint8', 148 mojom.UINT8.spec: 'encodeUint8',
123 } 149 }
124 150
151 # The mojom_types.mojom and service_describer.mojom files are special because
152 # they are used to generate mojom Type's and ServiceDescription implementations.
153 _service_describer_pkg_short = "service_describer"
154 _service_describer_pkg = "package:mojo/mojo/%s.mojom.dart" % \
155 _service_describer_pkg_short
156 _mojom_types_pkg_short = "mojom_types"
157 _mojom_types_pkg = "package:mojo/mojo/%s.mojom.dart" % \
158 _mojom_types_pkg_short
159
125 def GetDartType(kind): 160 def GetDartType(kind):
126 if kind.imported_from: 161 if kind.imported_from:
127 return kind.imported_from["unique_name"] + "." + GetNameForElement(kind) 162 return kind.imported_from["unique_name"] + "." + GetNameForElement(kind)
128 return GetNameForElement(kind) 163 return GetNameForElement(kind)
129 164
130 def DartDefaultValue(field): 165 def DartDefaultValue(field):
131 if field.default: 166 if field.default:
132 if mojom.IsStructKind(field.kind): 167 if mojom.IsStructKind(field.kind):
133 assert field.default == "default" 168 assert field.default == "default"
134 return "new %s()" % GetDartType(field.kind) 169 return "new %s()" % GetDartType(field.kind)
(...skipping 30 matching lines...) Expand all
165 if mojom.IsMapKind(kind): 200 if mojom.IsMapKind(kind):
166 key_type = DartDeclType(kind.key_kind) 201 key_type = DartDeclType(kind.key_kind)
167 value_type = DartDeclType(kind.value_kind) 202 value_type = DartDeclType(kind.value_kind)
168 return "Map<"+ key_type + ", " + value_type + ">" 203 return "Map<"+ key_type + ", " + value_type + ">"
169 if mojom.IsInterfaceKind(kind) or \ 204 if mojom.IsInterfaceKind(kind) or \
170 mojom.IsInterfaceRequestKind(kind): 205 mojom.IsInterfaceRequestKind(kind):
171 return "Object" 206 return "Object"
172 if mojom.IsEnumKind(kind): 207 if mojom.IsEnumKind(kind):
173 return GetDartType(kind) 208 return GetDartType(kind)
174 209
210 def GetMojomTypeValue(kind, typepkg=''):
211 if not kind in _kind_to_mojom_type:
212 return ''
213
214 nullable = 'true' if mojom.IsNullableKind(kind) else 'false'
215 w = _kind_to_mojom_type[kind]
216 if kind == mojom.BOOL or kind == mojom.FLOAT or kind == mojom.DOUBLE or \
217 mojom.IsIntegralKind(kind):
218
219 return 'new %sType()..simpleType = %sSimpleType.%s' % (typepkg, typepkg, w)
220 elif mojom.IsAnyHandleKind(kind):
221 return ('new %sType()\n..handleType = (new %sHandleType()' +
222 '\n..kind = %sHandleTypeKind.%s' +
223 '\n..nullable = %s)') % \
224 (typepkg, typepkg, typepkg, w, nullable)
225 elif mojom.IsStringKind(kind):
226 return 'new %sType()\n..stringType = (new %sStringType()..nullable = %s)' \
227 % (typepkg, typepkg, nullable)
228 else:
229 raise Exception('Missing case for kind: %s' % kind)
230
175 def NameToComponent(name): 231 def NameToComponent(name):
176 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar -> 232 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar ->
177 # HTTP_Entry2_FooBar) 233 # HTTP_Entry2_FooBar)
178 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name) 234 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name)
179 # insert '_' between non upper and start of upper blocks (e.g., 235 # insert '_' between non upper and start of upper blocks (e.g.,
180 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar) 236 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar)
181 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name) 237 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name)
182 return [x.lower() for x in name.split('_')] 238 return [x.lower() for x in name.split('_')]
183 239
184 def UpperCamelCase(name): 240 def UpperCamelCase(name):
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 431
376 def IsPointerArrayKind(kind): 432 def IsPointerArrayKind(kind):
377 if not mojom.IsArrayKind(kind): 433 if not mojom.IsArrayKind(kind):
378 return False 434 return False
379 sub_kind = kind.kind 435 sub_kind = kind.kind
380 return mojom.IsObjectKind(sub_kind) 436 return mojom.IsObjectKind(sub_kind)
381 437
382 def IsEnumArrayKind(kind): 438 def IsEnumArrayKind(kind):
383 return mojom.IsArrayKind(kind) and mojom.IsEnumKind(kind.kind) 439 return mojom.IsArrayKind(kind) and mojom.IsEnumKind(kind.kind)
384 440
441 def IsImportedKind(kind):
442 return hasattr(kind, 'imported_from') and kind.imported_from is not None
443
385 def ParseStringAttribute(attribute): 444 def ParseStringAttribute(attribute):
386 assert isinstance(attribute, basestring) 445 assert isinstance(attribute, basestring)
387 return attribute 446 return attribute
388 447
389 def GetPackage(module): 448 def GetPackage(module):
390 if module.attributes and 'DartPackage' in module.attributes: 449 if module.attributes and 'DartPackage' in module.attributes:
391 return ParseStringAttribute(module.attributes['DartPackage']) 450 return ParseStringAttribute(module.attributes['DartPackage'])
392 # Default package. 451 # Default package.
393 return 'mojom' 452 return 'mojom'
394 453
454 def GetPackageName(module):
455 return module.name.split('.')[0]
456
395 def GetImportUri(module): 457 def GetImportUri(module):
396 package = GetPackage(module); 458 package = GetPackage(module);
397 elements = module.namespace.split('.') 459 elements = module.namespace.split('.')
398 elements.append("%s" % module.name) 460 elements.append("%s" % module.name)
399 return os.path.join(package, *elements) 461 return os.path.join(package, *elements)
400 462
463 identifier_cache = {}
464 def GetIdentifier(kind):
465 # Use the kind's module to determine the package name.
466 if hasattr(kind, 'module'):
467 package = GetPackageName(kind.module)
468 elif mojom.IsInterfaceRequestKind(kind):
469 package = GetPackageName(kind.kind.module)
470 else:
471 return ''
472
473 # Most kinds have a name, but those that don't should rely on their spec.
474 # Since spec can have : and ? characters, these must be replaced. Since ? is
475 # replaced with '', the caller must keep track of optionality on its own.
476 name_or_spec = (kind.name if hasattr(kind, 'name') else kind.spec)
477 package_unique = name_or_spec.replace(':', '_').replace('?', '')
478 return '%s_%s' % (package, package_unique)
479
480 def StoreIdentifier(identifier, cache_name):
481 if not cache_name in identifier_cache:
482 identifier_cache[cache_name] = {}
483 identifier_cache[cache_name][identifier] = True
484 return ''
485
486 def CheckIdentifier(identifier, cache_name):
487 if not cache_name in identifier_cache:
488 identifier_cache[cache_name] = {}
489 return identifier in identifier_cache[cache_name]
490
491 # Get the mojom type's identifier suffix.
492 def GetMojomTypeIdentifier(kind):
493 # Since this should be unique, it is based on the type's identifier.
494 return "_%s__" % GetIdentifier(kind)
495
401 class Generator(generator.Generator): 496 class Generator(generator.Generator):
402 497
403 dart_filters = { 498 dart_filters = {
404 'array_expected_length': GetArrayExpectedLength, 499 'array_expected_length': GetArrayExpectedLength,
405 'array': GetArrayKind, 500 'array': GetArrayKind,
406 'decode_method': DecodeMethod, 501 'decode_method': DecodeMethod,
407 'default_value': DartDefaultValue, 502 'default_value': DartDefaultValue,
408 'encode_method': EncodeMethod, 503 'encode_method': EncodeMethod,
409 'expression_to_text': ExpressionToText, 504 'expression_to_text': ExpressionToText,
505 'identifier': GetIdentifier,
506 'identifier_check': CheckIdentifier,
507 'identifier_store': StoreIdentifier,
508 'mojom_type_value': GetMojomTypeValue,
509 'mojom_type_identifier': GetMojomTypeIdentifier,
510 'is_imported_kind': IsImportedKind,
511 'is_array_kind': mojom.IsArrayKind,
410 'is_map_kind': mojom.IsMapKind, 512 'is_map_kind': mojom.IsMapKind,
411 'is_nullable_kind': mojom.IsNullableKind, 513 'is_nullable_kind': mojom.IsNullableKind,
412 'is_pointer_array_kind': IsPointerArrayKind, 514 'is_pointer_array_kind': IsPointerArrayKind,
413 'is_enum_array_kind': IsEnumArrayKind, 515 'is_enum_array_kind': IsEnumArrayKind,
414 'is_struct_kind': mojom.IsStructKind, 516 'is_struct_kind': mojom.IsStructKind,
415 'is_union_kind': mojom.IsUnionKind, 517 'is_union_kind': mojom.IsUnionKind,
416 'is_enum_kind': mojom.IsEnumKind, 518 'is_enum_kind': mojom.IsEnumKind,
519 'is_interface_kind': mojom.IsInterfaceKind,
520 'is_interface_request_kind': mojom.IsInterfaceRequestKind,
417 'dart_true_false': GetDartTrueFalse, 521 'dart_true_false': GetDartTrueFalse,
418 'dart_type': DartDeclType, 522 'dart_type': DartDeclType,
419 'name': GetNameForElement, 523 'name': GetNameForElement,
420 'tag_name': GetUnionFieldTagName, 524 'tag_name': GetUnionFieldTagName,
421 'interface_response_name': GetInterfaceResponseName, 525 'interface_response_name': GetInterfaceResponseName,
422 'dot_to_underscore': DotToUnderscore, 526 'dot_to_underscore': DotToUnderscore,
423 'is_cloneable_kind': mojom.IsCloneableKind, 527 'is_cloneable_kind': mojom.IsCloneableKind,
528 'upper_camel': UpperCamelCase,
424 } 529 }
425 530
531 # TODO: This value should be settable via arguments. If False, then mojom type
532 # information will not be generated.
533 should_gen_mojom_types = True
534
426 def GetParameters(self, args): 535 def GetParameters(self, args):
536 package = GetPackageName(self.module)
537 defInterface = len(self.module.interfaces) > 0
538
427 return { 539 return {
428 "namespace": self.module.namespace, 540 "namespace": self.module.namespace,
429 "imports": self.GetImports(args), 541 "imports": self.GetImports(args),
430 "kinds": self.module.kinds, 542 "kinds": self.module.kinds,
431 "enums": self.module.enums, 543 "enums": self.module.enums,
432 "module": resolver.ResolveConstants(self.module, ExpressionToText), 544 "module": resolver.ResolveConstants(self.module, ExpressionToText),
433 "structs": self.GetStructs() + self.GetStructsFromMethods(), 545 "structs": self.GetStructs() + self.GetStructsFromMethods(),
434 "unions": self.GetUnions(), 546 "unions": self.GetUnions(),
435 "interfaces": self.GetInterfaces(), 547 "interfaces": self.GetInterfaces(),
436 "imported_interfaces": self.GetImportedInterfaces(), 548 "imported_interfaces": self.GetImportedInterfaces(),
437 "imported_from": self.ImportedFrom(), 549 "imported_from": self.ImportedFrom(),
550 "typepkg": '%s.' % _mojom_types_pkg_short \
551 if package != _mojom_types_pkg_short else '',
552 "descpkg": '%s.' % _service_describer_pkg_short \
553 if package != _service_describer_pkg_short else '',
554 "mojom_types_import": 'import \'%s\' as %s;' % \
555 (_mojom_types_pkg, _mojom_types_pkg_short) \
556 if package != _mojom_types_pkg_short else '',
557 "service_describer_import": 'import \'%s\' as %s;' % \
558 (_service_describer_pkg, _service_describer_pkg_short) \
559 if defInterface and package != _service_describer_pkg_short else '',
560 }
561
562 def GetGlobals(self):
563 return {
564 'should_gen_mojom_types': self.should_gen_mojom_types,
438 } 565 }
439 566
440 @UseJinja("dart_templates/module.lib.tmpl", filters=dart_filters) 567 @UseJinja("dart_templates/module.lib.tmpl", filters=dart_filters)
441 def GenerateLibModule(self, args): 568 def GenerateLibModule(self, args):
442 return self.GetParameters(args) 569 return self.GetParameters(args)
443 570
444 571
445 def GenerateFiles(self, args): 572 def GenerateFiles(self, args):
446 elements = self.module.namespace.split('.') 573 elements = self.module.namespace.split('.')
447 elements.append("%s.dart" % self.module.name) 574 elements.append("%s.dart" % self.module.name)
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
500 interface_to_import[name] = each_import["unique_name"] + "." + name 627 interface_to_import[name] = each_import["unique_name"] + "." + name
501 return interface_to_import 628 return interface_to_import
502 629
503 def ImportedFrom(self): 630 def ImportedFrom(self):
504 interface_to_import = {} 631 interface_to_import = {}
505 for each_import in self.module.imports: 632 for each_import in self.module.imports:
506 for each_interface in each_import["module"].interfaces: 633 for each_interface in each_import["module"].interfaces:
507 name = each_interface.name 634 name = each_interface.name
508 interface_to_import[name] = each_import["unique_name"] + "." 635 interface_to_import[name] = each_import["unique_name"] + "."
509 return interface_to_import 636 return interface_to_import
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698