diff --git a/compiler/testData/codegen/box/reflection/modifiers/classes.kt b/compiler/testData/codegen/box/reflection/modifiers/classes.kt index 31e798ed5b1..635addea422 100644 --- a/compiler/testData/codegen/box/reflection/modifiers/classes.kt +++ b/compiler/testData/codegen/box/reflection/modifiers/classes.kt @@ -1,8 +1,7 @@ -// IGNORE_BACKEND: JS_IR -// TODO: muted automatically, investigate should it be ran for JS or not -// IGNORE_BACKEND: JS, NATIVE - +// TARGET_BACKEND: JVM +// IGNORE_BACKEND_FIR: JVM_IR // WITH_REFLECT +// FILE: box.kt import kotlin.test.assertTrue import kotlin.test.assertFalse @@ -12,6 +11,7 @@ sealed class S { inner class InnerClass companion object object NonCompanionObject + fun interface FunInterface { fun invoke() } } fun box(): String { @@ -22,26 +22,49 @@ fun box(): String { assertFalse(S::class.isData) assertFalse(S::class.isInner) assertFalse(S::class.isCompanion) + assertFalse(S::class.isFun) assertFalse(S.DataClass::class.isSealed) assertTrue(S.DataClass::class.isData) assertFalse(S.DataClass::class.isInner) assertFalse(S.DataClass::class.isCompanion) + assertFalse(S.DataClass::class.isFun) assertFalse(S.InnerClass::class.isSealed) assertFalse(S.InnerClass::class.isData) assertTrue(S.InnerClass::class.isInner) assertFalse(S.InnerClass::class.isCompanion) + assertFalse(S.InnerClass::class.isFun) assertFalse(S.Companion::class.isSealed) assertFalse(S.Companion::class.isData) assertFalse(S.Companion::class.isInner) assertTrue(S.Companion::class.isCompanion) + assertFalse(S.Companion::class.isFun) assertFalse(S.NonCompanionObject::class.isSealed) assertFalse(S.NonCompanionObject::class.isData) assertFalse(S.NonCompanionObject::class.isInner) assertFalse(S.NonCompanionObject::class.isCompanion) + assertFalse(S.NonCompanionObject::class.isFun) + + assertFalse(S.FunInterface::class.isSealed) + assertFalse(S.FunInterface::class.isData) + assertFalse(S.FunInterface::class.isInner) + assertFalse(S.FunInterface::class.isCompanion) + assertTrue(S.FunInterface::class.isFun) + + assertFalse(JavaInterface::class.isSealed) + assertFalse(JavaInterface::class.isData) + assertFalse(JavaInterface::class.isInner) + assertFalse(JavaInterface::class.isCompanion) + assertFalse(JavaInterface::class.isFun) return "OK" } + +// FILE: JavaInterface.java + +public interface JavaInterface { + int invoke(String s); +} diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt index f0cc00577b3..2e8a97c9c15 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt @@ -279,6 +279,10 @@ internal class KClassImpl(override val jClass: Class) : KDeclaration override val isCompanion: Boolean get() = descriptor.isCompanionObject + @Suppress("NOTHING_TO_OVERRIDE") // Temporary workaround for the JPS build until bootstrap + override val isFun: Boolean + get() = descriptor.isFun + override fun equals(other: Any?): Boolean = other is KClassImpl<*> && javaObjectType == other.javaObjectType diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 26f9cc669ac..7248ea1a565 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -21766,11 +21766,6 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/reflection/modifiers/classVisibility.kt"); } - @TestMetadata("classes.kt") - public void testClasses() throws Exception { - runTest("compiler/testData/codegen/box/reflection/modifiers/classes.kt"); - } - @TestMetadata("functions.kt") public void testFunctions() throws Exception { runTest("compiler/testData/codegen/box/reflection/modifiers/functions.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index a636a60b113..601a7252109 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -21781,11 +21781,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/reflection/modifiers/classVisibility.kt"); } - @TestMetadata("classes.kt") - public void testClasses() throws Exception { - runTest("compiler/testData/codegen/box/reflection/modifiers/classes.kt"); - } - @TestMetadata("functions.kt") public void testFunctions() throws Exception { runTest("compiler/testData/codegen/box/reflection/modifiers/functions.kt"); diff --git a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ClassReference.kt b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ClassReference.kt index 11f492d071b..9861ff33c2c 100644 --- a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ClassReference.kt +++ b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/ClassReference.kt @@ -77,6 +77,10 @@ public class ClassReference(override val jClass: Class<*>) : KClass, ClassB override val isCompanion: Boolean get() = error() + @SinceKotlin("1.4") + override val isFun: Boolean + get() = error() + private fun error(): Nothing = throw KotlinReflectionNotSupportedError() override fun equals(other: Any?) = diff --git a/libraries/stdlib/jvm/src/kotlin/reflect/KClass.kt b/libraries/stdlib/jvm/src/kotlin/reflect/KClass.kt index 8e9ae52b8c5..950d01b0737 100644 --- a/libraries/stdlib/jvm/src/kotlin/reflect/KClass.kt +++ b/libraries/stdlib/jvm/src/kotlin/reflect/KClass.kt @@ -127,6 +127,12 @@ public actual interface KClass : KDeclarationContainer, KAnnotatedEleme @SinceKotlin("1.1") public val isCompanion: Boolean + /** + * `true` if this class is a Kotlin functional interface. + */ + @SinceKotlin("1.4") + public val isFun: Boolean + /** * Returns `true` if this [KClass] instance represents the same Kotlin class as the class represented by [other]. * On JVM this means that all of the following conditions are satisfied: diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt index b561882f46a..bfaa1afa5ae 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-stdlib-runtime-merged.txt @@ -3450,6 +3450,7 @@ public final class kotlin/jvm/internal/ClassReference : kotlin/jvm/internal/Clas public fun isCompanion ()Z public fun isData ()Z public fun isFinal ()Z + public fun isFun ()Z public fun isInner ()Z public fun isInstance (Ljava/lang/Object;)Z public fun isOpen ()Z @@ -4593,6 +4594,7 @@ public abstract interface class kotlin/reflect/KClass : kotlin/reflect/KAnnotate public abstract fun isCompanion ()Z public abstract fun isData ()Z public abstract fun isFinal ()Z + public abstract fun isFun ()Z public abstract fun isInner ()Z public abstract fun isInstance (Ljava/lang/Object;)Z public abstract fun isOpen ()Z