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,104 +642,101 @@ 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()
source = parameterSource // TODO: equals, hashCode, toString
dispatchReceiver = buildThisReceiverExpression {
calleeReference = buildImplicitThisReference {
boundSymbol = firClassBuilder.symbol
}
typeRef = firPrimaryConstructor.returnTypeRef
}
calleeReference = buildResolvedNamedReference {
source = parameterSource
this.name = firProperty.name
resolvedSymbol = firProperty.symbol
}
}
this.target = target
}
body = buildSingleExpressionBlock(returnExpression)
}.also {
target.bind(it)
}
firClassBuilder.addDeclaration(componentFunction)
} }
}
private val copyName = Name.identifier("copy") private inline fun generateComponentAccess(parameterSource: FirSourceElement?, firProperty: FirProperty) =
buildQualifiedAccessExpression {
fun List<Pair<T, FirProperty>>.generateCopyFunction( source = parameterSource
session: FirSession, dispatchReceiver = buildThisReceiverExpression {
classOrObject: T, calleeReference = buildImplicitThisReference {
classBuilder: AbstractFirRegularClassBuilder, boundSymbol = classBuilder.symbol
packageFqName: FqName,
classFqName: FqName,
firPrimaryConstructor: FirConstructor,
) {
classBuilder.addDeclaration(
buildSimpleFunction {
source = classOrObject?.toFirSourceElement()
this.session = session
returnTypeRef = firPrimaryConstructor.returnTypeRef
name = copyName
status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL)
symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, copyName))
for ((ktParameter, firProperty) in this@generateCopyFunction) {
val propertyName = firProperty.name
val parameterSource = ktParameter?.toFirSourceElement()
valueParameters += buildValueParameter {
source = parameterSource
this.session = session
returnTypeRef = firProperty.returnTypeRef
name = propertyName
symbol = FirVariableSymbol(propertyName)
defaultValue = buildQualifiedAccessExpression {
source = parameterSource
dispatchReceiver = buildThisReceiverExpression {
calleeReference = buildImplicitThisReference {
boundSymbol = classBuilder.symbol
}
typeRef = firPrimaryConstructor.returnTypeRef
}
calleeReference = buildResolvedNamedReference {
source = parameterSource
this.name = propertyName
resolvedSymbol = firProperty.symbol
}
}
isCrossinline = false
isNoinline = false
isVararg = false
} }
typeRef = classTypeRef
} }
calleeReference = buildResolvedNamedReference {
source = parameterSource
this.name = firProperty.name
resolvedSymbol = firProperty.symbol
}
}
body = buildEmptyExpressionBlock() 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
}
body = buildSingleExpressionBlock(returnExpression)
}.also {
target.bind(it)
}
classBuilder.addDeclaration(componentFunction)
}
}
private val copyName = Name.identifier("copy")
private fun generateCopyFunction() {
classBuilder.addDeclaration(
buildSimpleFunction {
source = this@DataClassMemberGenerator.source.toFirSourceElement()
session = this@DataClassMemberGenerator.session
returnTypeRef = classTypeRef
name = copyName
status = FirDeclarationStatusImpl(Visibilities.PUBLIC, Modality.FINAL)
symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, copyName))
for ((ktParameter, firProperty) in zippedParameters) {
val propertyName = firProperty.name
val parameterSource = ktParameter?.toFirSourceElement()
valueParameters += buildValueParameter {
source = parameterSource
session = this@DataClassMemberGenerator.session
returnTypeRef = firProperty.returnTypeRef
name = propertyName
symbol = FirVariableSymbol(propertyName)
defaultValue = generateComponentAccess(parameterSource, firProperty)
isCrossinline = false
isNoinline = false
isVararg = false
}
}
body = buildEmptyExpressionBlock()
},
)
}
} }
private fun FirVariable<*>.toQualifiedAccess(): FirQualifiedAccessExpression = buildQualifiedAccessExpression { private fun FirVariable<*>.toQualifiedAccess(): FirQualifiedAccessExpression = buildQualifiedAccessExpression {
@@ -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)) {