kotlin.reflect.jvm.internal.impl.resolve.inlineClassesUtils.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-reflect Show documentation
Show all versions of kotlin-reflect Show documentation
Kotlin Full Reflection Library
/*
* Copyright 2000-2018 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 kotlin.reflect.jvm.internal.impl.resolve
import kotlin.reflect.jvm.internal.impl.descriptors.*
import kotlin.reflect.jvm.internal.impl.name.ClassId
import kotlin.reflect.jvm.internal.impl.name.FqName
import kotlin.reflect.jvm.internal.impl.resolve.descriptorUtil.inlineClassRepresentation
import kotlin.reflect.jvm.internal.impl.resolve.descriptorUtil.multiFieldValueClassRepresentation
import kotlin.reflect.jvm.internal.impl.types.KotlinType
import kotlin.reflect.jvm.internal.impl.types.TypeSubstitutor
import kotlin.reflect.jvm.internal.impl.types.TypeUtils
import kotlin.reflect.jvm.internal.impl.types.Variance
import kotlin.reflect.jvm.internal.impl.types.checker.SimpleClassicTypeSystemContext.isNullableType
val JVM_INLINE_ANNOTATION_FQ_NAME = FqName("kotlin.jvm.JvmInline")
val JVM_INLINE_ANNOTATION_CLASS_ID = ClassId.topLevel(JVM_INLINE_ANNOTATION_FQ_NAME)
// FIXME: DeserializedClassDescriptor in reflection do not have @JvmInline annotation, that we
// FIXME: would like to check as well.
fun DeclarationDescriptor.isInlineClass(): Boolean = this is ClassDescriptor && this.valueClassRepresentation is InlineClassRepresentation
fun DeclarationDescriptor.isMultiFieldValueClass(): Boolean =
this is ClassDescriptor && this.valueClassRepresentation is MultiFieldValueClassRepresentation
fun DeclarationDescriptor.isValueClass(): Boolean = isInlineClass() || isMultiFieldValueClass()
fun KotlinType.unsubstitutedUnderlyingType(): KotlinType? =
(constructor.declarationDescriptor as? ClassDescriptor)?.inlineClassRepresentation?.underlyingType
fun KotlinType.unsubstitutedUnderlyingTypes(): List {
val declarationDescriptor = constructor.declarationDescriptor as? ClassDescriptor ?: return emptyList()
return when {
declarationDescriptor.isInlineClass() -> listOfNotNull(unsubstitutedUnderlyingType())
declarationDescriptor.isMultiFieldValueClass() ->
declarationDescriptor.unsubstitutedPrimaryConstructor?.valueParameters?.map { it.type } ?: emptyList()
else -> emptyList()
}
}
fun KotlinType.isInlineClassType(): Boolean = constructor.declarationDescriptor?.isInlineClass() ?: false
fun KotlinType.isMultiFieldValueClassType(): Boolean = constructor.declarationDescriptor?.isMultiFieldValueClass() ?: false
fun KotlinType.isValueClassType(): Boolean = constructor.declarationDescriptor?.isValueClass() ?: false
fun KotlinType.needsMfvcFlattening(): Boolean =
constructor.declarationDescriptor?.run { isMultiFieldValueClass() && !isNullableType() } == true
fun KotlinType.substitutedUnderlyingType(): KotlinType? =
unsubstitutedUnderlyingType()?.let { TypeSubstitutor.create(this).substitute(it, Variance.INVARIANT) }
fun KotlinType.substitutedUnderlyingTypes(): List =
unsubstitutedUnderlyingTypes().map { TypeSubstitutor.create(this).substitute(it, Variance.INVARIANT) }
fun KotlinType.isRecursiveInlineOrValueClassType(): Boolean =
isRecursiveInlineOrValueClassTypeInner(hashSetOf())
private fun KotlinType.isRecursiveInlineOrValueClassTypeInner(visited: HashSet): Boolean {
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()
}
return types.any {
val classifier = it.constructor.declarationDescriptor?.original ?: return@any false
!visited.add(classifier) || it.isRecursiveInlineOrValueClassTypeInner(visited).also { visited.remove(classifier) }
}
}
fun KotlinType.isNullableUnderlyingType(): Boolean {
if (!isInlineClassType()) return false
val underlyingType = unsubstitutedUnderlyingType() ?: return false
return TypeUtils.isNullableType(underlyingType)
}
fun CallableDescriptor.isGetterOfUnderlyingPropertyOfInlineClass() =
this is PropertyGetterDescriptor && correspondingProperty.isUnderlyingPropertyOfInlineClass()
fun CallableDescriptor.isGetterOfUnderlyingPropertyOfMultiFieldValueClass() =
this is PropertyGetterDescriptor && correspondingProperty.isUnderlyingPropertyOfMultiFieldValueClass()
fun CallableDescriptor.isGetterOfUnderlyingPropertyOfValueClass() =
this is PropertyGetterDescriptor && correspondingProperty.isUnderlyingPropertyOfValueClass()
fun VariableDescriptor.isUnderlyingPropertyOfInlineClass(): Boolean =
extensionReceiverParameter == null &&
(containingDeclaration as? ClassDescriptor)?.inlineClassRepresentation?.underlyingPropertyName == this.name
fun VariableDescriptor.isUnderlyingPropertyOfMultiFieldValueClass(): Boolean =
extensionReceiverParameter == null &&
(containingDeclaration as? ClassDescriptor)?.multiFieldValueClassRepresentation?.containsPropertyWithName(this.name) == true
fun VariableDescriptor.isUnderlyingPropertyOfValueClass(): Boolean =
extensionReceiverParameter == null &&
(containingDeclaration as? ClassDescriptor)?.valueClassRepresentation?.containsPropertyWithName(this.name) == true