[FIR2IR] Generate bodies of synthetic data/value class members after f/o creation

This commit is contained in:
Dmitriy Novozhilov
2023-08-18 16:25:19 +03:00
committed by Space Team
parent 76d3c0e804
commit 39195146a9
4 changed files with 95 additions and 49 deletions
@@ -89,6 +89,20 @@ internal class ClassMemberGenerator(
else -> declaration.accept(visitor, null)
}
}
if (klass is FirRegularClass && (irClass.isValue || irClass.isData)) {
val dataClassMembersGenerator = DataClassMembersGenerator(components)
if (irClass.isSingleFieldValueClass) {
dataClassMembersGenerator.generateBodiesForSingleFieldValueClassMembers(klass, irClass)
}
if (irClass.isMultiFieldValueClass) {
dataClassMembersGenerator.generateBodiesForMultiFieldValueClassMembers(klass, irClass)
}
if (irClass.isData) {
dataClassMembersGenerator.generateBodiesForDataClassMembers(klass, irClass)
}
}
annotationGenerator.generate(irClass, klass)
if (irPrimaryConstructor != null) {
declarationStorage.leaveScope(irPrimaryConstructor.symbol)
@@ -56,17 +56,27 @@ import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrComponents by components {
fun generateSingleFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass): List<FirDeclaration> {
return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_SINGLE_FIELD_VALUE_CLASS_MEMBER)
.generate(klass)
return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_SINGLE_FIELD_VALUE_CLASS_MEMBER).generateHeaders()
}
fun generateBodiesForSingleFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass) {
MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_SINGLE_FIELD_VALUE_CLASS_MEMBER).generateBodies()
}
fun generateMultiFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass): List<FirDeclaration> {
return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER)
.generate(klass)
return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER).generateHeaders()
}
fun generateBodiesForMultiFieldValueClassMembers(klass: FirRegularClass, irClass: IrClass) {
MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER).generateBodies()
}
fun generateDataClassMembers(klass: FirRegularClass, irClass: IrClass): List<FirDeclaration> {
return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER).generate(klass)
return MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER).generateHeaders()
}
fun generateBodiesForDataClassMembers(klass: FirRegularClass, irClass: IrClass) {
MyDataClassMethodsGenerator(irClass, klass, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER).generateBodies()
}
fun generateDataClassComponentBody(irFunction: IrFunction, klass: FirRegularClass) {
@@ -179,12 +189,74 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon
UNDEFINED_OFFSET
)
fun generate(klass: FirRegularClass): List<FirDeclaration> {
fun generateHeaders(): List<FirDeclaration> {
val result = mutableListOf<FirDeclaration>()
val contributedSyntheticFunctions = calculateSyntheticFirFunctions()
val toStringContributedFunction = contributedSyntheticFunctions[TO_STRING]
if (toStringContributedFunction != null) {
result.add(toStringContributedFunction)
val toStringFunction = createSyntheticIrFunction(
TO_STRING,
toStringContributedFunction,
components.irBuiltIns.stringType,
)
irClass.declarations.add(toStringFunction)
}
val hashcodeNameContributedFunction = contributedSyntheticFunctions[HASHCODE_NAME]
if (hashcodeNameContributedFunction != null) {
result.add(hashcodeNameContributedFunction)
val hashCodeFunction = createSyntheticIrFunction(
HASHCODE_NAME,
hashcodeNameContributedFunction,
components.irBuiltIns.intType,
)
irClass.declarations.add(hashCodeFunction)
}
val equalsContributedFunction = contributedSyntheticFunctions[EQUALS]
if (equalsContributedFunction != null) {
result.add(equalsContributedFunction)
val equalsFunction = createSyntheticIrFunction(
EQUALS,
equalsContributedFunction,
components.irBuiltIns.booleanType,
otherParameterNeeded = true,
isOperator = true
)
irClass.declarations.add(equalsFunction)
}
return result
}
fun generateBodies() {
val propertyParametersCount = irClass.primaryConstructor?.explicitParameters?.size ?: 0
val properties = irClass.properties.filter { it.backingField != null }.take(propertyParametersCount).toList()
val result = mutableListOf<FirDeclaration>()
val contributedSyntheticFunctions = calculateSyntheticFirFunctions()
val toStringContributedFunction = contributedSyntheticFunctions[TO_STRING]
if (toStringContributedFunction != null) {
val toStringFunction = irClass.functions.first { it.name == TO_STRING && it.origin == origin }
irDataClassMembersGenerator.generateToStringMethod(toStringFunction, properties)
}
val hashcodeNameContributedFunction = contributedSyntheticFunctions[HASHCODE_NAME]
if (hashcodeNameContributedFunction != null) {
val hashCodeFunction = irClass.functions.first { it.name == HASHCODE_NAME && it.origin == origin }
irDataClassMembersGenerator.generateHashCodeMethod(hashCodeFunction, properties)
}
val equalsContributedFunction = contributedSyntheticFunctions[EQUALS]
if (equalsContributedFunction != null) {
val equalsFunction = irClass.functions.first { it.name == EQUALS && it.origin == origin }
irDataClassMembersGenerator.generateEqualsMethod(equalsFunction, properties)
}
}
private fun calculateSyntheticFirFunctions(): Map<Name, FirSimpleFunction> {
val scope = klass.unsubstitutedScope(
components.session,
components.scopeSession,
@@ -206,46 +278,7 @@ class DataClassMembersGenerator(val components: Fir2IrComponents) : Fir2IrCompon
}
}
}
val toStringContributedFunction = contributedSyntheticFunctions[TO_STRING]
if (toStringContributedFunction != null) {
result.add(toStringContributedFunction)
val toStringFunction = createSyntheticIrFunction(
TO_STRING,
toStringContributedFunction,
components.irBuiltIns.stringType,
)
irDataClassMembersGenerator.generateToStringMethod(toStringFunction, properties)
irClass.declarations.add(toStringFunction)
}
val hashcodeNameContributedFunction = contributedSyntheticFunctions[HASHCODE_NAME]
if (hashcodeNameContributedFunction != null) {
result.add(hashcodeNameContributedFunction)
val hashCodeFunction = createSyntheticIrFunction(
HASHCODE_NAME,
hashcodeNameContributedFunction,
components.irBuiltIns.intType,
)
irDataClassMembersGenerator.generateHashCodeMethod(hashCodeFunction, properties)
irClass.declarations.add(hashCodeFunction)
}
val equalsContributedFunction = contributedSyntheticFunctions[EQUALS]
if (equalsContributedFunction != null) {
result.add(equalsContributedFunction)
val equalsFunction = createSyntheticIrFunction(
EQUALS,
equalsContributedFunction,
components.irBuiltIns.booleanType,
otherParameterNeeded = true,
isOperator = true
)
irDataClassMembersGenerator.generateEqualsMethod(equalsFunction, properties)
irClass.declarations.add(equalsFunction)
}
return result
return contributedSyntheticFunctions
}
fun generateComponentBody(irFunction: IrFunction) {
-1
View File
@@ -1,5 +1,4 @@
// ISSUE: KT-52677
// IGNORE_BACKEND_K2: ANY
// MODULE: lib
// FILE: lib.kt
@@ -85,7 +85,7 @@ FILE fqName:<root> fileName:/kt52677.kt
$this: VALUE_PARAMETER name:<this> type:<root>.LoginSuccessPacket
BLOCK_BODY
RETURN type=kotlin.Nothing from='public open fun hashCode (): kotlin.Int declared in <root>.LoginSuccessPacket'
CALL 'public open fun hashCode (): kotlin.Int declared in kotlin.Any' type=kotlin.Int origin=null
CALL 'public open fun hashCode (): kotlin.Int declared in <root>.Uuid1' type=kotlin.Int origin=null
$this: GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:id type:@[MySerializable(c = ...)] <root>.Uuid1 visibility:private [final]' type=@[MySerializable(c = CLASS_REFERENCE 'CLASS OBJECT name:UuidSerializer modality:FINAL visibility:public superTypes:[<root>.MySerializer<@[MySerializable(c = ...)] <root>.Uuid1>]' type=kotlin.reflect.KClass<<root>.UuidSerializer>)] <root>.Uuid1 origin=null
receiver: GET_VAR '<this>: <root>.LoginSuccessPacket declared in <root>.LoginSuccessPacket.hashCode' type=<root>.LoginSuccessPacket origin=null
FUN GENERATED_DATA_CLASS_MEMBER name:equals visibility:public modality:OPEN <> ($this:<root>.LoginSuccessPacket, other:kotlin.Any?) returnType:kotlin.Boolean [operator]