[IR] Unite inline class and multi-field value class representation
#KT-1179
This commit is contained in:
committed by
teamcity
parent
282ab398c6
commit
28bf83ceac
+10
-5
@@ -8,10 +8,15 @@ package org.jetbrains.kotlin.descriptors
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
|
||||
class InlineClassRepresentation<Type : SimpleTypeMarker>(
|
||||
class InlineClassRepresentation<Type : SimpleTypeMarker> constructor(
|
||||
val underlyingPropertyName: Name,
|
||||
val underlyingType: Type,
|
||||
) {
|
||||
inline fun <Other : SimpleTypeMarker> mapUnderlyingType(transform: (Type) -> Other): InlineClassRepresentation<Other> =
|
||||
InlineClassRepresentation(underlyingPropertyName, transform(underlyingType))
|
||||
}
|
||||
) : ValueClassRepresentation<Type>() {
|
||||
|
||||
override val underlyingPropertyNamesToTypes: List<Pair<Name, Type>>
|
||||
get() = listOf(underlyingPropertyName to underlyingType)
|
||||
|
||||
override fun containsPropertyWithName(name: Name): Boolean = underlyingPropertyName == name
|
||||
|
||||
override fun propertyTypeByName(name: Name): Type? = underlyingType.takeIf { containsPropertyWithName(name) }
|
||||
}
|
||||
+4
-10
@@ -9,19 +9,13 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
|
||||
class MultiFieldValueClassRepresentation<Type : SimpleTypeMarker>(
|
||||
val underlyingPropertyNamesToTypes: List<Pair<Name, Type>>
|
||||
) {
|
||||
init {
|
||||
require(underlyingPropertyNamesToTypes.size > 1) { "MultiFieldValueClassRepresentation has at least 2 properties" }
|
||||
}
|
||||
override val underlyingPropertyNamesToTypes: List<Pair<Name, Type>>
|
||||
) : ValueClassRepresentation<Type>() {
|
||||
|
||||
private val map = underlyingPropertyNamesToTypes.toMap().also {
|
||||
require(it.size == underlyingPropertyNamesToTypes.size) { "Some properties have the same names" }
|
||||
}
|
||||
|
||||
fun containsPropertyWithName(name: Name): Boolean = name in map
|
||||
fun propertyTypeByName(name: Name): Type? = map[name]
|
||||
|
||||
inline fun <Other : SimpleTypeMarker> mapUnderlyingType(transform: (Type) -> Other): MultiFieldValueClassRepresentation<Other> =
|
||||
MultiFieldValueClassRepresentation(underlyingPropertyNamesToTypes.map { (key, value) -> key to transform(value) })
|
||||
override fun containsPropertyWithName(name: Name): Boolean = name in map
|
||||
override fun propertyTypeByName(name: Name): Type? = map[name]
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ValueClassKind.Inline
|
||||
import org.jetbrains.kotlin.descriptors.ValueClassKind.MultiField
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||
|
||||
sealed class ValueClassRepresentation<Type : SimpleTypeMarker> {
|
||||
abstract val underlyingPropertyNamesToTypes: List<Pair<Name, Type>>
|
||||
abstract fun containsPropertyWithName(name: Name): Boolean
|
||||
abstract fun getPropertyTypeByName(name: Name): Type?
|
||||
|
||||
fun <Other : SimpleTypeMarker> mapUnderlyingType(transform: (Type) -> Other): ValueClassRepresentation<Other> = when (this) {
|
||||
is InlineClassRepresentation -> InlineClassRepresentation(underlyingPropertyName, transform(underlyingType))
|
||||
is MultiFieldValueClassRepresentation ->
|
||||
MultiFieldValueClassRepresentation(underlyingPropertyNamesToTypes.map { (name, type) -> name to transform(type) })
|
||||
}
|
||||
}
|
||||
|
||||
enum class ValueClassKind { Inline, MultiField }
|
||||
|
||||
fun <Type : SimpleTypeMarker> TypeSystemCommonBackendContext.valueClassLoweringKind(
|
||||
fields: List<Pair<Name, Type>>,
|
||||
): ValueClassKind = when {
|
||||
fields.size > 1 -> MultiField
|
||||
fields.isEmpty() -> error("Value classes cannot have 0 fields")
|
||||
else -> {
|
||||
val type = fields.single().second
|
||||
with(this) {
|
||||
when {
|
||||
type.isNullableType() -> Inline
|
||||
!type.typeConstructor().isMultiFieldValueClass() -> Inline
|
||||
else -> MultiField
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun <Type : SimpleTypeMarker> createValueClassRepresentation(context: TypeSystemCommonBackendContext, fields: List<Pair<Name, Type>>) =
|
||||
when (context.valueClassLoweringKind(fields)) {
|
||||
Inline -> InlineClassRepresentation(fields[0].first, fields[0].second)
|
||||
MultiField -> MultiFieldValueClassRepresentation(fields)
|
||||
}
|
||||
@@ -31,6 +31,8 @@ interface TypeSystemCommonBackendContext : TypeSystemContext {
|
||||
fun KotlinTypeMarker.getAnnotationFirstArgumentValue(fqName: FqName): Any?
|
||||
|
||||
fun TypeConstructorMarker.isInlineClass(): Boolean
|
||||
fun TypeConstructorMarker.isMultiFieldValueClass(): Boolean
|
||||
fun TypeConstructorMarker.valueClassRepresentationTypeMarkersList(): List<Pair<Name, SimpleTypeMarker>>?
|
||||
fun TypeConstructorMarker.isInnerClass(): Boolean
|
||||
fun TypeParameterMarker.getRepresentativeUpperBound(): KotlinTypeMarker
|
||||
fun KotlinTypeMarker.getUnsubstitutedUnderlyingType(): KotlinTypeMarker?
|
||||
|
||||
+1
-3
@@ -196,9 +196,7 @@ class LazyJavaClassDescriptor(
|
||||
emptyList()
|
||||
}
|
||||
|
||||
override fun getInlineClassRepresentation(): InlineClassRepresentation<SimpleType>? = null
|
||||
|
||||
override fun getMultiFieldValueClassRepresentation(): MultiFieldValueClassRepresentation<SimpleType>? = null
|
||||
override fun getValueClassRepresentation(): ValueClassRepresentation<SimpleType>? = null
|
||||
|
||||
override fun toString() = "Lazy Java class ${this.fqNameUnsafe}"
|
||||
|
||||
|
||||
+1
-2
@@ -87,8 +87,7 @@ class FunctionClassDescriptor(
|
||||
override val annotations: Annotations get() = Annotations.EMPTY
|
||||
override fun getSource(): SourceElement = SourceElement.NO_SOURCE
|
||||
override fun getSealedSubclasses() = emptyList<ClassDescriptor>()
|
||||
override fun getInlineClassRepresentation(): InlineClassRepresentation<SimpleType>? = null
|
||||
override fun getMultiFieldValueClassRepresentation(): MultiFieldValueClassRepresentation<SimpleType>? = null
|
||||
override fun getValueClassRepresentation(): ValueClassRepresentation<SimpleType>? = null
|
||||
|
||||
override fun getDeclaredTypeParameters() = parameters
|
||||
|
||||
|
||||
@@ -102,10 +102,7 @@ public interface ClassDescriptor extends ClassifierDescriptorWithTypeParameters,
|
||||
Collection<ClassDescriptor> getSealedSubclasses();
|
||||
|
||||
@Nullable
|
||||
InlineClassRepresentation<SimpleType> getInlineClassRepresentation();
|
||||
|
||||
@Nullable
|
||||
MultiFieldValueClassRepresentation<SimpleType> getMultiFieldValueClassRepresentation();
|
||||
ValueClassRepresentation<SimpleType> getValueClassRepresentation();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
|
||||
@@ -84,8 +84,7 @@ class NotFoundClasses(private val storageManager: StorageManager, private val mo
|
||||
override fun getUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor? = null
|
||||
override fun getCompanionObjectDescriptor(): ClassDescriptor? = null
|
||||
override fun getSealedSubclasses(): Collection<ClassDescriptor> = emptyList()
|
||||
override fun getInlineClassRepresentation(): InlineClassRepresentation<SimpleType>? = null
|
||||
override fun getMultiFieldValueClassRepresentation(): MultiFieldValueClassRepresentation<SimpleType>? = null
|
||||
override fun getValueClassRepresentation(): ValueClassRepresentation<SimpleType>? = null
|
||||
|
||||
override fun toString() = "class $name (not found)"
|
||||
}
|
||||
|
||||
@@ -178,13 +178,7 @@ public class ClassDescriptorImpl extends ClassDescriptorBase {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public InlineClassRepresentation<SimpleType> getInlineClassRepresentation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public MultiFieldValueClassRepresentation<SimpleType> getMultiFieldValueClassRepresentation() {
|
||||
public ValueClassRepresentation<SimpleType> getValueClassRepresentation() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-7
@@ -195,13 +195,7 @@ public class EnumEntrySyntheticClassDescriptor extends ClassDescriptorBase {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public InlineClassRepresentation<SimpleType> getInlineClassRepresentation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public MultiFieldValueClassRepresentation<SimpleType> getMultiFieldValueClassRepresentation() {
|
||||
public ValueClassRepresentation<SimpleType> getValueClassRepresentation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+8
-21
@@ -324,30 +324,17 @@ public class LazySubstitutingClassDescriptor extends ModuleAwareClassDescriptor
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public InlineClassRepresentation<SimpleType> getInlineClassRepresentation() {
|
||||
InlineClassRepresentation<SimpleType> representation = original.getInlineClassRepresentation();
|
||||
//noinspection ConstantConditions
|
||||
return representation == null ? null : new InlineClassRepresentation<SimpleType>(
|
||||
representation.getUnderlyingPropertyName(),
|
||||
substituteSimpleType(representation.getUnderlyingType())
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public MultiFieldValueClassRepresentation<SimpleType> getMultiFieldValueClassRepresentation() {
|
||||
MultiFieldValueClassRepresentation<SimpleType> representation = original.getMultiFieldValueClassRepresentation();
|
||||
public ValueClassRepresentation<SimpleType> getValueClassRepresentation() {
|
||||
ValueClassRepresentation<SimpleType> representation = original.getValueClassRepresentation();
|
||||
if (representation == null) {
|
||||
return null;
|
||||
}
|
||||
List<Pair<Name, SimpleType>> underlyingList = new ArrayList<Pair<Name, SimpleType>>(representation.getUnderlyingPropertyNamesToTypes());
|
||||
for (int i = 0; i < underlyingList.size(); i++) {
|
||||
Pair<Name, SimpleType> pair = underlyingList.get(i);
|
||||
Name name = pair.getFirst();
|
||||
SimpleType simpleType = pair.getSecond();
|
||||
underlyingList.set(i, new Pair<Name, SimpleType>(name, substituteSimpleType(simpleType)));
|
||||
}
|
||||
return new MultiFieldValueClassRepresentation<SimpleType>(underlyingList);
|
||||
return representation.mapUnderlyingType(new Function1<SimpleType, SimpleType>() {
|
||||
@Override
|
||||
public SimpleType invoke(SimpleType type) {
|
||||
return substituteSimpleType(type);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+1
-7
@@ -191,13 +191,7 @@ public class MutableClassDescriptor extends ClassDescriptorBase {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public InlineClassRepresentation<SimpleType> getInlineClassRepresentation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public MultiFieldValueClassRepresentation<SimpleType> getMultiFieldValueClassRepresentation() {
|
||||
public ValueClassRepresentation<SimpleType> getValueClassRepresentation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
||||
import org.jetbrains.kotlin.types.checker.REFINER_CAPABILITY
|
||||
import org.jetbrains.kotlin.types.checker.TypeRefinementSupport
|
||||
import org.jetbrains.kotlin.types.TypeRefinement
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
@@ -450,3 +449,9 @@ fun <D : CallableDescriptor> D.shouldBeSubstituteWithStubTypes() =
|
||||
&& dispatchReceiverParameter?.type?.isError != true
|
||||
&& extensionReceiverParameter?.type?.isError != true
|
||||
&& containsStubTypes()
|
||||
|
||||
val ClassDescriptor?.inlineClassRepresentation: InlineClassRepresentation<SimpleType>?
|
||||
get() = this?.valueClassRepresentation as? InlineClassRepresentation<SimpleType>
|
||||
|
||||
val ClassDescriptor?.multiFieldValueClassRepresentation: MultiFieldValueClassRepresentation<SimpleType>?
|
||||
get() = this?.valueClassRepresentation as? MultiFieldValueClassRepresentation<SimpleType>
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.inlineClassRepresentation
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
@@ -19,16 +20,12 @@ val JVM_INLINE_ANNOTATION_CLASS_ID = ClassId.topLevel(JVM_INLINE_ANNOTATION_FQ_N
|
||||
|
||||
// FIXME: DeserializedClassDescriptor in reflection do not have @JvmInline annotation, that we
|
||||
// FIXME: would like to check as well.
|
||||
fun DeclarationDescriptor.isInlineClass(): Boolean = when {
|
||||
this !is ClassDescriptor -> false
|
||||
isInline -> true
|
||||
else -> isValue && unsubstitutedPrimaryConstructor?.valueParameters?.size?.let { it == 1 } ?: true
|
||||
}
|
||||
fun DeclarationDescriptor.isInlineClass(): Boolean = this is ClassDescriptor && this.valueClassRepresentation is InlineClassRepresentation
|
||||
|
||||
fun DeclarationDescriptor.isValueClass(): Boolean =
|
||||
this is ClassDescriptor && isValue
|
||||
fun DeclarationDescriptor.isMultiFieldValueClass(): Boolean =
|
||||
this is ClassDescriptor && this.valueClassRepresentation is MultiFieldValueClassRepresentation
|
||||
|
||||
fun DeclarationDescriptor.isInlineOrValueClass(): Boolean = isInlineClass() || isValueClass()
|
||||
fun DeclarationDescriptor.isValueClass(): Boolean = isInlineClass() || isMultiFieldValueClass()
|
||||
|
||||
fun KotlinType.unsubstitutedUnderlyingType(): KotlinType? =
|
||||
constructor.declarationDescriptor.safeAs<ClassDescriptor>()?.inlineClassRepresentation?.underlyingType
|
||||
@@ -37,7 +34,7 @@ fun KotlinType.unsubstitutedUnderlyingTypes(): List<KotlinType> {
|
||||
val declarationDescriptor = constructor.declarationDescriptor.safeAs<ClassDescriptor>() ?: return emptyList()
|
||||
return when {
|
||||
declarationDescriptor.isInlineClass() -> listOfNotNull(unsubstitutedUnderlyingType())
|
||||
declarationDescriptor.isValueClass() ->
|
||||
declarationDescriptor.isMultiFieldValueClass() ->
|
||||
declarationDescriptor.unsubstitutedPrimaryConstructor?.valueParameters?.map { it.type } ?: emptyList()
|
||||
else -> emptyList()
|
||||
}
|
||||
@@ -56,8 +53,8 @@ fun KotlinType.isRecursiveInlineOrValueClassType(): Boolean =
|
||||
isRecursiveInlineOrValueClassTypeInner(hashSetOf())
|
||||
|
||||
private fun KotlinType.isRecursiveInlineOrValueClassTypeInner(visited: HashSet<ClassifierDescriptor>): Boolean {
|
||||
val types = when (val descriptor = constructor.declarationDescriptor?.original?.takeIf { it.isInlineOrValueClass() }) {
|
||||
is ClassDescriptor -> if (descriptor.isInlineOrValueClass()) unsubstitutedUnderlyingTypes() else emptyList()
|
||||
val types = when (val descriptor = constructor.declarationDescriptor?.original?.takeIf { it.isValueClass() }) {
|
||||
is ClassDescriptor -> if (descriptor.isValueClass()) unsubstitutedUnderlyingTypes() else emptyList()
|
||||
is TypeParameterDescriptor -> descriptor.upperBounds
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
+13
-4
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.CapturedType
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.resolve.isInlineClass
|
||||
import org.jetbrains.kotlin.resolve.substitutedUnderlyingType
|
||||
import org.jetbrains.kotlin.resolve.unsubstitutedUnderlyingType
|
||||
import org.jetbrains.kotlin.types.*
|
||||
@@ -31,10 +30,10 @@ import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSignedOrUnsignedNumberType as classicIsSignedOrUnsignedNumberType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isStubTypeForVariableInSubtyping as isSimpleTypeStubTypeForVariableInSubtyping
|
||||
import org.jetbrains.kotlin.types.typeUtil.isStubTypeForBuilderInference as isSimpleTypeStubTypeForBuilderInference
|
||||
import org.jetbrains.kotlin.types.typeUtil.isStubType as isSimpleTypeStubType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isStubTypeForBuilderInference as isSimpleTypeStubTypeForBuilderInference
|
||||
import org.jetbrains.kotlin.types.error.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.isStubTypeForVariableInSubtyping as isSimpleTypeStubTypeForVariableInSubtyping
|
||||
|
||||
interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSystemCommonBackendContext {
|
||||
override fun TypeConstructorMarker.isDenotable(): Boolean {
|
||||
@@ -742,7 +741,17 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
||||
|
||||
override fun TypeConstructorMarker.isInlineClass(): Boolean {
|
||||
require(this is TypeConstructor, this::errorMessage)
|
||||
return (declarationDescriptor as? ClassDescriptor)?.isInlineClass() == true
|
||||
return (declarationDescriptor as? ClassDescriptor)?.valueClassRepresentation is InlineClassRepresentation
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.isMultiFieldValueClass(): Boolean {
|
||||
require(this is TypeConstructor, this::errorMessage)
|
||||
return (declarationDescriptor as? ClassDescriptor)?.valueClassRepresentation is MultiFieldValueClassRepresentation
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.valueClassRepresentationTypeMarkersList(): List<Pair<Name, SimpleTypeMarker>>? {
|
||||
require(this is TypeConstructor, this::errorMessage)
|
||||
return (declarationDescriptor as? ClassDescriptor)?.valueClassRepresentation?.underlyingPropertyNamesToTypes
|
||||
}
|
||||
|
||||
override fun TypeConstructorMarker.isInnerClass(): Boolean {
|
||||
|
||||
+42
-32
@@ -17,7 +17,10 @@ import org.jetbrains.kotlin.incremental.record
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.CliSealedClassInheritorsProvider
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.NonReportingOverrideStrategy
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
@@ -68,9 +71,7 @@ class DeserializedClassDescriptor(
|
||||
private val constructors = c.storageManager.createLazyValue { computeConstructors() }
|
||||
private val companionObjectDescriptor = c.storageManager.createNullableLazyValue { computeCompanionObjectDescriptor() }
|
||||
private val sealedSubclasses = c.storageManager.createLazyValue { computeSubclassesForSealedClass() }
|
||||
private val inlineClassRepresentation = c.storageManager.createNullableLazyValue { computeInlineClassRepresentation() }
|
||||
private val multiFieldValueClassRepresentation =
|
||||
c.storageManager.createNullableLazyValue { computeMultiFieldValueClassRepresentation() }
|
||||
private val valueClassRepresentation = c.storageManager.createNullableLazyValue { computeValueClassRepresentation() }
|
||||
|
||||
internal val thisAsProtoContainer: ProtoContainer.Class = ProtoContainer.Class(
|
||||
classProto, c.nameResolver, c.typeTable, sourceElement,
|
||||
@@ -182,12 +183,28 @@ class DeserializedClassDescriptor(
|
||||
|
||||
override fun getSealedSubclasses() = sealedSubclasses()
|
||||
|
||||
override fun getInlineClassRepresentation(): InlineClassRepresentation<SimpleType>? = inlineClassRepresentation()
|
||||
override fun getMultiFieldValueClassRepresentation(): MultiFieldValueClassRepresentation<SimpleType>? =
|
||||
multiFieldValueClassRepresentation()
|
||||
override fun getValueClassRepresentation(): ValueClassRepresentation<SimpleType>? = valueClassRepresentation()
|
||||
|
||||
private fun computeValueClassRepresentation(): ValueClassRepresentation<SimpleType>? {
|
||||
val inlineClassRepresentation = computeInlineClassRepresentation()
|
||||
val multiFieldValueClassRepresentation = computeMultiFieldValueClassRepresentation()
|
||||
return when {
|
||||
inlineClassRepresentation != null && multiFieldValueClassRepresentation != null ->
|
||||
throw IllegalArgumentException("Class cannot have both inline class representation and multi field class representation: $this")
|
||||
(isValue || isInline) && inlineClassRepresentation == null && multiFieldValueClassRepresentation == null ->
|
||||
throw IllegalArgumentException("Value class has no value class representation: $this")
|
||||
else -> inlineClassRepresentation ?: multiFieldValueClassRepresentation
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeInlineClassRepresentation(): InlineClassRepresentation<SimpleType>? {
|
||||
if (!isInlineClass()) return null
|
||||
if (!isInline && !isValue) return null
|
||||
if (isValue &&
|
||||
!classProto.hasInlineClassUnderlyingPropertyName() &&
|
||||
!classProto.hasInlineClassUnderlyingType() &&
|
||||
!classProto.hasInlineClassUnderlyingTypeId() &&
|
||||
classProto.multiFieldValueClassUnderlyingNameCount > 0
|
||||
) return null
|
||||
|
||||
val propertyName = when {
|
||||
classProto.hasInlineClassUnderlyingPropertyName() ->
|
||||
@@ -201,34 +218,27 @@ class DeserializedClassDescriptor(
|
||||
else -> error("Inline class has no underlying property name in metadata: $this")
|
||||
}
|
||||
|
||||
val type = classProto.inlineClassUnderlyingType(c.typeTable)?.let(c.typeDeserializer::simpleType)
|
||||
?: getPropertyTypeFromContributedVariables(propertyName)
|
||||
val type = classProto.inlineClassUnderlyingType(c.typeTable)?.let(c.typeDeserializer::simpleType) ?: run {
|
||||
val underlyingProperty = memberScope.getContributedVariables(propertyName, NoLookupLocation.FROM_DESERIALIZATION)
|
||||
.singleOrNull { it.extensionReceiverParameter == null } ?: error("Value class has no underlying property: $this")
|
||||
underlyingProperty.type as SimpleType
|
||||
}
|
||||
|
||||
return InlineClassRepresentation(propertyName, type)
|
||||
}
|
||||
|
||||
private fun getPropertyTypeFromContributedVariables(propertyName: Name): SimpleType {
|
||||
val underlyingProperty = memberScope.getContributedVariables(propertyName, NoLookupLocation.FROM_DESERIALIZATION)
|
||||
.singleOrNull { it.extensionReceiverParameter == null } ?: error("Value class has no underlying property: $this")
|
||||
return underlyingProperty.type as SimpleType
|
||||
}
|
||||
|
||||
private fun computeMultiFieldValueClassRepresentation(): MultiFieldValueClassRepresentation<SimpleType>? {
|
||||
if (!isValueClass() || isInlineClass()) return null
|
||||
val representation = classProto.multiFieldValueClassRepresentation
|
||||
?: error("No multiFieldValueClassRepresentation for multi-field value class: $this")
|
||||
val propertyList = representation.propertyList.map { valueClassProperty ->
|
||||
val name: Name = c.nameResolver.getName(valueClassProperty.name)
|
||||
val protoType: ProtoBuf.Type = when {
|
||||
valueClassProperty.hasType() -> valueClassProperty.type
|
||||
valueClassProperty.hasTypeId() -> c.typeTable[valueClassProperty.typeId]
|
||||
else -> error("Unlike inline classes before 1.5.0, multi-field value classes always have intermediate representation")
|
||||
}
|
||||
name to c.typeDeserializer.simpleType(protoType)
|
||||
}
|
||||
require(propertyList.size > 1)
|
||||
require(propertyList.distinctBy { (name, _) -> name }.size == propertyList.size)
|
||||
return MultiFieldValueClassRepresentation(propertyList)
|
||||
val names = classProto.multiFieldValueClassUnderlyingNameList.map { c.nameResolver.getName(it) }.takeIf { it.isNotEmpty() }
|
||||
?: return null
|
||||
require(isValue) { "Not a value class: $this" }
|
||||
val typeIdCount = classProto.multiFieldValueClassUnderlyingTypeIdCount
|
||||
val typeCount = classProto.multiFieldValueClassUnderlyingTypeCount
|
||||
val types = when (typeIdCount to typeCount) {
|
||||
names.size to 0 -> classProto.multiFieldValueClassUnderlyingTypeIdList.map { c.typeTable[it] }
|
||||
0 to names.size -> classProto.multiFieldValueClassUnderlyingTypeList
|
||||
else -> error("Illegal multi-field value class representation: $this")
|
||||
}.map { c.typeDeserializer.simpleType(it) }
|
||||
return MultiFieldValueClassRepresentation(names zip types)
|
||||
}
|
||||
|
||||
override fun toString() =
|
||||
@@ -283,7 +293,7 @@ class DeserializedClassDescriptor(
|
||||
|
||||
private inner class DeserializedClassMemberScope(private val kotlinTypeRefiner: KotlinTypeRefiner) : DeserializedMemberScope(
|
||||
c, classProto.functionList, classProto.propertyList, classProto.typeAliasList,
|
||||
classProto.nestedClassNameList.map(c.nameResolver::getName).let { list -> { list } } // workaround KT-13454
|
||||
classProto.nestedClassNameList.map(c.nameResolver::getName).let { { it } } // workaround KT-13454
|
||||
) {
|
||||
private val classDescriptor: DeserializedClassDescriptor get() = this@DeserializedClassDescriptor
|
||||
|
||||
|
||||
@@ -242,18 +242,9 @@ message Class {
|
||||
optional Type inline_class_underlying_type = 18;
|
||||
optional int32 inline_class_underlying_type_id = 19 [(type_id_in_table) = true];
|
||||
|
||||
message MultiFieldValueClassRepresentation {
|
||||
message MultiFieldValueClassProperty {
|
||||
required int32 name = 1;
|
||||
oneof type_representation {
|
||||
Type type = 2;
|
||||
int32 type_id = 3;
|
||||
}
|
||||
}
|
||||
repeated MultiFieldValueClassProperty property = 1;
|
||||
}
|
||||
|
||||
optional MultiFieldValueClassRepresentation multi_field_value_class_representation = 22;
|
||||
repeated int32 multi_field_value_class_underlying_name = 22 [packed = true, (name_id_in_table) = true];
|
||||
repeated Type multi_field_value_class_underlying_type = 23;
|
||||
repeated int32 multi_field_value_class_underlying_type_id = 24 [packed = true, (type_id_in_table) = true];
|
||||
|
||||
optional TypeTable type_table = 30;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user