diff --git a/compiler/testData/codegen/boxWithStdlib/reflection/constructors/primaryConstructor.kt b/compiler/testData/codegen/boxWithStdlib/reflection/constructors/primaryConstructor.kt new file mode 100644 index 00000000000..c44e31b5140 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reflection/constructors/primaryConstructor.kt @@ -0,0 +1,52 @@ +import kotlin.test.assertNull +import kotlin.test.assertNotNull +import kotlin.reflect.* + +class OnlyPrimary + +class PrimaryWithSecondary(val s: String) { + constructor(x: Int) : this(x.toString()) + + override fun toString() = s +} + +class OnlySecondary { + constructor(s: String) +} + +class TwoSecondaries { + constructor(s: String) + constructor(d: Double) +} + +enum class En + +interface I +object O +class C { + companion object +} + +fun box(): String { + val p1 = OnlyPrimary::class.primaryConstructor + assertNotNull(p1) + assert(p1!!.call() is OnlyPrimary) + + val p2 = PrimaryWithSecondary::class.primaryConstructor + assertNotNull(p2) + assert(p2!!.call("beer").toString() == "beer") + + val p3 = OnlySecondary::class.primaryConstructor + assertNull(p3) + + val p4 = TwoSecondaries::class.primaryConstructor + assertNull(p4) + + assertNotNull(En::class.primaryConstructor) // TODO: maybe primaryConstructor should be null for enum classes + + assertNull(I::class.primaryConstructor) + assertNull(O::class.primaryConstructor) + assertNull(C.Companion::class.primaryConstructor) + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index a7f262c2903..f4ad2ff54c5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -2934,6 +2934,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("primaryConstructor.kt") + public void testPrimaryConstructor() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/constructors/primaryConstructor.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("simpleGetConstructors.kt") public void testSimpleGetConstructors() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/constructors/simpleGetConstructors.kt"); diff --git a/core/reflection.jvm/src/kotlin/reflect/KClassExtensions.kt b/core/reflection.jvm/src/kotlin/reflect/KClassExtensions.kt index 63878a8c5cb..9936dc6391b 100644 --- a/core/reflection.jvm/src/kotlin/reflect/KClassExtensions.kt +++ b/core/reflection.jvm/src/kotlin/reflect/KClassExtensions.kt @@ -16,7 +16,19 @@ package kotlin.reflect +import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import kotlin.reflect.jvm.internal.KClassImpl +import kotlin.reflect.jvm.internal.KFunctionImpl + +/** + * Returns the primary constructor of this class, or `null` if this class has no primary constructor. + * See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/classes.html#constructors) + * for more information. + */ +public val KClass.primaryConstructor: KFunction? + get() = (this as KClassImpl).constructors.firstOrNull { + ((it as KFunctionImpl).descriptor as ConstructorDescriptor).isPrimary + } /** * Returns all functions declared in this class.