FIR deserializer: fix parameter shift for constructor of inner classes and enums

#KT-39837 Fixed
This commit is contained in:
Jinseong Jeon
2020-06-30 11:50:25 -07:00
committed by Dmitriy Novozhilov
parent 8e24256f95
commit c9e423bf64
5 changed files with 42 additions and 24 deletions
@@ -15,7 +15,7 @@ public final enum class E : R|kotlin/Enum<test/E>| {
public final val y: R|kotlin/Int| public final val y: R|kotlin/Int|
public get(): R|kotlin/Int| public get(): R|kotlin/Int|
private constructor(x: R|kotlin/String|, y: R|kotlin/Int|): R|test/E| private constructor(@R|test/A|() x: R|kotlin/String|, @R|test/B|() y: R|kotlin/Int|): R|test/E|
public final static fun values(): R|kotlin/Array<test/E>| { public final static fun values(): R|kotlin/Array<test/E>| {
} }
@@ -17,10 +17,7 @@ import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.load.kotlin.MemberSignature import org.jetbrains.kotlin.load.kotlin.MemberSignature
import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.NameResolver import org.jetbrains.kotlin.metadata.deserialization.*
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
import org.jetbrains.kotlin.metadata.deserialization.getExtensionOrNull
import org.jetbrains.kotlin.metadata.deserialization.hasReceiver
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -145,28 +142,34 @@ class JvmBinaryAnnotationDeserializer(
containerSource: DeserializedContainerSource?, containerSource: DeserializedContainerSource?,
callableProto: MessageLite, callableProto: MessageLite,
valueParameterProto: ProtoBuf.ValueParameter, valueParameterProto: ProtoBuf.ValueParameter,
classProto: ProtoBuf.Class?,
nameResolver: NameResolver, nameResolver: NameResolver,
typeTable: TypeTable, typeTable: TypeTable,
kind: CallableKind, kind: CallableKind,
parameterIndex: Int, parameterIndex: Int,
): List<FirAnnotationCall> { ): List<FirAnnotationCall> {
val methodSignature = getCallableSignature(callableProto, nameResolver, typeTable, kind) ?: return emptyList() val methodSignature = getCallableSignature(callableProto, nameResolver, typeTable, kind) ?: return emptyList()
val index = parameterIndex + computeJvmParameterIndexShift(callableProto) val index = parameterIndex + computeJvmParameterIndexShift(classProto, callableProto)
val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(methodSignature, index) val paramSignature = MemberSignature.fromMethodSignatureAndParameterIndex(methodSignature, index)
return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, paramSignature) return findJvmBinaryClassAndLoadMemberAnnotations(containerSource, paramSignature)
} }
/* private fun computeJvmParameterIndexShift(classProto: ProtoBuf.Class?, message: MessageLite): Int {
* TODO: Support container proto and fix index shift for
* constructors of inner classes and enums
*
* See [AbstractBinaryClassAnnotationAndConstantLoader]
*/
private fun computeJvmParameterIndexShift(message: MessageLite): Int {
return when (message) { return when (message) {
is ProtoBuf.Function -> if (message.hasReceiver()) 1 else 0 is ProtoBuf.Function -> if (message.hasReceiver()) 1 else 0
is ProtoBuf.Property -> if (message.hasReceiver()) 1 else 0 is ProtoBuf.Property -> if (message.hasReceiver()) 1 else 0
is ProtoBuf.Constructor -> 0 is ProtoBuf.Constructor -> {
assert(classProto != null) {
"Constructor call without information about enclosing Class: $message"
}
val kind = Flags.CLASS_KIND.get(classProto!!.flags) ?: ProtoBuf.Class.Kind.CLASS
val isInner = Flags.IS_INNER.get(classProto.flags)
when {
kind == ProtoBuf.Class.Kind.ENUM_CLASS -> 2
isInner -> 1
else -> 0
}
}
else -> throw UnsupportedOperationException("Unsupported message: ${message::class.java}") else -> throw UnsupportedOperationException("Unsupported message: ${message::class.java}")
} }
} }
@@ -135,6 +135,7 @@ abstract class AbstractAnnotationDeserializer(
containerSource: DeserializedContainerSource?, containerSource: DeserializedContainerSource?,
callableProto: MessageLite, callableProto: MessageLite,
valueParameterProto: ProtoBuf.ValueParameter, valueParameterProto: ProtoBuf.ValueParameter,
classProto: ProtoBuf.Class?,
nameResolver: NameResolver, nameResolver: NameResolver,
typeTable: TypeTable, typeTable: TypeTable,
kind: CallableKind, kind: CallableKind,
@@ -100,7 +100,6 @@ fun deserializeClassToSymbol(
typeParameters += context.typeDeserializer.ownTypeParameters.map { it.fir } typeParameters += context.typeDeserializer.ownTypeParameters.map { it.fir }
if (status.isInner) if (status.isInner)
typeParameters += parentContext?.allTypeParameters?.map { buildOuterClassTypeParameterRef { this.symbol = it } }.orEmpty() typeParameters += parentContext?.allTypeParameters?.map { buildOuterClassTypeParameterRef { this.symbol = it } }.orEmpty()
// annotations += context.annotationDeserializer.loadClassAnnotations(classProto, context.nameResolver)
val typeDeserializer = context.typeDeserializer val typeDeserializer = context.typeDeserializer
val classDeserializer = context.memberDeserializer val classDeserializer = context.memberDeserializer
@@ -114,12 +113,21 @@ fun deserializeClassToSymbol(
buildResolvedTypeRef { type = it } buildResolvedTypeRef { type = it }
} }
addDeclarations(classProto.functionList.map(classDeserializer::loadFunction)) addDeclarations(
addDeclarations(classProto.propertyList.map(classDeserializer::loadProperty)) classProto.functionList.map {
classDeserializer.loadFunction(it, classProto)
}
)
addDeclarations(
classProto.propertyList.map {
classDeserializer.loadProperty(it, classProto)
}
)
addDeclarations( addDeclarations(
classProto.constructorList.map { classProto.constructorList.map {
classDeserializer.loadConstructor(it, this) classDeserializer.loadConstructor(it, classProto, this)
} }
) )
@@ -167,7 +175,8 @@ fun deserializeClassToSymbol(
ClassId.fromString(nameResolver.getQualifiedClassName(nameIndex)) ClassId.fromString(nameResolver.getQualifiedClassName(nameIndex))
} }
} }
(it.annotations as MutableList<FirAnnotationCall>) += context.annotationDeserializer.loadClassAnnotations(classProto, context.nameResolver) (it.annotations as MutableList<FirAnnotationCall>) +=
context.annotationDeserializer.loadClassAnnotations(classProto, context.nameResolver)
} }
} }
@@ -177,7 +177,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
} }
} }
fun loadProperty(proto: ProtoBuf.Property): FirProperty { fun loadProperty(proto: ProtoBuf.Property, classProto: ProtoBuf.Class? = null): FirProperty {
val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags) val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags)
val callableName = c.nameResolver.getName(proto.name) val callableName = c.nameResolver.getName(proto.name)
val symbol = FirPropertySymbol(CallableId(c.packageFqName, c.relativeClassName, callableName)) val symbol = FirPropertySymbol(CallableId(c.packageFqName, c.relativeClassName, callableName))
@@ -237,7 +237,8 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
valueParameters += local.memberDeserializer.valueParameters( valueParameters += local.memberDeserializer.valueParameters(
listOf(proto.setterValueParameter), listOf(proto.setterValueParameter),
proto, proto,
AbstractAnnotationDeserializer.CallableKind.PROPERTY_SETTER AbstractAnnotationDeserializer.CallableKind.PROPERTY_SETTER,
classProto
) )
} }
} else { } else {
@@ -287,7 +288,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
} }
} }
fun loadFunction(proto: ProtoBuf.Function, byteContent: ByteArray? = null): FirSimpleFunction { fun loadFunction(proto: ProtoBuf.Function, classProto: ProtoBuf.Class? = null): FirSimpleFunction {
val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags) val flags = if (proto.hasFlags()) proto.flags else loadOldFlags(proto.oldFlags)
val receiverAnnotations = val receiverAnnotations =
@@ -329,7 +330,8 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
valueParameters += local.memberDeserializer.valueParameters( valueParameters += local.memberDeserializer.valueParameters(
proto.valueParameterList, proto.valueParameterList,
proto, proto,
AbstractAnnotationDeserializer.CallableKind.OTHERS AbstractAnnotationDeserializer.CallableKind.OTHERS,
classProto
) )
annotations += annotations +=
c.annotationDeserializer.loadFunctionAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable) c.annotationDeserializer.loadFunctionAnnotations(c.containerSource, proto, local.nameResolver, local.typeTable)
@@ -344,7 +346,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
return simpleFunction return simpleFunction
} }
fun loadConstructor(proto: ProtoBuf.Constructor, classBuilder: FirRegularClassBuilder): FirConstructor { fun loadConstructor(proto: ProtoBuf.Constructor, classProto: ProtoBuf.Class, classBuilder: FirRegularClassBuilder): FirConstructor {
val flags = proto.flags val flags = proto.flags
val relativeClassName = c.relativeClassName!! val relativeClassName = c.relativeClassName!!
val symbol = FirConstructorSymbol(CallableId(c.packageFqName, relativeClassName, relativeClassName.shortName())) val symbol = FirConstructorSymbol(CallableId(c.packageFqName, relativeClassName, relativeClassName.shortName()))
@@ -383,6 +385,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
proto.valueParameterList, proto.valueParameterList,
proto, proto,
AbstractAnnotationDeserializer.CallableKind.OTHERS, AbstractAnnotationDeserializer.CallableKind.OTHERS,
classProto,
addDefaultValue = classBuilder.symbol.classId == StandardClassIds.Enum addDefaultValue = classBuilder.symbol.classId == StandardClassIds.Enum
) )
annotations += annotations +=
@@ -401,6 +404,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
valueParameters: List<ProtoBuf.ValueParameter>, valueParameters: List<ProtoBuf.ValueParameter>,
callableProto: MessageLite, callableProto: MessageLite,
callableKind: AbstractAnnotationDeserializer.CallableKind, callableKind: AbstractAnnotationDeserializer.CallableKind,
classProto: ProtoBuf.Class?,
addDefaultValue: Boolean = false addDefaultValue: Boolean = false
): List<FirValueParameter> { ): List<FirValueParameter> {
return valueParameters.mapIndexed { index, proto -> return valueParameters.mapIndexed { index, proto ->
@@ -423,6 +427,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
c.containerSource, c.containerSource,
callableProto, callableProto,
proto, proto,
classProto,
c.nameResolver, c.nameResolver,
c.typeTable, c.typeTable,
callableKind, callableKind,