Use FIR metadata in FIR2IR data class member generator (KT-38156)

This commit is contained in:
Mikhail Glukhikh
2020-04-16 09:50:07 +03:00
parent c6c848f929
commit c2c85365e6
6 changed files with 65 additions and 19 deletions
@@ -126,11 +126,12 @@ internal class ClassMemberGenerator(
irFunction.body = IrSyntheticBodyImpl(startOffset, endOffset, kind)
}
irFunction.parent is IrClass && irFunction.parentAsClass.isData -> {
val classId = firFunction?.symbol?.callableId?.classId
when {
DataClassMembersGenerator.isComponentN(irFunction) ->
DataClassMembersGenerator(components).generateDataClassComponentBody(irFunction)
DataClassMembersGenerator(components).generateDataClassComponentBody(irFunction, classId!!)
DataClassMembersGenerator.isCopy(irFunction) ->
DataClassMembersGenerator(components).generateDataClassCopyBody(irFunction)
DataClassMembersGenerator(components).generateDataClassCopyBody(irFunction, classId!!)
else ->
irFunction.body = firFunction?.body?.let { visitor.convertToIrBlockBody(it) }
}
@@ -7,12 +7,24 @@ package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.FirMetadataSource
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.declareThisReceiverParameter
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBooleanTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitIntTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitNullableAnyTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitStringTypeRef
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.IrGeneratorContextBase
@@ -25,6 +37,8 @@ import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
class DataClassMembersGenerator(val components: Fir2IrComponents) {
@@ -32,17 +46,17 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
// TODO: generateInlineClassMembers
fun generateDataClassMembers(klass: FirClass<*>, irClass: IrClass): List<Name> =
MyDataClassMethodsGenerator(irClass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER).generate(klass)
MyDataClassMethodsGenerator(irClass, klass.symbol.classId, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER).generate(klass)
fun generateDataClassComponentBody(irFunction: IrFunction) =
MyDataClassMethodsGenerator(irFunction.parentAsClass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER)
fun generateDataClassComponentBody(irFunction: IrFunction, classId: ClassId) =
MyDataClassMethodsGenerator(irFunction.parentAsClass, classId, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER)
.generateComponentBody(irFunction)
fun generateDataClassCopyBody(irFunction: IrFunction) =
MyDataClassMethodsGenerator(irFunction.parentAsClass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER)
fun generateDataClassCopyBody(irFunction: IrFunction, classId: ClassId) =
MyDataClassMethodsGenerator(irFunction.parentAsClass, classId, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER)
.generateCopyBody(irFunction)
private inner class MyDataClassMethodsGenerator(val irClass: IrClass, val origin: IrDeclarationOrigin) {
private inner class MyDataClassMethodsGenerator(val irClass: IrClass, val classId: ClassId, val origin: IrDeclarationOrigin) {
private val irDataClassMembersGenerator = object : DataClassMembersGenerator(
IrGeneratorContextBase(components.irBuiltIns),
components.symbolTable,
@@ -137,11 +151,7 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
val equalsFunction = createSyntheticIrFunction(
equalsName,
components.irBuiltIns.booleanType,
).apply {
valueParameters = listOf(
createSyntheticIrParameter(this, Name.identifier("other"), components.irBuiltIns.anyNType)
)
}
) { createSyntheticIrParameter(it, Name.identifier("other"), components.irBuiltIns.anyNType) }
irDataClassMembersGenerator.generateEqualsMethod(equalsFunction, properties)
irClass.declarations.add(equalsFunction)
}
@@ -184,7 +194,11 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
fun generateCopyBody(irFunction: IrFunction) =
irDataClassMembersGenerator.generateCopyFunction(irFunction, irClass.primaryConstructor!!.symbol)
private fun createSyntheticIrFunction(name: Name, returnType: IrType): IrFunction {
private fun createSyntheticIrFunction(
name: Name,
returnType: IrType,
valueParameterBuilder: (IrFunction) -> IrValueParameter? = { null }
): IrFunction {
val functionDescriptor = WrappedSimpleFunctionDescriptor()
val thisReceiverDescriptor = WrappedValueParameterDescriptor()
return components.symbolTable.declareSimpleFunction(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, functionDescriptor) { symbol ->
@@ -205,7 +219,39 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) {
isFakeOverride = false,
isOperator = false
).apply {
metadata = MetadataSource.Function(functionDescriptor)
val irValueParameter = valueParameterBuilder(this)?.let {
this.valueParameters = listOf(it)
it
}
metadata = FirMetadataSource.Function(
buildSimpleFunction {
this.name = name
this.symbol = FirNamedFunctionSymbol(CallableId(classId.packageFqName, classId.relativeClassName, name))
this.status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL)
this.session = components.session
this.returnTypeRef = when (returnType) {
components.irBuiltIns.booleanType -> FirImplicitBooleanTypeRef(null)
components.irBuiltIns.intType -> FirImplicitIntTypeRef(null)
components.irBuiltIns.stringType -> FirImplicitStringTypeRef(null)
else -> throw AssertionError("Should not be here")
}
if (irValueParameter != null) {
this.valueParameters.add(
buildValueParameter {
this.name = irValueParameter.name
this.session = components.session
this.returnTypeRef = FirImplicitNullableAnyTypeRef(null)
this.symbol = FirVariableSymbol(irValueParameter.name)
isCrossinline = false
isNoinline = false
isVararg = false
}
)
}
},
descriptor
)
}
}.apply {
parent = irClass
@@ -132,7 +132,9 @@ class FirBasedClassCodegen internal constructor(
}
null -> {
}
else -> error("Incorrect metadata source $metadata for:\n${method.dump()}")
else -> {
error("Incorrect metadata source $metadata for:\n${method.dump()}")
}
}
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE