IR: more consolidation of synthetic member generation for data class.
This commit is contained in:
committed by
Dmitriy Novozhilov
parent
7f02d57d88
commit
9f1ecadd65
+17
-82
@@ -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(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user