JVM_IR: generate default constructor
Quoted from https://kotlinlang.org/docs/reference/classes.html "On the JVM, if all of the parameters of the primary constructor have default values, the compiler will generate an additional parameterless constructor which will use the default values. This makes it easier to use Kotlin with libraries such as Jackson or JPA that create class instances through parameterless constructors."
This commit is contained in:
committed by
max-kammerer
parent
440f327e74
commit
74e8c7c1c5
@@ -114,6 +114,7 @@ val jvmPhases = namedIrFilePhase<JvmBackendContext>(
|
||||
annotationPhase then
|
||||
tailrecPhase then
|
||||
|
||||
jvmDefaultConstructorPhase then
|
||||
defaultArgumentStubPhase then
|
||||
|
||||
interfacePhase then
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
|
||||
import org.jetbrains.kotlin.ir.builders.irBlockBody
|
||||
import org.jetbrains.kotlin.ir.builders.irDelegatingConstructorCall
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.hasDefaultValue
|
||||
|
||||
internal val jvmDefaultConstructorPhase = makeIrFilePhase(
|
||||
::JvmDefaultConstructorLowering,
|
||||
name = "JvmDefaultConstructor",
|
||||
description = "Generate default constructors for Java"
|
||||
)
|
||||
|
||||
// Quoted from https://kotlinlang.org/docs/reference/classes.html
|
||||
//
|
||||
// "On the JVM, if all of the parameters of the primary constructor have default values, the compiler will generate an additional
|
||||
// parameterless constructor which will use the default values. This makes it easier to use Kotlin with libraries such as Jackson
|
||||
// or JPA that create class instances through parameterless constructors."
|
||||
private class JvmDefaultConstructorLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
||||
|
||||
override fun lower(irClass: IrClass) {
|
||||
val primaryConstructor = irClass.constructors.firstOrNull { it.isPrimary } ?: return
|
||||
|
||||
if (!primaryConstructor.valueParameters.all { it.hasDefaultValue() })
|
||||
return
|
||||
|
||||
// Skip if the default constructor is already defined by user.
|
||||
if (irClass.constructors.any { it.valueParameters.isEmpty() })
|
||||
return
|
||||
|
||||
irClass.addConstructor().apply {
|
||||
val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset)
|
||||
body = irBuilder.irBlockBody {
|
||||
+irDelegatingConstructorCall(primaryConstructor).apply {
|
||||
passTypeArgumentsFrom(irClass)
|
||||
passTypeArgumentsFrom(primaryConstructor, irClass.typeParameters.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: common.kt
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.NO_EXCEPTION_ON_EXPLICIT_EQUALS_FOR_BOXED_NULL
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: test.kt
|
||||
import kotlin.test.*
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: WithPrimary.java
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
package test
|
||||
|
||||
class A(val a: Int = 1)
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
package test
|
||||
|
||||
class A(val a: Int = 1, val b: String = "default")
|
||||
|
||||
Reference in New Issue
Block a user