OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |