[FIR] Don't force calculation of return type in substitution scope

This commit is contained in:
Dmitriy Novozhilov
2020-10-14 18:26:43 +03:00
parent 06981fc0af
commit f9faa5be64
5 changed files with 222 additions and 52 deletions
@@ -0,0 +1,17 @@
FILE: implicitTypeInFakeOverride.kt
public final fun <K> extract(x: R|Out<K>|): R|T| {
^extract R|<local>/x|.R|/Out.get|()
}
public final class Out<out T> : R|kotlin/Any| {
public constructor<out T>(x: R|T|): R|Out<T>| {
super<R|kotlin/Any|>()
}
public final val x: R|T| = R|<local>/x|
public get(): R|T|
public final fun get(): R|T| {
^get this@R|/Out|.R|/Out.x|
}
}
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2020 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.fir.scopes
import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes
import org.jetbrains.kotlin.fir.declarations.FirDeclarationDataKey
import org.jetbrains.kotlin.fir.declarations.FirDeclarationDataRegistry
import org.jetbrains.kotlin.fir.declarations.FirTypedDeclaration
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
abstract class FakeOverrideTypeCalculator {
abstract fun computeReturnType(declaration: FirTypedDeclaration): ConeKotlinType?
class DoNothing : FakeOverrideTypeCalculator() {
override fun computeReturnType(declaration: FirTypedDeclaration): ConeKotlinType? {
return declaration.returnTypeRef.coneTypeSafe()
}
}
}
class ForcedFakeOverrideTypeCalculator : FakeOverrideTypeCalculator() {
override fun computeReturnType(declaration: FirTypedDeclaration): ConeKotlinType {
declaration.returnTypeRef.coneTypeSafe<ConeKotlinType>()?.let { return it }
val (substitutor, baseSymbol) = declaration.attributes.fakeOverrideSubstitution ?: error("")
val baseDeclaration = baseSymbol.fir as FirTypedDeclaration
val returnType = computeReturnType(baseDeclaration)
declaration.attributes.fakeOverrideSubstitution = null
return substitutor.substituteOrSelf(returnType)
}
}
// ---------------------------------------------------------------------------------------------------------------------------------------
object FakeOverrideSubstitutionKey : FirDeclarationDataKey()
var FirDeclarationAttributes.fakeOverrideSubstitution: FakeOverrideSubstitution? by FirDeclarationDataRegistry.attributesAccessor(
FakeOverrideSubstitutionKey
)
data class FakeOverrideSubstitution(
val substitutor: ConeSubstitutor,
val baseSymbol: AbstractFirBasedSymbol<*>
)
@@ -13,12 +13,14 @@ import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.chain
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FakeOverrideSubstitution
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.runIf
class FirClassSubstitutionScope(
private val session: FirSession,
@@ -126,13 +128,13 @@ class FirClassSubstitutionScope(
}
if (skipPrivateMembers && member.visibility == Visibilities.Private) return original
val (newTypeParameters, newReceiverType, newReturnType, newSubstitutor) = createSubstitutedData(member)
val (newTypeParameters, newReceiverType, newReturnType, newSubstitutor, fakeOverrideSubstitution) = createSubstitutedData(member)
val newParameterTypes = member.valueParameters.map {
it.returnTypeRef.coneType.substitute(newSubstitutor)
}
if (newReceiverType == null && newReturnType == null && newParameterTypes.all { it == null } &&
newTypeParameters === member.typeParameters) {
newTypeParameters === member.typeParameters && fakeOverrideSubstitution == null) {
return original
}
@@ -150,7 +152,8 @@ class FirClassSubstitutionScope(
newParameterTypes,
newTypeParameters as List<FirTypeParameter>,
derivedClassId,
makeExpect
makeExpect,
fakeOverrideSubstitution
)
}
@@ -158,7 +161,7 @@ class FirClassSubstitutionScope(
if (substitutor == ConeSubstitutor.Empty) return original
val constructor = original.fir
val (newTypeParameters, _, newReturnType, newSubstitutor) = createSubstitutedData(constructor)
val (newTypeParameters, _, newReturnType, newSubstitutor, fakeOverrideSubstitution) = createSubstitutedData(constructor)
val newParameterTypes = constructor.valueParameters.map {
it.returnTypeRef.coneType.substitute(newSubstitutor)
}
@@ -168,7 +171,7 @@ class FirClassSubstitutionScope(
}
return FirFakeOverrideGenerator.createFakeOverrideConstructor(
FirConstructorSymbol(original.callableId, overriddenSymbol = original),
session, constructor, newReturnType, newParameterTypes, newTypeParameters, makeExpect
session, constructor, newReturnType, newParameterTypes, newTypeParameters, makeExpect, fakeOverrideSubstitution
).symbol
}
@@ -177,7 +180,7 @@ class FirClassSubstitutionScope(
val member = original.fir
if (skipPrivateMembers && member.visibility == Visibilities.Private) return original
val (newTypeParameters, newReceiverType, newReturnType, _) = createSubstitutedData(member)
val (newTypeParameters, newReceiverType, newReturnType, _, fakeOverrideSubstitution) = createSubstitutedData(member)
if (newReceiverType == null &&
newReturnType == null && newTypeParameters === member.typeParameters
) {
@@ -193,7 +196,8 @@ class FirClassSubstitutionScope(
newReturnType,
newTypeParameters as List<FirTypeParameter>,
derivedClassId,
makeExpect
makeExpect,
fakeOverrideSubstitution
)
}
@@ -201,7 +205,8 @@ class FirClassSubstitutionScope(
val typeParameters: List<FirTypeParameterRef>,
val receiverType: ConeKotlinType?,
val returnType: ConeKotlinType?,
val substitutor: ConeSubstitutor
val substitutor: ConeSubstitutor,
val fakeOverrideSubstitution: FakeOverrideSubstitution?
)
private fun createSubstitutedData(member: FirCallableMemberDeclaration<*>): SubstitutedData {
@@ -214,9 +219,10 @@ class FirClassSubstitutionScope(
val receiverType = member.receiverTypeRef?.coneType
val newReceiverType = receiverType?.substitute(substitutor)
val returnType = member.returnTypeRef.coneType
val newReturnType = returnType.substitute(substitutor)
return SubstitutedData(newTypeParameters, newReceiverType, newReturnType, substitutor)
val returnType = member.returnTypeRef.coneTypeSafe<ConeKotlinType>()
val fakeOverrideSubstitution = runIf(returnType == null) { FakeOverrideSubstitution(substitutor, member.symbol) }
val newReturnType = returnType?.substitute(substitutor)
return SubstitutedData(newTypeParameters, newReceiverType, newReturnType, substitutor, fakeOverrideSubstitution)
}
private fun createFakeOverrideField(original: FirFieldSymbol): FirFieldSymbol {
@@ -224,8 +230,9 @@ class FirClassSubstitutionScope(
val member = original.fir
if (skipPrivateMembers && member.visibility == Visibilities.Private) return original
val returnType = member.returnTypeRef.coneType
val newReturnType = returnType.substitute() ?: return original
val returnType = member.returnTypeRef.coneTypeSafe<ConeKotlinType>()
// TODO: do we have fields with implicit type?
val newReturnType = returnType?.substitute() ?: return original
return FirFakeOverrideGenerator.createFakeOverrideField(session, member, original, newReturnType, derivedClassId)
}
@@ -235,8 +242,9 @@ class FirClassSubstitutionScope(
val member = original.fir as FirSyntheticProperty
if (skipPrivateMembers && member.visibility == Visibilities.Private) return original
val returnType = member.returnTypeRef.coneType
val newReturnType = returnType.substitute()
val returnType = member.returnTypeRef.coneTypeSafe<ConeKotlinType>()
val fakeOverrideSubstitution = runIf(returnType == null) { FakeOverrideSubstitution(substitutor, original) }
val newReturnType = returnType?.substitute()
val newParameterTypes = member.getter.valueParameters.map {
it.returnTypeRef.coneType.substitute()
@@ -246,7 +254,14 @@ class FirClassSubstitutionScope(
return original
}
return FirFakeOverrideGenerator.createFakeOverrideAccessor(session, member, original, newReturnType, newParameterTypes)
return FirFakeOverrideGenerator.createFakeOverrideAccessor(
session,
member,
original,
newReturnType,
newParameterTypes,
fakeOverrideSubstitution
)
}
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
@@ -16,12 +16,16 @@ import org.jetbrains.kotlin.fir.declarations.synthetic.buildSyntheticProperty
import org.jetbrains.kotlin.fir.resolve.substitution.ChainedSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
import org.jetbrains.kotlin.fir.scopes.FakeOverrideSubstitution
import org.jetbrains.kotlin.fir.scopes.fakeOverrideSubstitution
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.utils.addToStdlib.runIf
object FirFakeOverrideGenerator {
fun createFakeOverrideFunction(
@@ -33,14 +37,16 @@ object FirFakeOverrideGenerator {
newParameterTypes: List<ConeKotlinType?>? = null,
newTypeParameters: List<FirTypeParameter>? = null,
derivedClassId: ClassId? = null,
isExpect: Boolean = baseFunction.isExpect
isExpect: Boolean = baseFunction.isExpect,
fakeOverrideSubstitution: FakeOverrideSubstitution? = null
): FirNamedFunctionSymbol {
val symbol = FirNamedFunctionSymbol(
CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseFunction.name),
isFakeOverride = true, overriddenSymbol = baseSymbol
)
createFakeOverrideFunction(
symbol, session, baseFunction, newReceiverType, newReturnType, newParameterTypes, newTypeParameters, isExpect
symbol, session, baseFunction, newReceiverType, newReturnType,
newParameterTypes, newTypeParameters, isExpect, fakeOverrideSubstitution
)
return symbol
}
@@ -54,6 +60,7 @@ object FirFakeOverrideGenerator {
newParameterTypes: List<ConeKotlinType?>?,
newTypeParameters: List<FirTypeParameter>?,
isExpect: Boolean = baseFunction.isExpect,
fakeOverrideSubstitution: FakeOverrideSubstitution?,
): FirSimpleFunction {
// TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl
// As second alternative, we can invent some light-weight kind of FirRegularClass
@@ -66,7 +73,8 @@ object FirFakeOverrideGenerator {
newParameterTypes,
newTypeParameters,
newReceiverType,
newReturnType
newReturnType,
fakeOverrideSubstitution = fakeOverrideSubstitution
)
}
@@ -82,6 +90,7 @@ object FirFakeOverrideGenerator {
newReturnType: ConeKotlinType? = null,
newModality: Modality? = null,
newVisibility: Visibility? = null,
fakeOverrideSubstitution: FakeOverrideSubstitution? = null
): FirSimpleFunction {
return buildSimpleFunction {
source = baseFunction.source
@@ -93,7 +102,8 @@ object FirFakeOverrideGenerator {
resolvePhase = baseFunction.resolvePhase
typeParameters += configureAnnotationsTypeParametersAndSignature(
session, baseFunction, newParameterTypes, newTypeParameters, newReceiverType, newReturnType
session, baseFunction, newParameterTypes,
newTypeParameters, newReceiverType, newReturnType, fakeOverrideSubstitution
).filterIsInstance<FirTypeParameter>()
}
}
@@ -105,7 +115,8 @@ object FirFakeOverrideGenerator {
newReturnType: ConeKotlinType?,
newParameterTypes: List<ConeKotlinType?>?,
newTypeParameters: List<FirTypeParameterRef>?,
isExpect: Boolean
isExpect: Boolean,
fakeOverrideSubstitution: FakeOverrideSubstitution?
): FirConstructor {
// TODO: consider using here some light-weight functions instead of pseudo-real FirMemberFunctionImpl
// As second alternative, we can invent some light-weight kind of FirRegularClass
@@ -119,7 +130,7 @@ object FirFakeOverrideGenerator {
resolvePhase = baseConstructor.resolvePhase
typeParameters += configureAnnotationsTypeParametersAndSignature(
session, baseConstructor, newParameterTypes, newTypeParameters, newReceiverType = null, newReturnType
session, baseConstructor, newParameterTypes, newTypeParameters, newReceiverType = null, newReturnType, fakeOverrideSubstitution
)
}
}
@@ -130,11 +141,19 @@ object FirFakeOverrideGenerator {
newParameterTypes: List<ConeKotlinType?>?,
newTypeParameters: List<FirTypeParameterRef>?,
newReceiverType: ConeKotlinType?,
newReturnType: ConeKotlinType?
newReturnType: ConeKotlinType?,
fakeOverrideSubstitution: FakeOverrideSubstitution?
): List<FirTypeParameterRef> {
return when {
baseFunction.typeParameters.isEmpty() -> {
configureAnnotationsAndSignature(session, baseFunction, newParameterTypes, newReceiverType, newReturnType)
configureAnnotationsAndSignature(
session,
baseFunction,
newParameterTypes,
newReceiverType,
newReturnType,
fakeOverrideSubstitution
)
emptyList()
}
newTypeParameters == null -> {
@@ -144,14 +163,33 @@ object FirFakeOverrideGenerator {
val copiedParameterTypes = baseFunction.valueParameters.map {
substitutor.substituteOrNull(it.returnTypeRef.coneType)
}
val (copiedReceiverType, copiedReturnType) = substituteReceiverAndReturnType(
val symbol = baseFunction.symbol
val (copiedReceiverType, possibleReturnType) = substituteReceiverAndReturnType(
baseFunction as FirCallableMemberDeclaration<*>, newReceiverType, newReturnType, substitutor
)
configureAnnotationsAndSignature(session, baseFunction, copiedParameterTypes, copiedReceiverType, copiedReturnType)
val (copiedReturnType, newFakeOverrideSubstitution) = when (possibleReturnType) {
is Maybe.Value -> possibleReturnType.value to null
else -> null to FakeOverrideSubstitution(substitutor, symbol)
}
configureAnnotationsAndSignature(
session,
baseFunction,
copiedParameterTypes,
copiedReceiverType,
copiedReturnType,
newFakeOverrideSubstitution
)
copiedTypeParameters
}
else -> {
configureAnnotationsAndSignature(session, baseFunction, newParameterTypes, newReceiverType, newReturnType)
configureAnnotationsAndSignature(
session,
baseFunction,
newParameterTypes,
newReceiverType,
newReturnType,
fakeOverrideSubstitution
)
newTypeParameters
}
}
@@ -162,10 +200,22 @@ object FirFakeOverrideGenerator {
baseFunction: FirFunction<*>,
newParameterTypes: List<ConeKotlinType?>?,
newReceiverType: ConeKotlinType?,
newReturnType: ConeKotlinType?
newReturnType: ConeKotlinType?,
fakeOverrideSubstitution: FakeOverrideSubstitution?
) {
annotations += baseFunction.annotations
returnTypeRef = replaceReturnTypeIfResolved(baseFunction, newReturnType)
@Suppress("NAME_SHADOWING")
val fakeOverrideSubstitution = fakeOverrideSubstitution ?: runIf(baseFunction.returnTypeRef is FirImplicitTypeRef) {
FakeOverrideSubstitution(ConeSubstitutor.Empty, baseFunction.symbol)
}
if (fakeOverrideSubstitution != null) {
returnTypeRef = buildImplicitTypeRef()
attributes.fakeOverrideSubstitution = fakeOverrideSubstitution
} else {
returnTypeRef = baseFunction.returnTypeRef.withReplacedReturnType(newReturnType)
}
if (this is FirSimpleFunctionBuilder) {
receiverTypeRef = baseFunction.receiverTypeRef?.withReplacedConeType(newReceiverType)
@@ -181,14 +231,6 @@ object FirFakeOverrideGenerator {
}
}
private fun replaceReturnTypeIfResolved(
base: FirCallableDeclaration<*>,
newReturnType: ConeKotlinType?
): FirTypeRef = if (base.returnTypeRef is FirResolvedTypeRef)
base.returnTypeRef.withReplacedConeType(newReturnType)
else
base.returnTypeRef
fun createFakeOverrideProperty(
session: FirSession,
baseProperty: FirProperty,
@@ -197,7 +239,8 @@ object FirFakeOverrideGenerator {
newReturnType: ConeKotlinType? = null,
newTypeParameters: List<FirTypeParameter>? = null,
derivedClassId: ClassId? = null,
isExpect: Boolean = baseProperty.isExpect
isExpect: Boolean = baseProperty.isExpect,
fakeOverrideSubstitution: FakeOverrideSubstitution? = null
): FirPropertySymbol {
val symbol = FirPropertySymbol(
CallableId(derivedClassId ?: baseSymbol.callableId.classId!!, baseProperty.name),
@@ -205,7 +248,8 @@ object FirFakeOverrideGenerator {
)
createCopyForFirProperty(
symbol, baseProperty, session, isExpect,
newTypeParameters, newReceiverType, newReturnType
newTypeParameters, newReceiverType, newReturnType,
fakeOverrideSubstitution = fakeOverrideSubstitution
)
return symbol
}
@@ -220,6 +264,7 @@ object FirFakeOverrideGenerator {
newReturnType: ConeKotlinType? = null,
newModality: Modality? = null,
newVisibility: Visibility? = null,
fakeOverrideSubstitution: FakeOverrideSubstitution? = null
): FirProperty {
return buildProperty {
source = baseProperty.source
@@ -236,7 +281,8 @@ object FirFakeOverrideGenerator {
baseProperty,
newTypeParameters,
newReceiverType,
newReturnType
newReturnType,
fakeOverrideSubstitution
)
}
}
@@ -245,25 +291,30 @@ object FirFakeOverrideGenerator {
baseProperty: FirProperty,
newTypeParameters: List<FirTypeParameter>?,
newReceiverType: ConeKotlinType?,
newReturnType: ConeKotlinType?
newReturnType: ConeKotlinType?,
fakeOverrideSubstitution: FakeOverrideSubstitution?
): List<FirTypeParameter> {
return when {
baseProperty.typeParameters.isEmpty() -> {
configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType)
configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType, fakeOverrideSubstitution)
emptyList()
}
newTypeParameters == null -> {
val (copiedTypeParameters, substitutor) = createNewTypeParametersAndSubstitutor(
baseProperty, ConeSubstitutor.Empty
)
val (copiedReceiverType, copiedReturnType) = substituteReceiverAndReturnType(
val (copiedReceiverType, possibleReturnType) = substituteReceiverAndReturnType(
baseProperty, newReceiverType, newReturnType, substitutor
)
configureAnnotationsAndSignature(baseProperty, copiedReceiverType, copiedReturnType)
val (copiedReturnType, newFakeOverrideSubstitution) = when (possibleReturnType) {
is Maybe.Value -> possibleReturnType.value to null
else -> null to FakeOverrideSubstitution(substitutor, baseProperty.symbol)
}
configureAnnotationsAndSignature(baseProperty, copiedReceiverType, copiedReturnType, newFakeOverrideSubstitution)
copiedTypeParameters.filterIsInstance<FirTypeParameter>()
}
else -> {
configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType)
configureAnnotationsAndSignature(baseProperty, newReceiverType, newReturnType, fakeOverrideSubstitution)
newTypeParameters
}
}
@@ -274,27 +325,40 @@ object FirFakeOverrideGenerator {
newReceiverType: ConeKotlinType?,
newReturnType: ConeKotlinType?,
substitutor: ConeSubstitutor
): Pair<ConeKotlinType?, ConeKotlinType?> {
): Pair<ConeKotlinType?, Maybe<ConeKotlinType?>> {
val copiedReceiverType = newReceiverType?.let {
substitutor.substituteOrNull(it)
} ?: baseCallable.receiverTypeRef?.let {
substitutor.substituteOrNull(it.coneType)
}
val copiedReturnType = newReturnType?.let {
substitutor.substituteOrNull(it)
} ?: baseCallable.returnTypeRef.let {
substitutor.substituteOrNull(it.coneType)
val coneType = baseCallable.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: return copiedReceiverType to Maybe.Nothing
substitutor.substituteOrNull(coneType)
}
return copiedReceiverType to copiedReturnType
return copiedReceiverType to Maybe.Value(copiedReturnType)
}
private fun FirPropertyBuilder.configureAnnotationsAndSignature(
baseProperty: FirProperty,
newReceiverType: ConeKotlinType?,
newReturnType: ConeKotlinType?
newReturnType: ConeKotlinType?,
fakeOverrideSubstitution: FakeOverrideSubstitution?
) {
annotations += baseProperty.annotations
returnTypeRef = replaceReturnTypeIfResolved(baseProperty, newReturnType)
@Suppress("NAME_SHADOWING")
val fakeOverrideSubstitution = fakeOverrideSubstitution ?: runIf(baseProperty.returnTypeRef is FirImplicitTypeRef) {
FakeOverrideSubstitution(ConeSubstitutor.Empty, baseProperty.symbol)
}
if (fakeOverrideSubstitution != null) {
returnTypeRef = buildImplicitTypeRef()
attributes.fakeOverrideSubstitution = fakeOverrideSubstitution
} else {
returnTypeRef = baseProperty.returnTypeRef.withReplacedReturnType(newReturnType)
}
receiverTypeRef = baseProperty.receiverTypeRef?.withReplacedConeType(newReceiverType)
}
@@ -329,7 +393,8 @@ object FirFakeOverrideGenerator {
baseProperty: FirSyntheticProperty,
baseSymbol: FirAccessorSymbol,
newReturnType: ConeKotlinType?,
newParameterTypes: List<ConeKotlinType?>?
newParameterTypes: List<ConeKotlinType?>?,
fakeOverrideSubstitution: FakeOverrideSubstitution?
): FirAccessorSymbol {
val functionSymbol = FirNamedFunctionSymbol(baseSymbol.accessorId)
val function = createFakeOverrideFunction(
@@ -339,7 +404,8 @@ object FirFakeOverrideGenerator {
newReceiverType = null,
newReturnType,
newParameterTypes,
newTypeParameters = null
newTypeParameters = null,
fakeOverrideSubstitution = fakeOverrideSubstitution
)
return buildSyntheticProperty {
this.session = session
@@ -417,4 +483,9 @@ object FirFakeOverrideGenerator {
ChainedSubstitutor(substitutor, additionalSubstitutor)
)
}
private sealed class Maybe<out A> {
class Value<out A>(val value: A) : Maybe<A>()
object Nothing : Maybe<kotlin.Nothing>()
}
}
@@ -39,6 +39,11 @@ object FirDeclarationDataRegistry : TypeRegistry<FirDeclarationDataKey, Any>() {
return DeclarationDataAccessor(generateNullableAccessor(kClass), kClass)
}
fun <K : FirDeclarationDataKey, V : Any> attributesAccessor(key: K): ReadWriteProperty<FirDeclarationAttributes, V?> {
val kClass = key::class
return AttributeDataAccessor(generateNullableAccessor(kClass), kClass)
}
private class DeclarationDataAccessor<V : Any>(
val dataAccessor: NullableArrayMapAccessor<FirDeclarationDataKey, Any, V>,
val key: KClass<out FirDeclarationDataKey>
@@ -51,4 +56,17 @@ object FirDeclarationDataRegistry : TypeRegistry<FirDeclarationDataKey, Any>() {
thisRef.attributes[key] = value
}
}
private class AttributeDataAccessor<V : Any>(
val dataAccessor: NullableArrayMapAccessor<FirDeclarationDataKey, Any, V>,
val key: KClass<out FirDeclarationDataKey>
) : ReadWriteProperty<FirDeclarationAttributes, V?> {
override fun getValue(thisRef: FirDeclarationAttributes, property: KProperty<*>): V? {
return dataAccessor.getValue(thisRef, property)
}
override fun setValue(thisRef: FirDeclarationAttributes, property: KProperty<*>, value: V?) {
thisRef[key] = value
}
}
}