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

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: Simplify identifier_store for Go and Dart Created 5 years 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 from collections import defaultdict
zra 2015/11/24 17:34:44 I'm not familiar with python conventions for impor
azani 2015/11/24 20:02:02 The prescribed style is that you import the module
alexfandrianto 2015/12/18 01:53:19 Not needed anymore. No more identifiercache
7 import os 8 import os
8 import re 9 import re
9 import shutil 10 import shutil
10 import sys 11 import sys
11 12
12 import mojom.fileutil as fileutil 13 import mojom.fileutil as fileutil
13 import mojom.generate.constant_resolver as resolver 14 import mojom.generate.constant_resolver as resolver
14 import mojom.generate.generator as generator 15 import mojom.generate.generator as generator
15 import mojom.generate.module as mojom 16 import mojom.generate.module as mojom
16 import mojom.generate.pack as pack 17 import mojom.generate.pack as pack
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 mojom.NULLABLE_DPPIPE: "core.MojoDataPipeProducer", 64 mojom.NULLABLE_DPPIPE: "core.MojoDataPipeProducer",
64 mojom.NULLABLE_MSGPIPE: "core.MojoMessagePipeEndpoint", 65 mojom.NULLABLE_MSGPIPE: "core.MojoMessagePipeEndpoint",
65 mojom.NULLABLE_SHAREDBUFFER: "core.MojoSharedBuffer", 66 mojom.NULLABLE_SHAREDBUFFER: "core.MojoSharedBuffer",
66 mojom.INT64: "int", 67 mojom.INT64: "int",
67 mojom.UINT64: "int", 68 mojom.UINT64: "int",
68 mojom.DOUBLE: "double", 69 mojom.DOUBLE: "double",
69 mojom.STRING: "String", 70 mojom.STRING: "String",
70 mojom.NULLABLE_STRING: "String" 71 mojom.NULLABLE_STRING: "String"
71 } 72 }
72 73
74 _kind_to_mojom_type = {
75 mojom.BOOL: "BOOL",
76 mojom.INT8: "INT8",
77 mojom.UINT8: "UINT8",
78 mojom.INT16: "INT16",
79 mojom.UINT16: "UINT16",
80 mojom.INT32: "INT32",
81 mojom.UINT32: "UINT32",
82 mojom.FLOAT: "FLOAT",
83 mojom.HANDLE: "UNSPECIFIED",
84 mojom.DCPIPE: "DATA_PIPE_CONSUMER",
85 mojom.DPPIPE: "DATA_PIPE_PRODUCER",
86 mojom.MSGPIPE: "MESSAGE_PIPE",
87 mojom.SHAREDBUFFER: "SHARED_BUFFER",
88 mojom.NULLABLE_HANDLE: "UNSPECIFIED",
89 mojom.NULLABLE_DCPIPE: "DATA_PIPE_CONSUMER",
90 mojom.NULLABLE_DPPIPE: "DATA_PIPE_PRODUCER",
91 mojom.NULLABLE_MSGPIPE: "MESSAGE_PIPE",
92 mojom.NULLABLE_SHAREDBUFFER: "SHARED_BUFFER",
93 mojom.INT64: "INT64",
94 mojom.UINT64: "UINT64",
95 mojom.DOUBLE: "DOUBLE",
96 mojom.STRING: "STRING",
97 mojom.NULLABLE_STRING: "STRING"
98 }
99
73 _spec_to_decode_method = { 100 _spec_to_decode_method = {
74 mojom.BOOL.spec: 'decodeBool', 101 mojom.BOOL.spec: 'decodeBool',
75 mojom.DCPIPE.spec: 'decodeConsumerHandle', 102 mojom.DCPIPE.spec: 'decodeConsumerHandle',
76 mojom.DOUBLE.spec: 'decodeDouble', 103 mojom.DOUBLE.spec: 'decodeDouble',
77 mojom.DPPIPE.spec: 'decodeProducerHandle', 104 mojom.DPPIPE.spec: 'decodeProducerHandle',
78 mojom.FLOAT.spec: 'decodeFloat', 105 mojom.FLOAT.spec: 'decodeFloat',
79 mojom.HANDLE.spec: 'decodeHandle', 106 mojom.HANDLE.spec: 'decodeHandle',
80 mojom.INT16.spec: 'decodeInt16', 107 mojom.INT16.spec: 'decodeInt16',
81 mojom.INT32.spec: 'decodeInt32', 108 mojom.INT32.spec: 'decodeInt32',
82 mojom.INT64.spec: 'decodeInt64', 109 mojom.INT64.spec: 'decodeInt64',
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 mojom.NULLABLE_SHAREDBUFFER.spec: 'encodeSharedBufferHandle', 142 mojom.NULLABLE_SHAREDBUFFER.spec: 'encodeSharedBufferHandle',
116 mojom.NULLABLE_STRING.spec: 'encodeString', 143 mojom.NULLABLE_STRING.spec: 'encodeString',
117 mojom.SHAREDBUFFER.spec: 'encodeSharedBufferHandle', 144 mojom.SHAREDBUFFER.spec: 'encodeSharedBufferHandle',
118 mojom.STRING.spec: 'encodeString', 145 mojom.STRING.spec: 'encodeString',
119 mojom.UINT16.spec: 'encodeUint16', 146 mojom.UINT16.spec: 'encodeUint16',
120 mojom.UINT32.spec: 'encodeUint32', 147 mojom.UINT32.spec: 'encodeUint32',
121 mojom.UINT64.spec: 'encodeUint64', 148 mojom.UINT64.spec: 'encodeUint64',
122 mojom.UINT8.spec: 'encodeUint8', 149 mojom.UINT8.spec: 'encodeUint8',
123 } 150 }
124 151
152 # The mojom_types.mojom and service_describer.mojom files are special because
zra 2015/11/24 17:34:44 It looks like you might be trying to avoid importi
alexfandrianto 2015/12/18 01:53:19 Done.
153 # they are used to generate mojom Type's and ServiceDescription implementations.
154 _service_describer_pkg_short = "service_describer"
155 _service_describer_pkg = "package:mojo/mojo/%s.mojom.dart" % \
156 _service_describer_pkg_short
157 _mojom_types_pkg_short = "mojom_types"
158 _mojom_types_pkg = "package:mojo/mojo/%s.mojom.dart" % \
159 _mojom_types_pkg_short
160
125 def GetDartType(kind): 161 def GetDartType(kind):
126 if kind.imported_from: 162 if kind.imported_from:
127 return kind.imported_from["unique_name"] + "." + GetNameForElement(kind) 163 return kind.imported_from["unique_name"] + "." + GetNameForElement(kind)
128 return GetNameForElement(kind) 164 return GetNameForElement(kind)
129 165
130 def DartDefaultValue(field): 166 def DartDefaultValue(field):
131 if field.default: 167 if field.default:
132 if mojom.IsStructKind(field.kind): 168 if mojom.IsStructKind(field.kind):
133 assert field.default == "default" 169 assert field.default == "default"
134 return "new %s()" % GetDartType(field.kind) 170 return "new %s()" % GetDartType(field.kind)
(...skipping 30 matching lines...) Expand all
165 if mojom.IsMapKind(kind): 201 if mojom.IsMapKind(kind):
166 key_type = DartDeclType(kind.key_kind) 202 key_type = DartDeclType(kind.key_kind)
167 value_type = DartDeclType(kind.value_kind) 203 value_type = DartDeclType(kind.value_kind)
168 return "Map<"+ key_type + ", " + value_type + ">" 204 return "Map<"+ key_type + ", " + value_type + ">"
169 if mojom.IsInterfaceKind(kind) or \ 205 if mojom.IsInterfaceKind(kind) or \
170 mojom.IsInterfaceRequestKind(kind): 206 mojom.IsInterfaceRequestKind(kind):
171 return "Object" 207 return "Object"
172 if mojom.IsEnumKind(kind): 208 if mojom.IsEnumKind(kind):
173 return GetDartType(kind) 209 return GetDartType(kind)
174 210
211 def GetMojomTypeValue(kind, typepkg=''):
212 if not kind in _kind_to_mojom_type:
213 return ''
214
215 nullable = 'true' if mojom.IsNullableKind(kind) else 'false'
216 w = _kind_to_mojom_type[kind]
217 if kind == mojom.BOOL or kind == mojom.FLOAT or kind == mojom.DOUBLE or \
218 mojom.IsIntegralKind(kind):
219
220 return 'new %sType()..simpleType = %sSimpleType.%s' % (typepkg, typepkg, w)
221 elif mojom.IsAnyHandleKind(kind):
222 return ('new %sType()\n..handleType = (new %sHandleType()' +
223 '\n..kind = %sHandleTypeKind.%s' +
224 '\n..nullable = %s)') % \
225 (typepkg, typepkg, typepkg, w, nullable)
226 elif mojom.IsStringKind(kind):
227 return 'new %sType()\n..stringType = (new %sStringType()..nullable = %s)' \
228 % (typepkg, typepkg, nullable)
229 else:
230 raise Exception('Missing case for kind: %s' % kind)
231
175 def NameToComponent(name): 232 def NameToComponent(name):
176 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar -> 233 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar ->
177 # HTTP_Entry2_FooBar) 234 # HTTP_Entry2_FooBar)
178 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name) 235 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name)
179 # insert '_' between non upper and start of upper blocks (e.g., 236 # insert '_' between non upper and start of upper blocks (e.g.,
180 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar) 237 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar)
181 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name) 238 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name)
182 return [x.lower() for x in name.split('_')] 239 return [x.lower() for x in name.split('_')]
183 240
184 def UpperCamelCase(name): 241 def UpperCamelCase(name):
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 432
376 def IsPointerArrayKind(kind): 433 def IsPointerArrayKind(kind):
377 if not mojom.IsArrayKind(kind): 434 if not mojom.IsArrayKind(kind):
378 return False 435 return False
379 sub_kind = kind.kind 436 sub_kind = kind.kind
380 return mojom.IsObjectKind(sub_kind) 437 return mojom.IsObjectKind(sub_kind)
381 438
382 def IsEnumArrayKind(kind): 439 def IsEnumArrayKind(kind):
383 return mojom.IsArrayKind(kind) and mojom.IsEnumKind(kind.kind) 440 return mojom.IsArrayKind(kind) and mojom.IsEnumKind(kind.kind)
384 441
442 def IsImportedKind(kind):
443 return hasattr(kind, 'imported_from') and kind.imported_from
444
385 def ParseStringAttribute(attribute): 445 def ParseStringAttribute(attribute):
386 assert isinstance(attribute, basestring) 446 assert isinstance(attribute, basestring)
387 return attribute 447 return attribute
388 448
389 def GetPackage(module): 449 def GetPackage(module):
390 if module.attributes and 'DartPackage' in module.attributes: 450 if module.attributes and 'DartPackage' in module.attributes:
391 return ParseStringAttribute(module.attributes['DartPackage']) 451 return ParseStringAttribute(module.attributes['DartPackage'])
392 # Default package. 452 # Default package.
393 return 'mojom' 453 return 'mojom'
394 454
455 def GetPackageName(module):
456 return module.name.split('.')[0]
457
395 def GetImportUri(module): 458 def GetImportUri(module):
396 package = GetPackage(module); 459 package = GetPackage(module);
397 elements = module.namespace.split('.') 460 elements = module.namespace.split('.')
398 elements.append("%s" % module.name) 461 elements.append("%s" % module.name)
399 return os.path.join(package, *elements) 462 return os.path.join(package, *elements)
400 463
464 # The identifier_store tracks identifiers that have been used so that code
zra 2015/11/24 17:34:44 Is this needed for the new code generation you're
alexfandrianto 2015/12/18 01:53:19 Removed
465 # generation can avoid over-generating code for the same identifier.
466 identifier_store = defaultdict(bool)
467 def GetIdentifier(kind):
468 # Use the kind's module to determine the package and name.
469 # Note: InterfaceRequestKind's should use the Interface inside them.
470 if hasattr(kind, 'module'):
471 package = GetPackageName(kind.module)
472 name = kind.name
473 elif mojom.IsInterfaceRequestKind(kind):
474 package = GetPackageName(kind.kind.module)
475 name = kind.kind.name
476 else:
477 # This is for a type that should not be stored. Return an empty identifier.
478 return ''
479
480 return '%s_%s' % (package, name)
481
482 def StoreIdentifier(identifier):
483 identifier_store[identifier] = True
484 return ''
485
486 def CheckIdentifier(identifier):
487 return identifier in identifier_store
488
489 def GetMojomTypeIdentifier(kind):
490 """Get the mojom type's identifier suffix."""
491 # Since this should be unique, it is based on the type's identifier.
492 return "_%s__" % GetIdentifier(kind)
493
401 class Generator(generator.Generator): 494 class Generator(generator.Generator):
402 495
403 dart_filters = { 496 dart_filters = {
404 'array_expected_length': GetArrayExpectedLength, 497 'array_expected_length': GetArrayExpectedLength,
405 'array': GetArrayKind, 498 'array': GetArrayKind,
406 'decode_method': DecodeMethod, 499 'decode_method': DecodeMethod,
407 'default_value': DartDefaultValue, 500 'default_value': DartDefaultValue,
408 'encode_method': EncodeMethod, 501 'encode_method': EncodeMethod,
409 'expression_to_text': ExpressionToText, 502 'expression_to_text': ExpressionToText,
503 'identifier': GetIdentifier,
504 'identifier_check': CheckIdentifier,
505 'identifier_store': StoreIdentifier,
506 'mojom_type_value': GetMojomTypeValue,
507 'mojom_type_identifier': GetMojomTypeIdentifier,
508 'is_imported_kind': IsImportedKind,
509 'is_array_kind': mojom.IsArrayKind,
410 'is_map_kind': mojom.IsMapKind, 510 'is_map_kind': mojom.IsMapKind,
411 'is_nullable_kind': mojom.IsNullableKind, 511 'is_nullable_kind': mojom.IsNullableKind,
412 'is_pointer_array_kind': IsPointerArrayKind, 512 'is_pointer_array_kind': IsPointerArrayKind,
413 'is_enum_array_kind': IsEnumArrayKind, 513 'is_enum_array_kind': IsEnumArrayKind,
414 'is_struct_kind': mojom.IsStructKind, 514 'is_struct_kind': mojom.IsStructKind,
415 'is_union_kind': mojom.IsUnionKind, 515 'is_union_kind': mojom.IsUnionKind,
416 'is_enum_kind': mojom.IsEnumKind, 516 'is_enum_kind': mojom.IsEnumKind,
517 'is_interface_kind': mojom.IsInterfaceKind,
518 'is_interface_request_kind': mojom.IsInterfaceRequestKind,
417 'dart_true_false': GetDartTrueFalse, 519 'dart_true_false': GetDartTrueFalse,
418 'dart_type': DartDeclType, 520 'dart_type': DartDeclType,
419 'name': GetNameForElement, 521 'name': GetNameForElement,
420 'tag_name': GetUnionFieldTagName, 522 'tag_name': GetUnionFieldTagName,
421 'interface_response_name': GetInterfaceResponseName, 523 'interface_response_name': GetInterfaceResponseName,
422 'dot_to_underscore': DotToUnderscore, 524 'dot_to_underscore': DotToUnderscore,
423 'is_cloneable_kind': mojom.IsCloneableKind, 525 'is_cloneable_kind': mojom.IsCloneableKind,
526 'upper_camel': UpperCamelCase,
424 } 527 }
425 528
529 # If set to True, then mojom type information will be generated.
530 should_gen_mojom_types = False
531
426 def GetParameters(self, args): 532 def GetParameters(self, args):
427 return { 533 package = GetPackageName(self.module)
534
535 parameters = {
428 "namespace": self.module.namespace, 536 "namespace": self.module.namespace,
429 "imports": self.GetImports(args), 537 "imports": self.GetImports(args),
430 "kinds": self.module.kinds, 538 "kinds": self.module.kinds,
431 "enums": self.module.enums, 539 "enums": self.module.enums,
432 "module": resolver.ResolveConstants(self.module, ExpressionToText), 540 "module": resolver.ResolveConstants(self.module, ExpressionToText),
433 "structs": self.GetStructs() + self.GetStructsFromMethods(), 541 "structs": self.GetStructs() + self.GetStructsFromMethods(),
434 "unions": self.GetUnions(), 542 "unions": self.GetUnions(),
435 "interfaces": self.GetInterfaces(), 543 "interfaces": self.GetInterfaces(),
436 "imported_interfaces": self.GetImportedInterfaces(), 544 "imported_interfaces": self.GetImportedInterfaces(),
437 "imported_from": self.ImportedFrom(), 545 "imported_from": self.ImportedFrom(),
546 "typepkg": '%s.' % _mojom_types_pkg_short,
547 "descpkg": '%s.' % _service_describer_pkg_short,
548 "mojom_types_import": 'import \'%s\' as %s;' % \
549 (_mojom_types_pkg, _mojom_types_pkg_short),
550 "service_describer_import": 'import \'%s\' as %s;' % \
551 (_service_describer_pkg, _service_describer_pkg_short),
552 }
553
554 # If this is the mojom types package, clear the import-related params.
555 if package == _mojom_types_pkg_short:
556 parameters["typepkg"] = ""
557 parameters["mojom_types_import"] = ""
558
559 # If this is the service describer package, clear the import-related params.
560 if package == _service_describer_pkg_short:
561 parameters["descpkg"] = ""
562 parameters["service_describer_import"] = ""
563
564 # If no interfaces were defined, the service describer import isn't needed.
565 if len(self.module.interfaces) == 0:
566 parameters["service_describer_import"] = ""
567
568 return parameters
569
570 def GetGlobals(self):
571 return {
572 'should_gen_mojom_types': self.should_gen_mojom_types,
438 } 573 }
439 574
440 @UseJinja("dart_templates/module.lib.tmpl", filters=dart_filters) 575 @UseJinja("dart_templates/module.lib.tmpl", filters=dart_filters)
441 def GenerateLibModule(self, args): 576 def GenerateLibModule(self, args):
442 return self.GetParameters(args) 577 return self.GetParameters(args)
443 578
444 579
445 def GenerateFiles(self, args): 580 def GenerateFiles(self, args):
581 if "--dart_gen_types" in args:
582 self.should_gen_mojom_types = True
583
446 elements = self.module.namespace.split('.') 584 elements = self.module.namespace.split('.')
447 elements.append("%s.dart" % self.module.name) 585 elements.append("%s.dart" % self.module.name)
448 586
449 lib_module = self.GenerateLibModule(args) 587 lib_module = self.GenerateLibModule(args)
450 588
451 # List of packages with checked in bindings. 589 # List of packages with checked in bindings.
452 # TODO(johnmccutchan): Stop generating bindings as part of build system 590 # TODO(johnmccutchan): Stop generating bindings as part of build system
453 # and then remove this. 591 # and then remove this.
454 packages_with_checked_in_bindings = [ 592 packages_with_checked_in_bindings = [
455 '_mojo_for_test_only', 593 '_mojo_for_test_only',
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 interface_to_import[name] = each_import["unique_name"] + "." + name 651 interface_to_import[name] = each_import["unique_name"] + "." + name
514 return interface_to_import 652 return interface_to_import
515 653
516 def ImportedFrom(self): 654 def ImportedFrom(self):
517 interface_to_import = {} 655 interface_to_import = {}
518 for each_import in self.module.imports: 656 for each_import in self.module.imports:
519 for each_interface in each_import["module"].interfaces: 657 for each_interface in each_import["module"].interfaces:
520 name = each_interface.name 658 name = each_interface.name
521 interface_to_import[name] = each_import["unique_name"] + "." 659 interface_to_import[name] = each_import["unique_name"] + "."
522 return interface_to_import 660 return interface_to_import
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698