| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright 2015 The Chromium Authors. All rights reserved. | |
| 3 # Use of this source code is governed by a BSD-style license that can be | |
| 4 # found in the LICENSE file. | |
| 5 # | |
| 6 # This module is responsible for translating a MojomFileGraph (see | |
| 7 # mojom_files.mojom) to one or more module.Module. | |
| 8 # | |
| 9 # This module takes the output of the mojom parser, a MojomFileGraph and | |
| 10 # translates it to the input of the code generators, a module.Module object. | |
| 11 # This is part of version 2 of the code generation pipeline. In version 1, the | |
| 12 # analogous functionality (translating from parser output to code generators | |
| 13 # input) is performed by the data module. | |
| 14 # | |
| 15 # The code generators remain from version 1 of the pipeline and so this module | |
| 16 # serves as an adapter between the v1 backends and the v2 frontend. | |
| 17 # | |
| 18 # The current version of this script does not validate the input data at all | |
| 19 # and instead trusts that it will be invoked with valid data produced by the | |
| 20 # frontend parser. | |
| 21 # | |
| 22 # NOTE: This module assumes that the python path contains the generated modules | |
| 23 # for mojom_files.mojom and mojom_types.mojom as well as their dependencies. | |
| 24 # It is the responsibility of the module's loader to handle this. | |
| 25 | |
| 26 import os | |
| 27 | |
| 28 from generated import mojom_files_mojom | |
| 29 from generated import mojom_types_mojom | |
| 30 import module | |
| 31 import operator | |
| 32 import pack | |
| 33 | |
| 34 | |
| 35 class FileTranslator(object): | |
| 36 """FileTranslator translates a MojomFile to a module.Module.""" | |
| 37 def __init__(self, graph, file_name): | |
| 38 """Initializes a FileTranslator. | |
| 39 | |
| 40 Args: | |
| 41 graph: {mojom_files_mojom.MojomFileGraph} containing the file to be | |
| 42 translated. | |
| 43 file_name: {str} key to the file to be translated in graph.files. | |
| 44 """ | |
| 45 assert isinstance(graph, mojom_files_mojom.MojomFileGraph) | |
| 46 self._type_cache = {} | |
| 47 self._value_cache = {} | |
| 48 self._constant_cache = {} | |
| 49 self._graph = graph | |
| 50 self._file_name = file_name | |
| 51 self._types = {} | |
| 52 self._module = module.Module() | |
| 53 self._transitive_imports = {} | |
| 54 | |
| 55 def Translate(self): | |
| 56 """Translates the file specified in the constructor. | |
| 57 | |
| 58 Returns: | |
| 59 {module.Module} representing the translated file. | |
| 60 """ | |
| 61 mojom_file = self._graph.files[self._file_name] | |
| 62 | |
| 63 mod = self._module | |
| 64 self.PopulateModuleMetadata(mod, mojom_file) | |
| 65 | |
| 66 mod.imports = [] | |
| 67 self._transitive_imports = self.GetTransitiveImports(mojom_file) | |
| 68 mod.transitive_imports = self._transitive_imports.values() | |
| 69 if mojom_file.imports: | |
| 70 mod.imports = [ | |
| 71 self._transitive_imports[imp] for imp in mojom_file.imports] | |
| 72 | |
| 73 if mojom_file.declared_mojom_objects: | |
| 74 if mojom_file.declared_mojom_objects.top_level_constants: | |
| 75 mod.constants = [ | |
| 76 self.ConstantFromKey(key) | |
| 77 for key in mojom_file.declared_mojom_objects.top_level_constants] | |
| 78 | |
| 79 user_defined_types = ['interfaces', 'structs', 'unions'] | |
| 80 for user_defined_type in user_defined_types: | |
| 81 if getattr(mojom_file.declared_mojom_objects, user_defined_type): | |
| 82 setattr(mod, user_defined_type, [self.UserDefinedFromTypeKey(key) | |
| 83 for key in getattr( | |
| 84 mojom_file.declared_mojom_objects, user_defined_type)]) | |
| 85 if mojom_file.declared_mojom_objects.top_level_enums: | |
| 86 mod.enums = [self.UserDefinedFromTypeKey(key) | |
| 87 for key in mojom_file.declared_mojom_objects.top_level_enums] | |
| 88 | |
| 89 mod.serialized_runtime_type_info = mojom_file.serialized_runtime_type_info | |
| 90 | |
| 91 return mod | |
| 92 | |
| 93 def PopulateModuleMetadata(self, mod, mojom_file): | |
| 94 """Populates some fields of a module.Module based on a MojomFile. | |
| 95 | |
| 96 Populates name, path, namespace and attributes of mod. | |
| 97 | |
| 98 Args: | |
| 99 mod: {module.Module} the module to be populated. | |
| 100 mojom_file: {MojomFile} the file to be translated. | |
| 101 """ | |
| 102 mod.name = os.path.basename(mojom_file.file_name) | |
| 103 # specified_file_name is the file name specified on the command line if one | |
| 104 # was specified. The mojom parser sets specified_file_name to the empty | |
| 105 # string if the file was parsed only because the file was imported by | |
| 106 # another file. While specified_file_name can be None, the mojom parser | |
| 107 # should not set it to None, so we check for that error here. | |
| 108 assert mojom_file.specified_file_name is not None | |
| 109 mod.specified_name = mojom_file.specified_file_name | |
| 110 mod.path = mojom_file.file_name | |
| 111 mod.namespace = mojom_file.module_namespace | |
| 112 # Note that attribute values are typed. That is why we use | |
| 113 # attr.value.data directly instead of the string representation of it. | |
| 114 if mojom_file.attributes: | |
| 115 mod.attributes = {attr.key: | |
| 116 attr.value.data for attr in mojom_file.attributes} | |
| 117 | |
| 118 def GetTransitiveImports(self, mojom_file): | |
| 119 """Gets a mojom file's transitive imports. | |
| 120 | |
| 121 Args: | |
| 122 mojom_file: {mojom_files.MojomFile} the mojom file whose imports have to | |
| 123 be found. | |
| 124 | |
| 125 Returns: | |
| 126 {dict} The key is the file_name which is an index into self._graph.files | |
| 127 and is referenced in the SourceFileInfo.file_name of imported types. | |
| 128 The value is a dictionary as returned by ImportFromMojom. | |
| 129 """ | |
| 130 if not mojom_file.imports: | |
| 131 return {} | |
| 132 to_be_processed = set(mojom_file.imports) | |
| 133 processed = set() | |
| 134 transitive_imports = {} | |
| 135 | |
| 136 while to_be_processed: | |
| 137 import_name = to_be_processed.pop() | |
| 138 processed.add(import_name) | |
| 139 | |
| 140 import_dict = self.ImportFromMojom(import_name) | |
| 141 | |
| 142 transitive_imports[import_dict['module'].path] = import_dict | |
| 143 | |
| 144 import_file = self._graph.files[import_name] | |
| 145 if import_file.imports: | |
| 146 to_be_processed.update(set(import_file.imports) - processed) | |
| 147 | |
| 148 return transitive_imports | |
| 149 | |
| 150 def ImportFromMojom(self, import_name): | |
| 151 """Builds a dict representing an import. | |
| 152 | |
| 153 Args: | |
| 154 import_name: {str} key to the imported file in graph.files. | |
| 155 | |
| 156 Returns: | |
| 157 {dict} representing the imported file. | |
| 158 """ | |
| 159 import_file = self._graph.files[import_name] | |
| 160 import_module = module.Module() | |
| 161 self.PopulateModuleMetadata(import_module, import_file) | |
| 162 | |
| 163 import_item = { | |
| 164 'module_name': import_module.name, | |
| 165 'namespace': import_module.namespace, | |
| 166 'module': import_module, | |
| 167 } | |
| 168 return import_item | |
| 169 | |
| 170 def UnionFromMojom(self, union, mojom_type): | |
| 171 """Populates a module.Union based on a MojomUnion. | |
| 172 | |
| 173 Args: | |
| 174 union: {module.Union} to be populated. | |
| 175 mojom_type: {UserDefinedType} referring to the MojomUnion to be | |
| 176 translated. | |
| 177 """ | |
| 178 assert mojom_type.tag == mojom_types_mojom.UserDefinedType.Tags.union_type | |
| 179 mojom_union = mojom_type.union_type | |
| 180 self.PopulateUserDefinedType(union, mojom_union) | |
| 181 union.fields = [self.UnionFieldFromMojom(f) for f in mojom_union.fields] | |
| 182 # mojom_union.fields is indexed by the field tags. We want | |
| 183 # to capture these tags but sort union.fields by declaration_order. | |
| 184 union.fields.sort(key=lambda field: field.declaration_order) | |
| 185 | |
| 186 def StructFromMojom(self, struct, mojom_type): | |
| 187 """Populates a module.Struct based on a MojomStruct. | |
| 188 | |
| 189 Args: | |
| 190 struct: {module.Struct} to be populated. | |
| 191 mojom_type: {UserDefinedType} referring to the MojomStruct to be | |
| 192 translated. | |
| 193 """ | |
| 194 assert mojom_type.tag == mojom_types_mojom.UserDefinedType.Tags.struct_type | |
| 195 mojom_struct = mojom_type.struct_type | |
| 196 self.StructFromMojomStruct(struct, mojom_struct) | |
| 197 | |
| 198 def StructFromMojomStruct(self, struct, mojom_struct): | |
| 199 """Populates a module.Struct based on a MojomStruct. | |
| 200 | |
| 201 Args: | |
| 202 struct: {module.Struct} to be populated. | |
| 203 mojom_struct: {mojom_types.MojomStruct} to be translated. | |
| 204 """ | |
| 205 self.PopulateUserDefinedType(struct, mojom_struct) | |
| 206 # mojom_struct.fields is indexed by the field ordinals. | |
| 207 struct.fields_in_ordinal_order = [self.StructFieldFromMojom(ordinal, f) | |
| 208 for (ordinal, f) in enumerate(mojom_struct.fields)] | |
| 209 # We also want a list of fields sorted in declaration_order. | |
| 210 struct.fields = [f for f in struct.fields_in_ordinal_order] | |
| 211 struct.fields.sort(key=lambda field: field.declaration_order) | |
| 212 | |
| 213 assert mojom_struct.version_info | |
| 214 struct.versions = [self.VersionInfoFromMojom(version) for version in | |
| 215 mojom_struct.version_info] | |
| 216 self.PopulateContainedDeclarationsFromMojom( | |
| 217 struct, mojom_struct.decl_data.contained_declarations) | |
| 218 | |
| 219 def UnionFieldFromMojom(self, mojom_field): | |
| 220 """Translates a mojom_types_mojom.UnionField to a module.UnionField. | |
| 221 | |
| 222 Args: | |
| 223 mojom_field: {mojom_types_mojom.UnionField} to be translated. | |
| 224 | |
| 225 Returns: | |
| 226 {module.UnionField} translated from mojom_field. | |
| 227 """ | |
| 228 union_field = module.UnionField() | |
| 229 self.PopulateCommonFieldValues(union_field, mojom_field) | |
| 230 # The |ordinal| attribute of |union_field| contains the field's tag | |
| 231 # as computed by the Mojom front-end. | |
| 232 union_field.ordinal = mojom_field.tag | |
| 233 # The |declared_tag| field is populated only if the user explicitly | |
| 234 # specified a tag for the field in the .mojom file and as such is not | |
| 235 # defined for every field. If defined it is equal to the |ordinal| | |
| 236 # attribute. Currently no code generators are consuming this data. | |
| 237 union_field.declared_tag = self.OrdinalFromMojom(mojom_field) | |
| 238 # The declaration_order field preserves the index of the field in | |
| 239 # declaration order in the .mojom file. | |
| 240 union_field.declaration_order = mojom_field.decl_data.declaration_order | |
| 241 return union_field | |
| 242 | |
| 243 def StructFieldFromMojom(self, ordinal, mojom_field): | |
| 244 """Translates a mojom_types_mojom.StructField to a module.StructField. | |
| 245 | |
| 246 Args: | |
| 247 ordinal: {int} The 0-based ordinal position of the field within the | |
| 248 struct. Note that this is not necessarily the same as the lexical | |
| 249 order or the packing order. | |
| 250 mojom_field: {mojom_types_mojom.StructField} to be translated. | |
| 251 | |
| 252 Returns: | |
| 253 {module.StructField} translated from mojom_field. | |
| 254 """ | |
| 255 struct_field = module.StructField() | |
| 256 self.PopulateCommonFieldValues(struct_field, mojom_field) | |
| 257 struct_field.computed_offset = mojom_field.offset | |
| 258 struct_field.computed_bit = mojom_field.bit | |
| 259 struct_field.computed_min_version = mojom_field.min_version | |
| 260 # Note that the |ordinal| attribute of |struct_field| records only the | |
| 261 # *declared* ordinal and as such is not defined for every field whereas | |
| 262 # the |computed_ordinal| attribute is defined for every field. If | |
| 263 # |ordinal| is defined then it is equal to |computed_ordinal|. | |
| 264 struct_field.ordinal = self.OrdinalFromMojom(mojom_field) | |
| 265 struct_field.computed_ordinal = ordinal | |
| 266 struct_field.declaration_order = mojom_field.decl_data.declaration_order | |
| 267 if mojom_field.default_value: | |
| 268 if (mojom_field.default_value.tag == | |
| 269 mojom_types_mojom.DefaultFieldValue.Tags.default_keyword): | |
| 270 struct_field.default = 'default' | |
| 271 else: | |
| 272 struct_field.default = self.ValueFromMojom( | |
| 273 mojom_field.default_value.value) | |
| 274 | |
| 275 return struct_field | |
| 276 | |
| 277 def VersionInfoFromMojom(self, mojom_version): | |
| 278 """Translates a mojom_types_mojom.StructVersion to a pack.VersionInfo | |
| 279 Args: | |
| 280 mojom_version: {mojom_types_mojom.StructVersion} to be translated. | |
| 281 | |
| 282 Returns: | |
| 283 {pack.VersionInfo} translated from |mojom_version|. | |
| 284 """ | |
| 285 return pack.VersionInfo(mojom_version.version_number, | |
| 286 mojom_version.num_fields, mojom_version.num_bytes) | |
| 287 | |
| 288 | |
| 289 def ParamFromMojom(self, mojom): | |
| 290 """Translates a mojom_types_mojom.StructField to a module.Parameter. | |
| 291 | |
| 292 The parameters passed to and returned from a method are expressed as a | |
| 293 struct. The struct fields in the struct are the parameters. | |
| 294 | |
| 295 Args: | |
| 296 mojom: {mojom_types_mojom.StructField} representing a method parameter. | |
| 297 | |
| 298 Returns: | |
| 299 {module.Parameter} translated from the mojom. | |
| 300 """ | |
| 301 param = module.Parameter() | |
| 302 param.ordinal = self.OrdinalFromMojom(mojom) | |
| 303 self.PopulateCommonFieldValues(param, mojom) | |
| 304 return param | |
| 305 | |
| 306 def PopulateCommonFieldValues(self, field, mojom_field): | |
| 307 """Populates a number of common field values based on a mojom field. | |
| 308 | |
| 309 Args: | |
| 310 field: {module.Field|module.Parameter} to be populated. | |
| 311 mojom_field: {StructField|UnionField} to be translated. | |
| 312 """ | |
| 313 # TODO(rudominer) Some of the code generators check that the type | |
| 314 # of field.name is a non-unicode string. If we change this we can | |
| 315 # remove the str() below. | |
| 316 field.name = str(mojom_field.decl_data.short_name) | |
| 317 field.kind = self.KindFromMojom(mojom_field.type) | |
| 318 field.attributes = self.AttributesFromMojom(mojom_field) | |
| 319 | |
| 320 def PopulateContainedDeclarationsFromMojom( | |
| 321 self, parent_kind, contained_declarations): | |
| 322 """Populates a module.Struct|module.Interface with contained declarations. | |
| 323 | |
| 324 Args: | |
| 325 parent_kind: {module.Struct|module.Interface} to be populated. | |
| 326 contained_declarations: {mojom_types_mojom.ContainedDeclarations} from | |
| 327 which the contained types need to be extracted. | |
| 328 """ | |
| 329 if not contained_declarations: | |
| 330 return | |
| 331 | |
| 332 if contained_declarations.enums: | |
| 333 for enum_key in contained_declarations.enums: | |
| 334 enum = self.UserDefinedFromTypeKey(enum_key) | |
| 335 parent_kind.enums.append(enum) | |
| 336 | |
| 337 if contained_declarations.constants: | |
| 338 for const_key in contained_declarations.constants: | |
| 339 const = self.ConstantFromKey(const_key) | |
| 340 parent_kind.constants.append(const) | |
| 341 | |
| 342 def EnumFromMojom(self, enum, mojom_type): | |
| 343 """Populates a module.Enum based on a MojomEnum. | |
| 344 | |
| 345 Args: | |
| 346 enum: {module.Enum} to be populated. | |
| 347 mojom_type: {mojom_types_mojom.Type} referring to the MojomEnum to be | |
| 348 translated. | |
| 349 """ | |
| 350 assert mojom_type.tag == mojom_types_mojom.UserDefinedType.Tags.enum_type | |
| 351 mojom_enum = mojom_type.enum_type | |
| 352 self.PopulateUserDefinedType(enum, mojom_enum) | |
| 353 if mojom_enum.decl_data.container_type_key: | |
| 354 parent_kind = self.UserDefinedFromTypeKey( | |
| 355 mojom_enum.decl_data.container_type_key) | |
| 356 enum.parent_kind = parent_kind | |
| 357 enum.fields = [self.EnumFieldFromMojom(value) | |
| 358 for value in mojom_enum.values] | |
| 359 | |
| 360 def EnumFieldFromMojom(self, mojom_enum_value): | |
| 361 """Translates an mojom_types_mojom.EnumValue to a module.EnumField. | |
| 362 | |
| 363 mojom_enum_value: {mojom_types_mojom.EnumValue} to be translated. | |
| 364 | |
| 365 Returns: | |
| 366 {module.EnumField} translated from mojom_enum_value. | |
| 367 """ | |
| 368 field = module.EnumField() | |
| 369 field.name = mojom_enum_value.decl_data.short_name | |
| 370 field.attributes = self.AttributesFromMojom(mojom_enum_value) | |
| 371 field.numeric_value = mojom_enum_value.int_value | |
| 372 if mojom_enum_value.initializer_value is not None: | |
| 373 field.value = self.ValueFromMojom(mojom_enum_value.initializer_value) | |
| 374 | |
| 375 return field | |
| 376 | |
| 377 def AttributesFromMojom(self, mojom): | |
| 378 """Extracts the attributes from a Mojom object into a dict. | |
| 379 | |
| 380 Args: | |
| 381 mojom: A type in mojom_types_mojom containing a decl_data field. | |
| 382 | |
| 383 Returns: | |
| 384 {dict<str, str>} of the attributes. | |
| 385 """ | |
| 386 if not mojom.decl_data.attributes: | |
| 387 return None | |
| 388 | |
| 389 # Note that attribute values are typed. That is why we use | |
| 390 # attr.value.data directly instead of the string representation of it. | |
| 391 return {attr.key: attr.value.data for attr in mojom.decl_data.attributes} | |
| 392 | |
| 393 def PopulateUserDefinedType(self, module_type, mojom): | |
| 394 """Populates fields that are common among user-defined types. | |
| 395 | |
| 396 Args: | |
| 397 module_type: {module.Struct|Union|Enum} to be populated. | |
| 398 mojom: {MojomStruct|MojomUnion|MojomEnum} to be translated. | |
| 399 """ | |
| 400 module_type.attributes = self.AttributesFromMojom(mojom) | |
| 401 module_type.name = mojom.decl_data.short_name | |
| 402 module_type.spec = mojom.decl_data.full_identifier | |
| 403 if module_type.spec == None: | |
| 404 module_type.spec = mojom.decl_data.short_name | |
| 405 self.PopulateModuleOrImportedFrom(module_type, mojom) | |
| 406 | |
| 407 def PopulateModuleOrImportedFrom(self, module_type, mojom): | |
| 408 """Populates either the module field or the imported_from field. | |
| 409 | |
| 410 All user-defined types must have either the module field populated (if | |
| 411 they are from the currently-processed module) or the imported_from (if | |
| 412 they are imported from another module). | |
| 413 | |
| 414 Args: | |
| 415 module_type: {module.Struct|Union|Enum|Interface} to be populated. | |
| 416 mojom: {MojomStruct|MojomUnion|MojomEnum|MojomInterface} to be translated. | |
| 417 """ | |
| 418 if mojom.decl_data.source_file_info: | |
| 419 if mojom.decl_data.source_file_info.file_name == self._file_name: | |
| 420 module_type.module = self._module | |
| 421 else: | |
| 422 imported_from = self._transitive_imports[ | |
| 423 mojom.decl_data.source_file_info.file_name] | |
| 424 module_type.imported_from = imported_from | |
| 425 module_type.module = imported_from['module'] | |
| 426 | |
| 427 | |
| 428 def OrdinalFromMojom(self, mojom): | |
| 429 """Extracts the declared ordinal from a mojom StructField or UnionField. | |
| 430 | |
| 431 Args: | |
| 432 mojom: {MojomStruct|MojomUnion} from which the ordinal is to be extracted. | |
| 433 | |
| 434 Returns: | |
| 435 {int} if an ordinal was present, {NoneType} otherwise. | |
| 436 """ | |
| 437 ordinal = mojom.decl_data.declared_ordinal | |
| 438 if ordinal < 0: | |
| 439 return None | |
| 440 return ordinal | |
| 441 | |
| 442 def InterfaceFromMojom(self, interface, mojom_type): | |
| 443 """Populates a module.Interface from a mojom_types_mojom.MojomInterface. | |
| 444 | |
| 445 Args: | |
| 446 interface: {module.Interface} to be populated. | |
| 447 mojom_type: {UserDefinedType} referring to the MojomInterface to be | |
| 448 translated. | |
| 449 """ | |
| 450 assert (mojom_type.tag | |
| 451 == mojom_types_mojom.UserDefinedType.Tags.interface_type) | |
| 452 mojom_interface = mojom_type.interface_type | |
| 453 interface.attributes = self.AttributesFromMojom(mojom_interface) | |
| 454 self.PopulateModuleOrImportedFrom(interface, mojom_interface) | |
| 455 interface.name = mojom_interface.decl_data.short_name | |
| 456 interface.spec = interface.name | |
| 457 interface.version = mojom_interface.current_version | |
| 458 interface.service_name = mojom_interface.service_name | |
| 459 if interface.attributes: | |
| 460 assert interface.service_name == interface.attributes.get( | |
| 461 'ServiceName', None), interface.service_name | |
| 462 else: | |
| 463 assert interface.service_name is None, interface.service_name | |
| 464 | |
| 465 | |
| 466 # Translate the dictionary of methods into a list of module.Methods. | |
| 467 interface.methods = [self.MethodFromMojom(mojom_method, interface) | |
| 468 for ordinal, mojom_method in mojom_interface.methods.iteritems()] | |
| 469 # We want the methods in an interface to be in some deterministic order | |
| 470 # and we choose declaration order (i.e. lexical order within the | |
| 471 # .mojom file.) | |
| 472 interface.methods.sort(key=lambda method: method.declaration_order) | |
| 473 self.PopulateContainedDeclarationsFromMojom( | |
| 474 interface, mojom_interface.decl_data.contained_declarations) | |
| 475 | |
| 476 def MethodFromMojom(self, mojom_method, interface): | |
| 477 """Translates a mojom_types_mojom.MojomMethod to a module.Method. | |
| 478 | |
| 479 Args: | |
| 480 mojom_method: {mojom_types_mojom.MojomMethod} to be translated. | |
| 481 interface: {module.Interface} the method is a member of. | |
| 482 | |
| 483 Returns: | |
| 484 {module.Method} translated from mojom_method. | |
| 485 """ | |
| 486 method = module.Method(interface, mojom_method.decl_data.short_name) | |
| 487 method.ordinal = mojom_method.ordinal | |
| 488 method.declaration_order = mojom_method.decl_data.declaration_order | |
| 489 method.param_struct = module.Struct() | |
| 490 self.StructFromMojomStruct(method.param_struct, mojom_method.parameters) | |
| 491 # The name of a synthetic request parameter struct is not guaranteed by | |
| 492 # the frontend to be anything in particular so we set the name of the | |
| 493 # translated struct to a value that the code generators are expecting. | |
| 494 method.param_struct.name = "%s_%s_Params" % ( | |
| 495 method.interface.name, method.name) | |
| 496 method.parameters = [self.ParamFromMojom(param) | |
| 497 for param in mojom_method.parameters.fields] | |
| 498 if mojom_method.response_params is not None: | |
| 499 method.response_param_struct = module.Struct() | |
| 500 self.StructFromMojomStruct(method.response_param_struct, | |
| 501 mojom_method.response_params) | |
| 502 # The name of a synthetic response parameter struct is not guaranteed by | |
| 503 # the frontend to be anything in particular so we set the name of the | |
| 504 # translated struct to a value that the code generators are expecting. | |
| 505 method.response_param_struct.name = "%s_%s_ResponseParams" % ( | |
| 506 method.interface.name, method.name) | |
| 507 method.response_parameters = [self.ParamFromMojom(param) | |
| 508 for param in mojom_method.response_params.fields] | |
| 509 | |
| 510 method.min_version=mojom_method.min_version | |
| 511 | |
| 512 return method | |
| 513 | |
| 514 def ConstantFromKey(self, constant_key): | |
| 515 """Takes a key into the map graph.resolved_constants and returns the module | |
| 516 equivalent constant. | |
| 517 | |
| 518 Args: | |
| 519 constant_key: {str} the key referring to the constant whose translation | |
| 520 is to be returned. | |
| 521 | |
| 522 Returns: | |
| 523 {module.Constant} translated. | |
| 524 """ | |
| 525 if constant_key in self._constant_cache: | |
| 526 return self._constant_cache[constant_key] | |
| 527 | |
| 528 mojom_const = self._graph.resolved_constants[constant_key] | |
| 529 const = module.Constant() | |
| 530 self._constant_cache[constant_key] = const | |
| 531 | |
| 532 self.ConstantFromMojom(const, mojom_const) | |
| 533 return const | |
| 534 | |
| 535 def ConstantFromMojom(self, const, mojom_const): | |
| 536 """Populates a module.Constant based on a DeclaredConstant. | |
| 537 | |
| 538 Args: | |
| 539 const: {module.Constant} to be populated. | |
| 540 mojom_const: {mojom_types_mojom.DeclaredConstant} to be translated. | |
| 541 | |
| 542 Returns: | |
| 543 {module.Constant} translated from mojom_const. | |
| 544 """ | |
| 545 const.name = mojom_const.decl_data.short_name | |
| 546 const.kind = self.KindFromMojom(mojom_const.type) | |
| 547 const.value = self.ValueFromMojom(mojom_const.value) | |
| 548 const.parent_kind = None | |
| 549 if mojom_const.decl_data.container_type_key: | |
| 550 const.parent_kind = self.UserDefinedFromTypeKey( | |
| 551 mojom_const.decl_data.container_type_key) | |
| 552 | |
| 553 def ValueFromMojom(self, value): | |
| 554 """Translates a mojom_types_mojom.Value. | |
| 555 | |
| 556 Args: | |
| 557 value: {mojom_types_mojom.Value} to be translated. | |
| 558 | |
| 559 Returns: | |
| 560 {str|module.BuiltinValue|module.NamedValue} translated from the passed in | |
| 561 mojom_value. | |
| 562 If value is a literal value, a string is returned. If the literal value is | |
| 563 a string literal value, the returned string is enclosed in double | |
| 564 quotes. If the literal value is a boolean literal value then one of the | |
| 565 strings 'true' or 'false' is returned. Otherwise the literal value is a | |
| 566 numeric literal value and in this case the returned value is a Python | |
| 567 string representation of the numeric value. | |
| 568 If value is a built-in value, a module.BuiltinValue is returned. | |
| 569 If value is a user defined reference, a module.NamedValue is returned. | |
| 570 """ | |
| 571 if value.tag == mojom_types_mojom.Value.Tags.literal_value: | |
| 572 if (value.literal_value.tag | |
| 573 == mojom_types_mojom.LiteralValue.Tags.string_value): | |
| 574 return '"%s"' % value.literal_value.data | |
| 575 if (value.literal_value.tag | |
| 576 == mojom_types_mojom.LiteralValue.Tags.bool_value): | |
| 577 # The strings 'true' and 'false' are used to represent bool literals. | |
| 578 return ('%s' % value.literal_value.data).lower() | |
| 579 elif (value.literal_value.tag | |
| 580 == mojom_types_mojom.LiteralValue.Tags.float_value or | |
| 581 value.literal_value.tag | |
| 582 == mojom_types_mojom.LiteralValue.Tags.double_value): | |
| 583 # Use the Python repr() function to get a string that accurately | |
| 584 # represents the value of the floating point number. | |
| 585 return repr(value.literal_value.data) | |
| 586 return str(value.literal_value.data) | |
| 587 elif value.tag == mojom_types_mojom.Value.Tags.builtin_value: | |
| 588 mojom_to_builtin = { | |
| 589 mojom_types_mojom.BuiltinConstantValue.DOUBLE_INFINITY: | |
| 590 'double.INFINITY', | |
| 591 mojom_types_mojom.BuiltinConstantValue.DOUBLE_NEGATIVE_INFINITY: | |
| 592 'double.NEGATIVE_INFINITY', | |
| 593 mojom_types_mojom.BuiltinConstantValue.DOUBLE_NAN: | |
| 594 'double.NAN', | |
| 595 mojom_types_mojom.BuiltinConstantValue.FLOAT_INFINITY: | |
| 596 'float.INFINITY', | |
| 597 mojom_types_mojom.BuiltinConstantValue.FLOAT_NEGATIVE_INFINITY: | |
| 598 'float.NEGATIVE_INFINITY', | |
| 599 mojom_types_mojom.BuiltinConstantValue.FLOAT_NAN: 'float.NAN', | |
| 600 } | |
| 601 return module.BuiltinValue(mojom_to_builtin[value.builtin_value]) | |
| 602 return self.FromUserValueReference(value) | |
| 603 | |
| 604 def FromUserValueReference(self, value): | |
| 605 """Translates a mojom_types.EnumValueReference or ConstantReference into the | |
| 606 module equivalent. | |
| 607 | |
| 608 Args: | |
| 609 value: {mojom_types_mojom.Value} the value ref to be translated. It | |
| 610 must be of type EnumValueReference or ConstantReference. | |
| 611 | |
| 612 Returns: | |
| 613 {module.EnumValue|module.ConstantValue} translated. | |
| 614 """ | |
| 615 if value.tag == mojom_types_mojom.Value.Tags.constant_reference: | |
| 616 return self.ConstantValueFromKey(value.constant_reference.constant_key) | |
| 617 assert value.tag == mojom_types_mojom.Value.Tags.enum_value_reference | |
| 618 return self.EnumValueFromKey(value.enum_value_reference.enum_type_key, | |
| 619 value.enum_value_reference.enum_value_index) | |
| 620 | |
| 621 def ConstantValueFromKey(self, constant_key): | |
| 622 """Takes a key into graph.resolved_constants referring to a | |
| 623 mojom declared_constant and returns a module.ConstantValue referring to the | |
| 624 module equivalent constant. | |
| 625 | |
| 626 Args: | |
| 627 constant_key: {str} the constant key referring to a constant. | |
| 628 | |
| 629 Returns: | |
| 630 {module.ConstantValue} translated. | |
| 631 """ | |
| 632 if constant_key in self._value_cache: | |
| 633 return self._value_cache[constant_key] | |
| 634 | |
| 635 const_value = module.ConstantValue() | |
| 636 self._value_cache[constant_key] = const_value | |
| 637 | |
| 638 const = self.ConstantFromKey(constant_key) | |
| 639 const_value.constant = const | |
| 640 const_value.name = const.name | |
| 641 const_value.parent_kind = const.parent_kind | |
| 642 self.PopulateModuleOrImportedFrom(const_value, | |
| 643 self._graph.resolved_constants[constant_key]) | |
| 644 const_value.namespace = const_value.module.namespace | |
| 645 return const_value | |
| 646 | |
| 647 def EnumValueFromKey(self, enum_type_key, enum_value_index): | |
| 648 """Takes an enum type key and an enum value index (together these | |
| 649 form a key to a mojom_enum_value) and returns a module.EnumValue referring | |
| 650 the module equivalent enum value | |
| 651 | |
| 652 Args: | |
| 653 enum_type_key: {str} the type key of a mojom_enum | |
| 654 enum_value_index: {int} the 0-based index into the |values| array of | |
| 655 the mojom_enum | |
| 656 | |
| 657 Returns: | |
| 658 {module.EnumValue} translated from mojom_enum_value. | |
| 659 """ | |
| 660 enum_value_key = (enum_type_key, enum_value_index) | |
| 661 if enum_value_key in self._value_cache: | |
| 662 return self._value_cache[enum_value_key] | |
| 663 | |
| 664 mojom_enum = self._graph.resolved_types[enum_type_key].enum_type | |
| 665 mojom_enum_value = mojom_enum.values[enum_value_index] | |
| 666 | |
| 667 # We need to create and cache the EnumValue object just in case later calls | |
| 668 # require the creation of that same EnumValue object. | |
| 669 enum_value = module.EnumValue() | |
| 670 self._value_cache[enum_value_key] = enum_value | |
| 671 | |
| 672 enum = self.UserDefinedFromTypeKey(enum_type_key) | |
| 673 enum_value.enum = enum | |
| 674 self.PopulateModuleOrImportedFrom(enum_value, mojom_enum_value) | |
| 675 enum_value.namespace = enum_value.module.namespace | |
| 676 enum_value.parent_kind = enum.parent_kind | |
| 677 enum_value.name = mojom_enum_value.decl_data.short_name | |
| 678 | |
| 679 return enum_value | |
| 680 | |
| 681 def KindFromMojom(self, mojom_type): | |
| 682 """Translates a mojom_types_mojom.Type to its equivalent module type. | |
| 683 | |
| 684 It is guaranteed that two calls to KindFromMojom with the same input yield | |
| 685 the same object. | |
| 686 | |
| 687 Args: | |
| 688 mojom_type: {mojom_types_mojom.Type} to be translated. | |
| 689 | |
| 690 Returns: | |
| 691 {module.Kind} translated from mojom_type. | |
| 692 """ | |
| 693 mappers = { | |
| 694 mojom_types_mojom.Type.Tags.simple_type: self.SimpleKindFromMojom, | |
| 695 mojom_types_mojom.Type.Tags.string_type: self.StringFromMojom, | |
| 696 mojom_types_mojom.Type.Tags.handle_type: self.HandleFromMojom, | |
| 697 mojom_types_mojom.Type.Tags.array_type: self.ArrayFromMojom, | |
| 698 mojom_types_mojom.Type.Tags.map_type: self.MapFromMojom, | |
| 699 mojom_types_mojom.Type.Tags.type_reference: self.UserDefinedFromTypeRef, | |
| 700 } | |
| 701 return mappers[mojom_type.tag](mojom_type) | |
| 702 | |
| 703 def SimpleKindFromMojom(self, mojom_type): | |
| 704 """Translates a simple type to its module equivalent. | |
| 705 | |
| 706 Args: | |
| 707 mojom_type: {mojom_types_mojom.Type} with its simple_type field set to be | |
| 708 translated. | |
| 709 | |
| 710 Returns: | |
| 711 {module.Kind} translated from mojom_type. | |
| 712 """ | |
| 713 simple_mojom_types = { | |
| 714 mojom_types_mojom.SimpleType.BOOL: module.BOOL, | |
| 715 mojom_types_mojom.SimpleType.INT8: module.INT8, | |
| 716 mojom_types_mojom.SimpleType.INT16: module.INT16, | |
| 717 mojom_types_mojom.SimpleType.INT32: module.INT32, | |
| 718 mojom_types_mojom.SimpleType.INT64: module.INT64, | |
| 719 mojom_types_mojom.SimpleType.UINT8: module.UINT8, | |
| 720 mojom_types_mojom.SimpleType.UINT16: module.UINT16, | |
| 721 mojom_types_mojom.SimpleType.UINT32: module.UINT32, | |
| 722 mojom_types_mojom.SimpleType.UINT64: module.UINT64, | |
| 723 mojom_types_mojom.SimpleType.FLOAT: module.FLOAT, | |
| 724 mojom_types_mojom.SimpleType.DOUBLE: module.DOUBLE, | |
| 725 } | |
| 726 return simple_mojom_types[mojom_type.simple_type] | |
| 727 | |
| 728 def HandleFromMojom(self, mojom_type): | |
| 729 """Translates a handle type to its module equivalent. | |
| 730 | |
| 731 Args: | |
| 732 mojom_type: {mojom_types_mojom.Type} with its handle_type field set to be | |
| 733 translated. | |
| 734 | |
| 735 Returns: | |
| 736 {module.ReferenceKind} translated from mojom_type. | |
| 737 """ | |
| 738 handle_mojom_types = { | |
| 739 mojom_types_mojom.HandleType.Kind.UNSPECIFIED: module.HANDLE, | |
| 740 mojom_types_mojom.HandleType.Kind.MESSAGE_PIPE: module.MSGPIPE, | |
| 741 mojom_types_mojom.HandleType.Kind.DATA_PIPE_CONSUMER: module.DCPIPE, | |
| 742 mojom_types_mojom.HandleType.Kind.DATA_PIPE_PRODUCER: module.DPPIPE, | |
| 743 mojom_types_mojom.HandleType.Kind.SHARED_BUFFER: module.SHAREDBUFFER, | |
| 744 } | |
| 745 | |
| 746 nullable_handle_mojom_types = { | |
| 747 mojom_types_mojom.HandleType.Kind.UNSPECIFIED: module.NULLABLE_HANDLE, | |
| 748 mojom_types_mojom.HandleType.Kind.MESSAGE_PIPE: module.NULLABLE_MSGPIPE, | |
| 749 mojom_types_mojom.HandleType.Kind.DATA_PIPE_CONSUMER: | |
| 750 module.NULLABLE_DCPIPE, | |
| 751 mojom_types_mojom.HandleType.Kind.DATA_PIPE_PRODUCER: | |
| 752 module.NULLABLE_DPPIPE, | |
| 753 mojom_types_mojom.HandleType.Kind.SHARED_BUFFER: | |
| 754 module.NULLABLE_SHAREDBUFFER, | |
| 755 } | |
| 756 | |
| 757 if mojom_type.handle_type.nullable: | |
| 758 return nullable_handle_mojom_types[mojom_type.handle_type.kind] | |
| 759 return handle_mojom_types[mojom_type.handle_type.kind] | |
| 760 | |
| 761 def StringFromMojom(self, mojom_type): | |
| 762 """Translates a string type to its module equivalent. | |
| 763 | |
| 764 Args: | |
| 765 mojom_type: {mojom_types_mojom.Type} with its string_type field set to be | |
| 766 translated. | |
| 767 | |
| 768 Returns: | |
| 769 {module.ReferenceKind} translated from mojom_type. Either module.STRING or | |
| 770 module.NULLABLE_STRING. | |
| 771 """ | |
| 772 if mojom_type.string_type.nullable: | |
| 773 return module.NULLABLE_STRING | |
| 774 return module.STRING | |
| 775 | |
| 776 def ArrayFromMojom(self, mojom_type): | |
| 777 """Translates an array type to its module equivalent. | |
| 778 | |
| 779 Args: | |
| 780 mojom_type: {mojom_types_mojom.Type} with its array_type field set to be | |
| 781 translated. | |
| 782 | |
| 783 Returns: | |
| 784 {module.Array} translated from mojom_type. | |
| 785 """ | |
| 786 array = module.Array( | |
| 787 kind=self.KindFromMojom(mojom_type.array_type.element_type)) | |
| 788 if mojom_type.array_type.fixed_length > 0: | |
| 789 array.length = mojom_type.array_type.fixed_length | |
| 790 if mojom_type.array_type.nullable: | |
| 791 return array.MakeNullableKind() | |
| 792 return array | |
| 793 | |
| 794 def MapFromMojom(self, mojom_type): | |
| 795 """Translates a map type to its module equivalent. | |
| 796 | |
| 797 Args: | |
| 798 mojom_type: {mojom_types_mojom.Type} with its map_type field set to be | |
| 799 translated. | |
| 800 | |
| 801 Returns: | |
| 802 {module.Map} translated from mojom_type. | |
| 803 """ | |
| 804 key_kind = self.KindFromMojom(mojom_type.map_type.key_type) | |
| 805 value_kind = self.KindFromMojom(mojom_type.map_type.value_type) | |
| 806 module_map = module.Map(key_kind=key_kind, value_kind=value_kind) | |
| 807 if mojom_type.map_type.nullable: | |
| 808 return module_map.MakeNullableKind() | |
| 809 return module_map | |
| 810 | |
| 811 def UserDefinedFromTypeRef(self, mojom_type): | |
| 812 """Translates a type reference to the module equivalent of the | |
| 813 UserDefinedType that the reference refers to. | |
| 814 | |
| 815 Args: | |
| 816 mojom_type: {mojom_types_mojom.Type} with its type_reference field set to | |
| 817 be translated. | |
| 818 | |
| 819 Returns: | |
| 820 {module.Enum|Struct|Union|Interface} translated from mojom_type. | |
| 821 """ | |
| 822 type_key = mojom_type.type_reference.type_key | |
| 823 module_type = self.UserDefinedFromTypeKey(type_key) | |
| 824 if mojom_type.type_reference.is_interface_request: | |
| 825 module_type = module.InterfaceRequest(module_type) | |
| 826 if mojom_type.type_reference.nullable: | |
| 827 return module_type.MakeNullableKind() | |
| 828 return module_type | |
| 829 | |
| 830 def UserDefinedFromTypeKey(self, type_key): | |
| 831 """Takes a type key into graph.resolved_types and returns the module | |
| 832 equivalent. | |
| 833 | |
| 834 Args: | |
| 835 type_key: {str} the type key referring to the type to be returned. | |
| 836 | |
| 837 Returns: | |
| 838 {module.Enum|Struct|Union|Interface} translated. | |
| 839 """ | |
| 840 if type_key in self._type_cache: | |
| 841 return self._type_cache[type_key] | |
| 842 else: | |
| 843 mojom_type = self._graph.resolved_types[type_key] | |
| 844 return self.UserDefinedFromMojom(type_key, mojom_type) | |
| 845 | |
| 846 def UserDefinedFromMojom(self, type_key, mojom_type): | |
| 847 """Translates a user defined type to its module equivalent. | |
| 848 | |
| 849 Args: | |
| 850 type_key: {str} the type key referring to the type in graph.resolved_types | |
| 851 used to cache the type object. | |
| 852 mojom_type: {mojom_types_mojom.UserDefinedType} to be translated. | |
| 853 | |
| 854 Returns: | |
| 855 {module.Enum|Struct|Union|Interface} translated from mojom_type. | |
| 856 """ | |
| 857 user_defined_types = { | |
| 858 mojom_types_mojom.UserDefinedType.Tags.struct_type: | |
| 859 (module.Struct, self.StructFromMojom), | |
| 860 mojom_types_mojom.UserDefinedType.Tags.enum_type: | |
| 861 (module.Enum, self.EnumFromMojom), | |
| 862 mojom_types_mojom.UserDefinedType.Tags.union_type: | |
| 863 (module.Union, self.UnionFromMojom), | |
| 864 mojom_types_mojom.UserDefinedType.Tags.interface_type: | |
| 865 (module.Interface, self.InterfaceFromMojom), | |
| 866 } | |
| 867 module_type_class, from_mojom = user_defined_types[mojom_type.tag] | |
| 868 module_type = module_type_class() | |
| 869 | |
| 870 if module_type.spec == None: | |
| 871 # module.py expects the spec of user defined types to be set when | |
| 872 # constructing map, array, and interface request types, but the value | |
| 873 # appears to be only used for error messages. | |
| 874 module_type.spec = 'dummyspec' | |
| 875 | |
| 876 # It is necessary to cache the type object before populating it since in | |
| 877 # the course of populating it, it may be necessary to resolve that same | |
| 878 # type (say, a struct with a field of its own type). | |
| 879 self._type_cache[type_key] = module_type | |
| 880 from_mojom(module_type, mojom_type) | |
| 881 | |
| 882 module_type.type_key = type_key | |
| 883 | |
| 884 return module_type | |
| 885 | |
| 886 | |
| 887 def TranslateFileGraph(graph): | |
| 888 """Translates a mojom_types_mojom.MojomFileGraph to module.Module(s). | |
| 889 | |
| 890 The input is the output of the parser. The output is the input to the | |
| 891 various bindings generators. | |
| 892 | |
| 893 Args: | |
| 894 graph: {mojom_types_mojom.MojomFileGraph} to be translated. | |
| 895 | |
| 896 Return: | |
| 897 {dict<str, module.Module>} mapping the file's name to its module.Module | |
| 898 translation for all files in graph.files. | |
| 899 """ | |
| 900 return {file_name: FileTranslator(graph, file_name).Translate() | |
| 901 for file_name in graph.files} | |
| OLD | NEW |