[KLIB] Fix annotation type deserialization

Instead of hardcoded `Unit` restore it basing on annotation class and
constructor's type arguments
This commit is contained in:
Roman Artemev
2021-03-10 21:47:03 +03:00
parent 607a598f1a
commit 0d8fff7186
2 changed files with 94 additions and 19 deletions
@@ -12,27 +12,19 @@ import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
class IrSimpleTypeImpl(
kotlinType: KotlinType?,
override val classifier: IrClassifierSymbol,
override val hasQuestionMark: Boolean,
override val arguments: List<IrTypeArgument>,
override val annotations: List<IrConstructorCall>,
override val abbreviation: IrTypeAbbreviation? = null
) : IrTypeBase(kotlinType), IrSimpleType {
abstract class IrAbstractSimpleType(kotlinType: KotlinType?) : IrTypeBase(kotlinType), IrSimpleType {
override val variance: Variance
get() = Variance.INVARIANT
constructor(
classifier: IrClassifierSymbol,
hasQuestionMark: Boolean,
arguments: List<IrTypeArgument>,
annotations: List<IrConstructorCall>,
abbreviation: IrTypeAbbreviation? = null
) : this(null, classifier, hasQuestionMark, arguments, annotations, abbreviation)
abstract override val classifier: IrClassifierSymbol
abstract override val hasQuestionMark: Boolean
abstract override val arguments: List<IrTypeArgument>
abstract override val annotations: List<IrConstructorCall>
abstract override val abbreviation: IrTypeAbbreviation?
override fun equals(other: Any?): Boolean =
other is IrSimpleTypeImpl &&
other is IrAbstractSimpleType &&
FqNameEqualityChecker.areEqual(classifier, other.classifier) &&
hasQuestionMark == other.hasQuestionMark &&
arguments == other.arguments
@@ -43,6 +35,41 @@ class IrSimpleTypeImpl(
arguments.hashCode()
}
abstract class IrDelegatedSimpleType : IrAbstractSimpleType(null) {
protected abstract val delegate: IrSimpleType
override val classifier: IrClassifierSymbol
get() = delegate.classifier
override val hasQuestionMark: Boolean
get() = delegate.hasQuestionMark
override val arguments: List<IrTypeArgument>
get() = delegate.arguments
override val abbreviation: IrTypeAbbreviation?
get() = delegate.abbreviation
override val annotations: List<IrConstructorCall>
get() = delegate.annotations
}
class IrSimpleTypeImpl(
kotlinType: KotlinType?,
override val classifier: IrClassifierSymbol,
override val hasQuestionMark: Boolean,
override val arguments: List<IrTypeArgument>,
override val annotations: List<IrConstructorCall>,
override val abbreviation: IrTypeAbbreviation? = null
) : IrAbstractSimpleType(kotlinType) {
constructor(
classifier: IrClassifierSymbol,
hasQuestionMark: Boolean,
arguments: List<IrTypeArgument>,
annotations: List<IrConstructorCall>,
abbreviation: IrTypeAbbreviation? = null
) : this(null, classifier, hasQuestionMark, arguments, annotations, abbreviation)
}
class IrSimpleTypeBuilder {
var kotlinType: KotlinType? = null
var classifier: IrClassifierSymbol? = null
@@ -18,6 +18,8 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlock as ProtoBlock
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBlockBody as ProtoBlockBody
import org.jetbrains.kotlin.backend.common.serialization.proto.IrBranch as ProtoBranch
@@ -34,10 +36,10 @@ import org.jetbrains.kotlin.backend.common.serialization.proto.IrDoWhile as Prot
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicMemberExpression as ProtoDynamicMemberExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicOperatorExpression as ProtoDynamicOperatorExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrEnumConstructorCall as ProtoEnumConstructorCall
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorCallExpression as ProtoErrorCallExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorExpression as ProtoErrorExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunctionExpression as ProtoFunctionExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorExpression as ProtoErrorExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorCallExpression as ProtoErrorCallExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrFunctionReference as ProtoFunctionReference
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetClass as ProtoGetClass
import org.jetbrains.kotlin.backend.common.serialization.proto.IrGetEnumValue as ProtoGetEnumValue
@@ -188,7 +190,53 @@ class IrBodyDeserializer(
}
fun deserializeAnnotation(proto: ProtoConstructorCall): IrConstructorCall {
return deserializeConstructorCall(proto, 0, 0, builtIns.unitType) // TODO: need a proper deserialization here
// TODO: probably a bit more abstraction possible here up to `IrMemberAccessExpression`
// but at this point further complexization looks overengineered
class IrAnnotationType : IrDelegatedSimpleType() {
var irConstructorCall: IrConstructorCall? = null
override val delegate: IrSimpleType by lazy { resolveType() }
private fun resolveType(): IrSimpleType {
val constructorCall = irConstructorCall ?: error("irConstructorCall should not be null at this stage")
irConstructorCall = null
val klass = constructorCall.symbol.owner.parentAsClass
val typeParameters = extractTypeParameters(klass)
val typeArguments = ArrayList<IrTypeArgument>(typeParameters.size)
val typeParameterSymbols = ArrayList<IrTypeParameterSymbol>(typeParameters.size)
val rawType = with(IrSimpleTypeBuilder()) {
arguments = typeParameters.run {
mapTo(ArrayList(size)) {
classifier = it.symbol
buildTypeProjection()
}
}
classifier = klass.symbol
buildSimpleType()
}
for (i in typeParameters.indices) {
val typeParameter = typeParameters[i]
val callTypeArgument = constructorCall.getTypeArgument(i) ?: error("No type argument for id $i")
val typeArgument = makeTypeProjection(callTypeArgument, typeParameter.variance)
typeArguments.add(typeArgument)
typeParameterSymbols.add(typeParameter.symbol)
}
val substitutor = IrTypeSubstitutor(typeParameterSymbols, typeArguments, builtIns)
return substitutor.substitute(rawType) as IrSimpleType
}
}
val irType = IrAnnotationType()
// TODO: use real coordinates
return deserializeConstructorCall(proto, 0, 0, irType).also { irType.irConstructorCall = it }
}
fun deserializeConstructorCall(proto: ProtoConstructorCall, start: Int, end: Int, type: IrType): IrConstructorCall {