blob: b25a69a079411ee209fa2eb702a4295931395a1f [file] [log] [blame]
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from .composition_parts import WithCodeGeneratorInfo
from .composition_parts import WithComponent
from .composition_parts import WithDebugInfo
from .composition_parts import WithIdentifier
from .idl_type import IdlType
class Union(WithIdentifier, WithCodeGeneratorInfo, WithComponent,
WithDebugInfo):
"""
Union class makes a group of union types with the same flattened member
types and the same result whether it includes a nullable type or not.
For example, the following union types will be grouped into one Union
instance.
(A? or B or C), (A or B? or C), ((A or B) or C?), (A or (B or C?)), ...
All these unions have the same set of flattened member types (A, B, C) and
include a nullable type.
However, all following union types will be grouped into separate Union
instances.
(A or B), ([X] A or B), ([Y] A or B)
IdlType(A), IdlType([X] A), and IdlType([Y] A) are all distinguished from
each other as they behave differently. Bindings code generators are
expected to define an implementation class for each Union instance.
"""
def __init__(self, identifier, union_types):
"""
Args:
union_types: Union types of which this object consists. All types
in |union_types| must have the same flattened_member_types and
the same value of does_include_nullable_type.
"""
assert isinstance(union_types, (list, tuple))
assert len(union_types) > 0
assert all(
isinstance(union_type, IdlType) and union_type.is_union
for union_type in union_types)
flattened_members = union_types[0].flattened_member_types
does_include_nullable_type = union_types[0].does_include_nullable_type
nullable_members = set()
typedef_members = set()
union_members = set()
for union_type in union_types:
assert union_type.flattened_member_types == flattened_members
assert (union_type.does_include_nullable_type ==
does_include_nullable_type)
for direct_member in union_type.member_types:
if direct_member.is_nullable:
nullable_members.add(direct_member)
if direct_member.is_typedef:
typedef_members.add(direct_member)
if direct_member.is_union:
union_members.add(direct_member)
sort_key = lambda x: x.syntactic_form
components = set()
def collect_components(idl_type):
user_defined_type = idl_type.type_definition_object
if user_defined_type:
components.update(user_defined_type.components)
for idl_type in flattened_members:
idl_type.apply_to_all_composing_elements(collect_components)
WithIdentifier.__init__(self, identifier)
WithCodeGeneratorInfo.__init__(self)
WithComponent.__init__(self, components=sorted(components))
WithDebugInfo.__init__(self)
# Sort improves reproducibility.
self._flattened_members = tuple(
sorted(flattened_members, key=sort_key))
self._does_include_nullable_type = does_include_nullable_type
self._nullable_members = tuple(sorted(nullable_members, key=sort_key))
self._typedef_members = tuple(sorted(typedef_members, key=sort_key))
self._union_members = tuple(sorted(union_members, key=sort_key))
@property
def flattened_member_types(self):
"""
Returns the same list of flattened member types as
IdlType.flattened_member_types.
"""
return self._flattened_members
@property
def does_include_nullable_type(self):
"""
Returns true if any of member type is nullable or a member union
includes a nullable type.
"""
return self._does_include_nullable_type
@property
def nullable_member_types(self):
"""
Returns a list of nullable types which are direct members of union types
of which this object consists.
Given the following unions,
(A? or B or C), (A or B? or C), (A or B or CN) where typedef C? CN;
nullable_member_types returns a list of IdlType(A?) and IdlType(B?).
"""
return self._nullable_members
@property
def typedef_member_types(self):
"""
Returns a list of typedef types which are direct members of union types
of which this object consists.
Given the following unions,
(AT or B), (A or BT) where typedef A AT, and typedef B BT;
typedef_member_types returns a list of IdlType(AT) and IdlType(BT).
"""
return self._typedef_members
@property
def union_member_types(self):
"""
Returns a list of union types which are direct members of union types of
which this object consists.
Given the following unions,
((A or B) or C), (A or (B or C))
union_member_types returns a list of IdlType(A or B) and
IdlType(B or C).
"""
return self._union_members