IR: more consolidation of synthetic member generation for data class.

This commit is contained in:
Jinseong Jeon
2020-04-15 13:45:54 -07:00
committed by Dmitriy Novozhilov
parent 7f02d57d88
commit 9f1ecadd65
22 changed files with 354 additions and 403 deletions
@@ -16,23 +16,17 @@
package org.jetbrains.kotlin.psi2ir.generators
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.common.DataClassMethodGenerator
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.mapTypeParameters
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator
import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi2ir.endOffsetOrUndefined
import org.jetbrains.kotlin.psi2ir.startOffsetOrUndefined
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
@@ -58,38 +52,6 @@ class DataClassMembersGenerator(
returnType = function.returnType!!.toIrType()
}
private inner class MemberFunctionBuilder(
val irClass: IrClass,
val function: FunctionDescriptor,
val origin: IrDeclarationOrigin,
startOffset: Int = UNDEFINED_OFFSET,
endOffset: Int = UNDEFINED_OFFSET,
val irFunction: IrFunction = declareSimpleFunction(startOffset, endOffset, origin, function)
) : IrBlockBodyBuilder(context, Scope(irFunction.symbol), startOffset, endOffset) {
inline fun addToClass(builder: MemberFunctionBuilder.(IrFunction) -> Unit): IrFunction {
irFunction.buildWithScope {
builder(irFunction)
irFunction.body = doBuild()
}
irClass.declarations.add(irFunction)
return irFunction
}
fun putDefault(parameter: ValueParameterDescriptor, value: IrExpression) {
irFunction.putDefault(parameter, irExprBody(value))
}
fun irThis(): IrExpression {
val irDispatchReceiverParameter = irFunction.dispatchReceiverParameter!!
return IrGetValueImpl(
startOffset, endOffset,
irDispatchReceiverParameter.type,
irDispatchReceiverParameter.symbol
)
}
}
private inner class MyDataClassMethodGenerator(
ktClassOrObject: KtClassOrObject,
val irClass: IrClass,
@@ -104,41 +66,30 @@ class DataClassMembersGenerator(
FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irFunction)
}
override fun getBackingField(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrField? =
parameter?.let {
val property = getOrFail(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter)
return getBackingField(property)
}
override fun transform(typeParameterDescriptor: TypeParameterDescriptor): IrType =
typeParameterDescriptor.defaultType.toIrType()
override fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression, descriptor: CallableDescriptor) {
irMemberAccessExpression.commitSubstituted(descriptor)
}
}
private inline fun buildMember(
function: FunctionDescriptor,
psiElement: PsiElement? = null,
body: MemberFunctionBuilder.(IrFunction) -> Unit
) {
MemberFunctionBuilder(
irClass, function, origin,
psiElement.startOffsetOrUndefined, psiElement.endOffsetOrUndefined
).addToClass { irFunction ->
irFunction.buildWithScope {
FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irFunction)
body(irFunction)
}
}
}
override fun generateComponentFunction(function: FunctionDescriptor, parameter: ValueParameterDescriptor) {
if (!irClass.isData) return
val ktParameter = DescriptorToSourceUtils.descriptorToDeclaration(parameter)
?: throw AssertionError("No definition for data class constructor parameter $parameter")
buildMember(function, ktParameter) {
+irReturn(irGetField(irThis(), getBackingField(parameter)))
}
}
private fun getBackingField(parameter: ValueParameterDescriptor): IrField {
val property = getOrFail(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter)
return irDataClassMembersGenerator.getBackingField(property)
val backingField = irDataClassMembersGenerator.getBackingField(parameter, null) ?: return
irDataClassMembersGenerator.generateComponentFunction(
function, backingField, ktParameter.startOffset, ktParameter.endOffset
)
}
override fun generateCopyFunction(function: FunctionDescriptor, constructorParameters: List<KtParameter>) {
@@ -148,23 +99,7 @@ class DataClassMembersGenerator(
?: throw AssertionError("Data class should have a primary constructor: $classDescriptor")
val constructorSymbol = context.symbolTable.referenceConstructor(dataClassConstructor)
buildMember(function, declaration) { irFunction ->
function.valueParameters.forEach { parameter ->
putDefault(parameter, irGetField(irThis(), getBackingField(parameter)))
}
+irReturn(
irCall(
constructorSymbol,
dataClassConstructor.returnType.toIrType()
).apply {
mapTypeParameters { it.defaultType.toIrType() }
mapValueParameters {
val irValueParameter = irFunction.valueParameters[it.index]
irGet(irValueParameter.type, irValueParameter.symbol)
}
}
)
}
irDataClassMembersGenerator.generateCopyFunction(function, constructorSymbol)
}
override fun generateEqualsMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) =
@@ -6,43 +6,20 @@
package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.IrBlockBodyBuilder
import org.jetbrains.kotlin.ir.builders.IrGeneratorContext
import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.builders.irAs
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irCallOp
import org.jetbrains.kotlin.ir.builders.irConcat
import org.jetbrains.kotlin.ir.builders.irEqeqeq
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.builders.irGetField
import org.jetbrains.kotlin.ir.builders.irIfNull
import org.jetbrains.kotlin.ir.builders.irIfThenReturnFalse
import org.jetbrains.kotlin.ir.builders.irIfThenReturnTrue
import org.jetbrains.kotlin.ir.builders.irInt
import org.jetbrains.kotlin.ir.builders.irNotEquals
import org.jetbrains.kotlin.ir.builders.irNotIs
import org.jetbrains.kotlin.ir.builders.irReturn
import org.jetbrains.kotlin.ir.builders.irReturnTrue
import org.jetbrains.kotlin.ir.builders.irString
import org.jetbrains.kotlin.ir.builders.irTemporary
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrField
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.mapTypeParameters
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
@@ -70,13 +47,16 @@ abstract class DataClassMembersGenerator(
val irFunction: IrFunction
) : IrBlockBodyBuilder(context, Scope(irFunction.symbol), startOffset, endOffset) {
inline fun addToClass(builder: MemberFunctionBuilder.(IrFunction) -> Unit): IrFunction {
build(builder)
irClass.declarations.add(irFunction)
return irFunction
}
inline fun build(builder: MemberFunctionBuilder.(IrFunction) -> Unit) {
irFunction.buildWithScope {
builder(irFunction)
irFunction.body = doBuild()
}
irClass.declarations.add(irFunction)
return irFunction
}
fun irThis(): IrExpression {
@@ -97,6 +77,29 @@ abstract class DataClassMembersGenerator(
)
}
fun putDefault(parameter: ValueParameterDescriptor, value: IrExpression) {
irFunction.putDefault(parameter, irExprBody(value))
}
fun generateComponentFunction(irField: IrField) {
+irReturn(irGetField(irThis(), irField))
}
fun generateCopyFunction(constructorSymbol: IrConstructorSymbol) {
+irReturn(
irCall(
constructorSymbol,
irClass.defaultType
).apply {
mapTypeParameters(::transform)
mapValueParameters {
val irValueParameter = irFunction.valueParameters[it.index]
irGet(irValueParameter.type, irValueParameter.symbol)
}
}
)
}
fun generateEqualsMethodBody(properties: List<PropertyDescriptor>) {
val irType = irClass.defaultType
@@ -231,7 +234,7 @@ abstract class DataClassMembersGenerator(
endOffset: Int = UNDEFINED_OFFSET,
body: MemberFunctionBuilder.(IrFunction) -> Unit
) {
MemberFunctionBuilder(startOffset, endOffset, irFunction).addToClass { function ->
MemberFunctionBuilder(startOffset, endOffset, irFunction).build { function ->
function.buildWithScope {
generateSyntheticFunctionParameterDeclarations(function)
body(function)
@@ -239,7 +242,45 @@ abstract class DataClassMembersGenerator(
}
}
// Entry for psi2ir
// Entry for psi2ir
fun generateComponentFunction(function: FunctionDescriptor, irField: IrField, startOffset: Int, endOffset: Int) {
buildMember(function, startOffset, endOffset) {
generateComponentFunction(irField)
}
}
// Entry for fir2ir
fun generateComponentFunction(irFunction: IrFunction, irField: IrField, startOffset: Int, endOffset: Int) {
buildMember(irFunction, startOffset, endOffset) {
generateComponentFunction(irField)
}
}
abstract fun getBackingField(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrField?
abstract fun transform(typeParameterDescriptor: TypeParameterDescriptor): IrType
// Entry for psi2ir
fun generateCopyFunction(function: FunctionDescriptor, constructorSymbol: IrConstructorSymbol) {
buildMember(function, irClass.startOffset, irClass.endOffset) {
function.valueParameters.forEach { parameter ->
putDefault(parameter, irGetField(irThis(), getBackingField(parameter, null)!!))
}
generateCopyFunction(constructorSymbol)
}
}
// Entry for fir2ir
fun generateCopyFunction(irFunction: IrFunction, constructorSymbol: IrConstructorSymbol) {
buildMember(irFunction, irClass.startOffset, irClass.endOffset) {
irFunction.valueParameters.forEach { irValueParameter ->
irValueParameter.defaultValue = irExprBody(irGetField(irThis(), getBackingField(null, irValueParameter)!!))
}
generateCopyFunction(constructorSymbol)
}
}
// Entry for psi2ir
fun generateEqualsMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
buildMember(function, irClass.startOffset, irClass.endOffset) {
generateEqualsMethodBody(properties)
@@ -315,4 +356,3 @@ abstract class DataClassMembersGenerator(
}
}
}