Merge pull request #9681 from smowton/smowton/fix/reintroduce-obinit

Kotlin: reintroduce obinit when we have multiple secondary constructors and no primary
This commit is contained in:
Chris Smowton
2022-06-24 10:25:24 +01:00
committed by GitHub
5 changed files with 82 additions and 3 deletions

View File

@@ -371,6 +371,27 @@ open class KotlinFileExtractor(
tw.writeHasLocation(stmtId, locId)
}
fun extractObinitFunction(c: IrClass, parentId: Label<out DbClassorinterface>) {
// add method:
val obinitLabel = getObinitLabel(c)
val obinitId = tw.getLabelFor<DbMethod>(obinitLabel)
val returnType = useType(pluginContext.irBuiltIns.unitType, TypeContext.RETURN)
tw.writeMethods(obinitId, "<obinit>", "<obinit>()", returnType.javaResult.id, parentId, obinitId)
tw.writeMethodsKotlinType(obinitId, returnType.kotlinResult.id)
val locId = tw.getLocation(c)
tw.writeHasLocation(obinitId, locId)
addModifiers(obinitId, "private")
// add body:
val blockId = tw.getFreshIdLabel<DbBlock>()
tw.writeStmts_block(blockId, obinitId, 0, obinitId)
tw.writeHasLocation(blockId, locId)
extractDeclInitializers(c.declarations, false) { Pair(blockId, obinitId) }
}
fun extractClassSource(c: IrClass, extractDeclarations: Boolean, extractStaticInitializer: Boolean, extractPrivateMembers: Boolean, extractFunctionBodies: Boolean): Label<out DbClassorinterface> {
with("class source", c) {
DeclarationStackAdjuster(c).use {
@@ -425,6 +446,9 @@ open class KotlinFileExtractor(
addModifiers(instance.id, "public", "static", "final")
tw.writeClass_object(id.cast<DbClass>(), instance.id)
}
if (extractFunctionBodies && needsObinitFunction(c)) {
extractObinitFunction(c, id)
}
extractClassModifiers(c, id)
extractClassSupertypes(c, id, inReceiverContext = true) // inReceiverContext = true is specified to force extraction of member prototypes of base types
@@ -2105,6 +2129,22 @@ open class KotlinFileExtractor(
enclosingStmt: Label<out DbStmt>
): Label<DbNewexpr> = extractNewExpr(useFunction<DbConstructor>(calledConstructor, constructorTypeArgs), constructedType, locId, parent, idx, callable, enclosingStmt)
private fun needsObinitFunction(c: IrClass) = c.primaryConstructor == null && c.constructors.count() > 1
private fun getObinitLabel(c: IrClass) = getFunctionLabel(
c,
null,
"<obinit>",
listOf(),
pluginContext.irBuiltIns.unitType,
null,
functionTypeParameters = listOf(),
classTypeArgsIncludingOuterClasses = listOf(),
overridesCollectionsMethod = false,
javaSignature = null,
addParameterWildcardsByDefault = false
)
private fun extractConstructorCall(
e: IrFunctionAccessExpression,
parent: Label<out DbExprparent>,
@@ -2434,13 +2474,29 @@ open class KotlinFileExtractor(
loopIdMap.remove(e)
}
is IrInstanceInitializerCall -> {
val stmtParent = parent.stmt(e, callable)
val irConstructor = declarationStack.peek() as? IrConstructor
if (irConstructor == null) {
logger.errorElement("IrInstanceInitializerCall outside constructor", e)
return
}
extractInstanceInitializerBlock(stmtParent, irConstructor)
if (needsObinitFunction(irConstructor.parentAsClass)) {
val exprParent = parent.expr(e, callable)
val id = tw.getFreshIdLabel<DbMethodaccess>()
val type = useType(pluginContext.irBuiltIns.unitType)
val locId = tw.getLocation(e)
val methodLabel = getObinitLabel(irConstructor.parentAsClass)
val methodId = tw.getLabelFor<DbMethod>(methodLabel)
tw.writeExprs_methodaccess(id, type.javaResult.id, exprParent.parent, exprParent.idx)
tw.writeExprsKotlinType(id, type.kotlinResult.id)
tw.writeHasLocation(id, locId)
tw.writeCallableEnclosingExpr(id, callable)
tw.writeStatementEnclosingExpr(id, exprParent.enclosingStmt)
tw.writeCallableBinding(id, methodId)
}
else {
val stmtParent = parent.stmt(e, callable)
extractInstanceInitializerBlock(stmtParent, irConstructor)
}
}
is IrConstructorCall -> {
val exprParent = parent.expr(e, callable)