FIR: fix body generation for data class's copy method

This commit is contained in:
Jinseong Jeon
2020-04-13 10:46:04 -07:00
committed by Mikhail Glukhikh
parent 948f9debdc
commit 08b91da6db
23 changed files with 162 additions and 32 deletions
@@ -28,6 +28,7 @@ FILE: constantValues.kt
}
public final fun copy(classId: R|ClassId| = this@R|/ClassLiteralValue|.R|/ClassLiteralValue.classId|, arrayNestedness: R|kotlin/Int| = this@R|/ClassLiteralValue|.R|/ClassLiteralValue.arrayNestedness|): R|ClassLiteralValue| {
^copy R|/ClassLiteralValue.ClassLiteralValue|(this@R|/ClassLiteralValue|.R|/ClassLiteralValue.classId|, this@R|/ClassLiteralValue|.R|/ClassLiteralValue.arrayNestedness|)
}
}
@@ -72,6 +73,7 @@ FILE: constantValues.kt
}
public final fun copy(value: R|ClassLiteralValue| = this@R|/KClassValue.Value.NormalClass|.R|/KClassValue.Value.NormalClass.value|): R|KClassValue.Value.NormalClass| {
^copy R|/KClassValue.Value.NormalClass.NormalClass|(this@R|/KClassValue.Value.NormalClass|.R|/KClassValue.Value.NormalClass.value|)
}
}
@@ -89,6 +91,7 @@ FILE: constantValues.kt
}
public final fun copy(type: R|KotlinType| = this@R|/KClassValue.Value.LocalClass|.R|/KClassValue.Value.LocalClass.type|): R|KClassValue.Value.LocalClass| {
^copy R|/KClassValue.Value.LocalClass.LocalClass|(this@R|/KClassValue.Value.LocalClass|.R|/KClassValue.Value.LocalClass.type|)
}
}
+1
View File
@@ -19,6 +19,7 @@ FILE: copy.kt
}
public final fun copy(x: R|kotlin/Int| = this@R|/Some|.R|/Some.x|, y: R|kotlin/String| = this@R|/Some|.R|/Some.y|): R|Some| {
^copy R|/Some.Some|(this@R|/Some|.R|/Some.x|, this@R|/Some|.R|/Some.y|)
}
}
@@ -56,6 +56,7 @@ FILE: incompatibleModifiers.kt
}
public final fun copy(i: R|kotlin/Int| = this@R|/H|.R|/H.i|): R|H| {
^copy R|/H.H|(this@R|/H|.R|/H.i|)
}
}
@@ -72,6 +73,7 @@ FILE: incompatibleModifiers.kt
}
public final fun copy(i: R|kotlin/Int| = this@R|/I|.R|/I.i|): R|I| {
^copy R|/I.I|(this@R|/I|.R|/I.i|)
}
}
@@ -88,6 +90,7 @@ FILE: incompatibleModifiers.kt
}
public final fun copy(i: R|kotlin/Int| = this@R|/J|.R|/J.i|): R|J| {
^copy R|/J.J|(this@R|/J|.R|/J.i|)
}
}
@@ -133,6 +136,7 @@ FILE: incompatibleModifiers.kt
}
public final fun copy(i: R|kotlin/Int| = this@R|/X.Y|.R|/X.Y.i|): R|X.Y| {
^copy R|/X.Y.Y|(this@R|/X.Y|.R|/X.Y.i|)
}
}
@@ -55,6 +55,7 @@ FILE: problems2.kt
}
public final fun copy(x: R|kotlin/Int| = this@R|/Some.WithPrimary|.R|/Some.WithPrimary.x|, arr: R|kotlin/Array<kotlin/String>?| = this@R|/Some.WithPrimary|.R|/Some.WithPrimary.arr|, s: R|kotlin/String?| = this@R|/Some.WithPrimary|.R|/Some.WithPrimary.s|): R|Some.WithPrimary| {
^copy R|/Some.WithPrimary.WithPrimary|(this@R|/Some.WithPrimary|.R|/Some.WithPrimary.x|, this@R|/Some.WithPrimary|.R|/Some.WithPrimary.arr|, this@R|/Some.WithPrimary|.R|/Some.WithPrimary.s|)
}
}
@@ -19,6 +19,7 @@ FILE: components.kt
}
public final fun copy(x: R|kotlin/Int| = this@R|/D|.R|/D.x|, y: R|kotlin/String| = this@R|/D|.R|/D.y|): R|D| {
^copy R|/D.D|(this@R|/D|.R|/D.x|, this@R|/D|.R|/D.y|)
}
}
@@ -642,23 +642,24 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
}
}
inner class DataClassMemberGenerator(
inner class DataClassMembersGenerator(
private val session: FirSession,
private val source: T,
private val classBuilder: AbstractFirRegularClassBuilder,
private val classTypeRef: FirTypeRef,
private val primaryConstructor: FirConstructor,
private val zippedParameters: List<Pair<T, FirProperty>>,
private val packageFqName: FqName,
private val classFqName: FqName,
) {
private val classTypeRef = primaryConstructor.returnTypeRef
fun generateMembers() {
fun generate() {
generateComponentFunctions()
generateCopyFunction()
// TODO: equals, hashCode, toString
// Refer to (IR utils or FIR backend) DataClassMembersGenerator for generating equals, hashCode, and toString
}
private inline fun generateComponentAccess(parameterSource: FirSourceElement?, firProperty: FirProperty) =
private fun generateComponentAccess(parameterSource: FirSourceElement?, firProperty: FirProperty) =
buildQualifiedAccessExpression {
source = parameterSource
dispatchReceiver = buildThisReceiverExpression {
@@ -684,10 +685,8 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
val target = FirFunctionTarget(labelName = null, isLambda = false)
val componentFunction = buildSimpleFunction {
source = parameterSource
session = this@DataClassMemberGenerator.session
returnTypeRef = buildImplicitTypeRef {
source = parameterSource
}
session = this@DataClassMembersGenerator.session
returnTypeRef = firProperty.returnTypeRef
receiverTypeRef = null
this.name = name
status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL)
@@ -709,10 +708,11 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
private val copyName = Name.identifier("copy")
private fun generateCopyFunction() {
val target = FirFunctionTarget(labelName = null, isLambda = false)
classBuilder.addDeclaration(
buildSimpleFunction {
source = this@DataClassMemberGenerator.source.toFirSourceElement()
session = this@DataClassMemberGenerator.session
source = this@DataClassMembersGenerator.source.toFirSourceElement()
session = this@DataClassMembersGenerator.session
returnTypeRef = classTypeRef
name = copyName
status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL)
@@ -722,7 +722,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
val parameterSource = ktParameter?.toFirSourceElement()
valueParameters += buildValueParameter {
source = parameterSource
session = this@DataClassMemberGenerator.session
session = this@DataClassMembersGenerator.session
returnTypeRef = firProperty.returnTypeRef
name = propertyName
symbol = FirVariableSymbol(propertyName)
@@ -733,8 +733,27 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
}
}
body = buildEmptyExpressionBlock()
},
// TODO: Handle generic types.
val initCallExpression = buildFunctionCall {
argumentList = buildArgumentList {
for ((ktParameter, firProperty) in zippedParameters) {
val parameterSource = ktParameter?.toFirSourceElement()
arguments += generateComponentAccess(parameterSource, firProperty)
}
}
calleeReference = buildResolvedNamedReference {
name = primaryConstructor.symbol.callableId.callableName
resolvedSymbol = primaryConstructor.symbol
}
}
val returnExpression = buildReturnExpression {
result = initCallExpression
this.target = target
}
body = buildSingleExpressionBlock(returnExpression)
}.also {
target.bind(it)
}
)
}
}
@@ -412,7 +412,6 @@ class DeclarationsConverter(
delegationSpecifiers?.let { superTypeRefs += it.superTypesRef }
when {
modifiers.isEnum() && (classKind == ClassKind.ENUM_CLASS) -> {
delegatedSuperTypeRef = buildResolvedTypeRef {
@@ -467,15 +466,15 @@ class DeclarationsConverter(
//parse data class
if (modifiers.isDataClass() && firPrimaryConstructor != null) {
val zippedParameters = properties.map { it.source?.lightNode!! to it }
DataClassMemberGenerator(
DataClassMembersGenerator(
baseSession,
classNode,
this,
firPrimaryConstructor.returnTypeRef,
firPrimaryConstructor,
zippedParameters,
context.packageFqName,
context.className
).generateMembers()
).generate()
}
if (modifiers.isEnum()) {
@@ -161,7 +161,7 @@ class RawFirBuilder(
delegatedSuperType: FirTypeRef,
delegatedSelfType: FirResolvedTypeRef,
owner: KtClassOrObject,
ownerClassBuilder: FirClassBuilder, hasPrimaryConstructor: Boolean,
ownerClassBuilder: FirClassBuilder, hasPrimaryConstructor: Boolean,
ownerTypeParameters: List<FirTypeParameterRef>
): FirDeclaration {
return when (this) {
@@ -693,15 +693,15 @@ class RawFirBuilder(
val zippedParameters = classOrObject.primaryConstructorParameters.zip(
declarations.filterIsInstance<FirProperty>(),
)
DataClassMemberGenerator(
DataClassMembersGenerator(
baseSession,
classOrObject,
this,
firPrimaryConstructor.returnTypeRef,
firPrimaryConstructor,
zippedParameters,
context.packageFqName,
context.className
).generateMembers()
).generate()
}
if (classOrObject.hasModifier(ENUM_KEYWORD)) {
@@ -26,6 +26,7 @@ FILE: annotated.kt
}
public final fun copy(): R|Two| {
^copy R|/Two.Two|()
}
}
@@ -13,19 +13,20 @@ FILE: destructuring.kt
public? final? val third: String = R|<local>/third|
public? get(): String
public final fun component1(): <implicit> {
public final fun component1(): Int {
^component1 this@R|/Some|.R|/Some.first|
}
public final fun component2(): <implicit> {
public final fun component2(): Double {
^component2 this@R|/Some|.R|/Some.second|
}
public final fun component3(): <implicit> {
public final fun component3(): String {
^component3 this@R|/Some|.R|/Some.third|
}
public final fun copy(first: Int = this@R|/Some|.R|/Some.first|, second: Double = this@R|/Some|.R|/Some.second|, third: String = this@R|/Some|.R|/Some.third|): R|Some| {
^copy R|/Some.Some|(this@R|/Some|.R|/Some.first|, this@R|/Some|.R|/Some.second|, this@R|/Some|.R|/Some.third|)
}
}
@@ -48,15 +48,16 @@ FILE: for.kt
public? final? val y: Int = R|<local>/y|
public? get(): Int
public final fun component1(): <implicit> {
public final fun component1(): Int {
^component1 this@R|/Some|.R|/Some.x|
}
public final fun component2(): <implicit> {
public final fun component2(): Int {
^component2 this@R|/Some|.R|/Some.y|
}
public final fun copy(x: Int = this@R|/Some|.R|/Some.x|, y: Int = this@R|/Some|.R|/Some.y|): R|Some| {
^copy R|/Some.Some|(this@R|/Some|.R|/Some.x|, this@R|/Some|.R|/Some.y|)
}
}
@@ -10,15 +10,16 @@ FILE: lambda.kt
public? final? val y: Int = R|<local>/y|
public? get(): Int
public final fun component1(): <implicit> {
public final fun component1(): Int {
^component1 this@R|/Tuple|.R|/Tuple.x|
}
public final fun component2(): <implicit> {
public final fun component2(): Int {
^component2 this@R|/Tuple|.R|/Tuple.y|
}
public final fun copy(x: Int = this@R|/Tuple|.R|/Tuple.x|, y: Int = this@R|/Tuple|.R|/Tuple.y|): R|Tuple| {
^copy R|/Tuple.Tuple|(this@R|/Tuple|.R|/Tuple.x|, this@R|/Tuple|.R|/Tuple.y|)
}
}