FIR: refactor member generations for data class

This commit is contained in:
Jinseong Jeon
2020-04-07 23:31:44 -07:00
committed by Mikhail Glukhikh
parent d4cbfcb79e
commit 948f9debdc
3 changed files with 106 additions and 105 deletions
@@ -642,37 +642,30 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
} }
} }
fun List<Pair<T, FirProperty>>.generateComponentFunctions( inner class DataClassMemberGenerator(
session: FirSession, firClassBuilder: AbstractFirRegularClassBuilder, packageFqName: FqName, classFqName: FqName, private val session: FirSession,
firPrimaryConstructor: FirConstructor, private val source: T,
private val classBuilder: AbstractFirRegularClassBuilder,
private val classTypeRef: FirTypeRef,
private val zippedParameters: List<Pair<T, FirProperty>>,
private val packageFqName: FqName,
private val classFqName: FqName,
) { ) {
var componentIndex = 1
for ((sourceNode, firProperty) in this) {
if (!firProperty.isVal && !firProperty.isVar) continue
val name = Name.identifier("component$componentIndex")
componentIndex++
val parameterSource = sourceNode?.toFirSourceElement()
val target = FirFunctionTarget(labelName = null, isLambda = false)
val componentFunction = buildSimpleFunction {
source = parameterSource
this.session = session
returnTypeRef = buildImplicitTypeRef {
source = parameterSource
}
receiverTypeRef = null
this.name = name
this.status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL)
this.symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, name))
val returnExpression = buildReturnExpression { fun generateMembers() {
source = parameterSource generateComponentFunctions()
result = buildQualifiedAccessExpression { generateCopyFunction()
// TODO: equals, hashCode, toString
}
private inline fun generateComponentAccess(parameterSource: FirSourceElement?, firProperty: FirProperty) =
buildQualifiedAccessExpression {
source = parameterSource source = parameterSource
dispatchReceiver = buildThisReceiverExpression { dispatchReceiver = buildThisReceiverExpression {
calleeReference = buildImplicitThisReference { calleeReference = buildImplicitThisReference {
boundSymbol = firClassBuilder.symbol boundSymbol = classBuilder.symbol
} }
typeRef = firPrimaryConstructor.returnTypeRef typeRef = classTypeRef
} }
calleeReference = buildResolvedNamedReference { calleeReference = buildResolvedNamedReference {
source = parameterSource source = parameterSource
@@ -680,57 +673,60 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
resolvedSymbol = firProperty.symbol resolvedSymbol = firProperty.symbol
} }
} }
private fun generateComponentFunctions() {
var componentIndex = 1
for ((sourceNode, firProperty) in zippedParameters) {
if (!firProperty.isVal && !firProperty.isVar) continue
val name = Name.identifier("component$componentIndex")
componentIndex++
val parameterSource = sourceNode?.toFirSourceElement()
val target = FirFunctionTarget(labelName = null, isLambda = false)
val componentFunction = buildSimpleFunction {
source = parameterSource
session = this@DataClassMemberGenerator.session
returnTypeRef = buildImplicitTypeRef {
source = parameterSource
}
receiverTypeRef = null
this.name = name
status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL)
symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, name))
val returnExpression = buildReturnExpression {
source = parameterSource
result = generateComponentAccess(parameterSource, firProperty)
this.target = target this.target = target
} }
body = buildSingleExpressionBlock(returnExpression) body = buildSingleExpressionBlock(returnExpression)
}.also { }.also {
target.bind(it) target.bind(it)
} }
firClassBuilder.addDeclaration(componentFunction) classBuilder.addDeclaration(componentFunction)
} }
} }
private val copyName = Name.identifier("copy") private val copyName = Name.identifier("copy")
fun List<Pair<T, FirProperty>>.generateCopyFunction( private fun generateCopyFunction() {
session: FirSession,
classOrObject: T,
classBuilder: AbstractFirRegularClassBuilder,
packageFqName: FqName,
classFqName: FqName,
firPrimaryConstructor: FirConstructor,
) {
classBuilder.addDeclaration( classBuilder.addDeclaration(
buildSimpleFunction { buildSimpleFunction {
source = classOrObject?.toFirSourceElement() source = this@DataClassMemberGenerator.source.toFirSourceElement()
this.session = session session = this@DataClassMemberGenerator.session
returnTypeRef = firPrimaryConstructor.returnTypeRef returnTypeRef = classTypeRef
name = copyName name = copyName
status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL) status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL)
symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, copyName)) symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, copyName))
for ((ktParameter, firProperty) in this@generateCopyFunction) { for ((ktParameter, firProperty) in zippedParameters) {
val propertyName = firProperty.name val propertyName = firProperty.name
val parameterSource = ktParameter?.toFirSourceElement() val parameterSource = ktParameter?.toFirSourceElement()
valueParameters += buildValueParameter { valueParameters += buildValueParameter {
source = parameterSource source = parameterSource
this.session = session session = this@DataClassMemberGenerator.session
returnTypeRef = firProperty.returnTypeRef returnTypeRef = firProperty.returnTypeRef
name = propertyName name = propertyName
symbol = FirVariableSymbol(propertyName) symbol = FirVariableSymbol(propertyName)
defaultValue = buildQualifiedAccessExpression { defaultValue = generateComponentAccess(parameterSource, firProperty)
source = parameterSource
dispatchReceiver = buildThisReceiverExpression {
calleeReference = buildImplicitThisReference {
boundSymbol = classBuilder.symbol
}
typeRef = firPrimaryConstructor.returnTypeRef
}
calleeReference = buildResolvedNamedReference {
source = parameterSource
this.name = propertyName
resolvedSymbol = firProperty.symbol
}
}
isCrossinline = false isCrossinline = false
isNoinline = false isNoinline = false
isVararg = false isVararg = false
@@ -741,6 +737,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
}, },
) )
} }
}
private fun FirVariable<*>.toQualifiedAccess(): FirQualifiedAccessExpression = buildQualifiedAccessExpression { private fun FirVariable<*>.toQualifiedAccess(): FirQualifiedAccessExpression = buildQualifiedAccessExpression {
calleeReference = buildResolvedNamedReference { calleeReference = buildResolvedNamedReference {
@@ -467,13 +467,15 @@ class DeclarationsConverter(
//parse data class //parse data class
if (modifiers.isDataClass() && firPrimaryConstructor != null) { if (modifiers.isDataClass() && firPrimaryConstructor != null) {
val zippedParameters = properties.map { it.source?.lightNode!! to it } val zippedParameters = properties.map { it.source?.lightNode!! to it }
zippedParameters.generateComponentFunctions( DataClassMemberGenerator(
baseSession, this, context.packageFqName, context.className, firPrimaryConstructor baseSession,
) classNode,
zippedParameters.generateCopyFunction( this,
baseSession, classNode, this, context.packageFqName, context.className, firPrimaryConstructor firPrimaryConstructor.returnTypeRef,
) zippedParameters,
// TODO: equals, hashCode, toString context.packageFqName,
context.className
).generateMembers()
} }
if (modifiers.isEnum()) { if (modifiers.isEnum()) {
@@ -693,13 +693,15 @@ class RawFirBuilder(
val zippedParameters = classOrObject.primaryConstructorParameters.zip( val zippedParameters = classOrObject.primaryConstructorParameters.zip(
declarations.filterIsInstance<FirProperty>(), declarations.filterIsInstance<FirProperty>(),
) )
zippedParameters.generateComponentFunctions( DataClassMemberGenerator(
baseSession, this, context.packageFqName, context.className, firPrimaryConstructor, baseSession,
) classOrObject,
zippedParameters.generateCopyFunction( this,
baseSession, classOrObject, this, context.packageFqName, context.className, firPrimaryConstructor, firPrimaryConstructor.returnTypeRef,
) zippedParameters,
// TODO: equals, hashCode, toString context.packageFqName,
context.className
).generateMembers()
} }
if (classOrObject.hasModifier(ENUM_KEYWORD)) { if (classOrObject.hasModifier(ENUM_KEYWORD)) {