diff --git a/compiler/testData/codegen/box/reflection/lambdaClasses/parameterNamesAndNullability.kt b/compiler/testData/codegen/box/reflection/lambdaClasses/parameterNamesAndNullability.kt index c8245ff9cc9..564d777df1b 100644 --- a/compiler/testData/codegen/box/reflection/lambdaClasses/parameterNamesAndNullability.kt +++ b/compiler/testData/codegen/box/reflection/lambdaClasses/parameterNamesAndNullability.kt @@ -1,5 +1,5 @@ +// !USE_EXPERIMENTAL: kotlin.reflect.jvm.ExperimentalReflectionOnLambdas // TARGET_BACKEND: JVM - // WITH_REFLECT import kotlin.reflect.KParameter diff --git a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithInlineClassArgument.kt b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithInlineClassArgument.kt index b214a51048d..13e3a31682c 100644 --- a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithInlineClassArgument.kt +++ b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithInlineClassArgument.kt @@ -1,3 +1,4 @@ +// !USE_EXPERIMENTAL: kotlin.reflect.jvm.ExperimentalReflectionOnLambdas // TARGET_BACKEND: JVM // WITH_REFLECT diff --git a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInArrayConstructor.kt b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInArrayConstructor.kt index 6d065e18695..79813e93d30 100644 --- a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInArrayConstructor.kt +++ b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInArrayConstructor.kt @@ -1,5 +1,5 @@ +// !USE_EXPERIMENTAL: kotlin.reflect.jvm.ExperimentalReflectionOnLambdas // TARGET_BACKEND: JVM -// WITH_RUNTIME // WITH_REFLECT import kotlin.reflect.jvm.* @@ -10,4 +10,4 @@ fun box(): String { assertNotNull(Array(1) { {} }.single().reflect()) return "OK" -} \ No newline at end of file +} diff --git a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInConstructor.kt b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInConstructor.kt index e677eff6698..d5e9fc7fc01 100644 --- a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInConstructor.kt +++ b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInConstructor.kt @@ -1,3 +1,4 @@ +// !USE_EXPERIMENTAL: kotlin.reflect.jvm.ExperimentalReflectionOnLambdas // TARGET_BACKEND: JVM // WITH_REFLECT diff --git a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInField.kt b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInField.kt index 60d6914c001..0f7ce0f34d6 100644 --- a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInField.kt +++ b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInField.kt @@ -1,3 +1,4 @@ +// !USE_EXPERIMENTAL: kotlin.reflect.jvm.ExperimentalReflectionOnLambdas // TARGET_BACKEND: JVM // WITH_REFLECT diff --git a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInStaticField.kt b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInStaticField.kt index ccd88ba89db..51a2c6db800 100644 --- a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInStaticField.kt +++ b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInStaticField.kt @@ -1,3 +1,4 @@ +// !USE_EXPERIMENTAL: kotlin.reflect.jvm.ExperimentalReflectionOnLambdas // TARGET_BACKEND: JVM // WITH_REFLECT diff --git a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspend.kt b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspend.kt index 0c26f334caf..9f077698687 100644 --- a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspend.kt +++ b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspend.kt @@ -1,3 +1,4 @@ +// !USE_EXPERIMENTAL: kotlin.reflect.jvm.ExperimentalReflectionOnLambdas // TARGET_BACKEND: JVM // WITH_REFLECT // WITH_COROUTINES diff --git a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt index 79dbae446c6..31f5236eee2 100644 --- a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt +++ b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInSuspendLambda.kt @@ -1,3 +1,4 @@ +// !USE_EXPERIMENTAL: kotlin.reflect.jvm.ExperimentalReflectionOnLambdas // TARGET_BACKEND: JVM // WITH_REFLECT // WITH_COROUTINES diff --git a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnSuspendLambdaInField.kt b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnSuspendLambdaInField.kt index e0acf8cdfac..7beb7be3a56 100644 --- a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnSuspendLambdaInField.kt +++ b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnSuspendLambdaInField.kt @@ -1,3 +1,4 @@ +// !USE_EXPERIMENTAL: kotlin.reflect.jvm.ExperimentalReflectionOnLambdas // TARGET_BACKEND: JVM // WITH_REFLECT diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/reflectLambda.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/reflectLambda.kt index 9020e2a9afe..f09d1f02f95 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/reflectLambda.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/reflectLambda.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.metadata.deserialization.TypeTable import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmMetadataVersion import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer +import kotlin.annotation.AnnotationTarget.* import kotlin.reflect.KFunction import kotlin.reflect.jvm.internal.EmptyContainerForLocal import kotlin.reflect.jvm.internal.KFunctionImpl @@ -31,6 +32,7 @@ import kotlin.reflect.jvm.internal.deserializeToDescriptor * returns a [KFunction] instance providing introspection capabilities for that lambda or function expression and its parameters. * Not all features are currently supported, in particular [KCallable.call] and [KCallable.callBy] will fail at the moment. */ +@ExperimentalReflectionOnLambdas fun Function.reflect(): KFunction? { val annotation = javaClass.getAnnotation(Metadata::class.java) ?: return null val data = annotation.data1.takeUnless(Array::isEmpty) ?: return null @@ -47,3 +49,30 @@ fun Function.reflect(): KFunction? { @Suppress("UNCHECKED_CAST") return KFunctionImpl(EmptyContainerForLocal, descriptor) as KFunction } + +/** + * This annotation marks the experimental kotlin-reflect API that allows to approximate a Kotlin lambda or a function expression instance + * to a [KFunction] instance. The behavior of this API may be changed or the API may be removed completely in any further release. + * + * Any usage of a declaration annotated with `@ExperimentalReflectionOnLambdas` should be accepted either by + * annotating that usage with the [OptIn] annotation, e.g. `@OptIn(ExperimentalReflectionOnLambdas::class)`, + * or by using the compiler argument `-Xopt-in=kotlin.reflect.jvm.ExperimentalReflectionOnLambdas`. + */ +@RequiresOptIn(level = RequiresOptIn.Level.WARNING) +@Retention(AnnotationRetention.BINARY) +@Target( + CLASS, + ANNOTATION_CLASS, + PROPERTY, + FIELD, + LOCAL_VARIABLE, + VALUE_PARAMETER, + CONSTRUCTOR, + FUNCTION, + PROPERTY_GETTER, + PROPERTY_SETTER, + TYPEALIAS +) +@MustBeDocumented +@SinceKotlin("1.5") +annotation class ExperimentalReflectionOnLambdas diff --git a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-reflect.txt b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-reflect.txt index cac1d358b55..5d7fdba1d33 100644 --- a/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-reflect.txt +++ b/libraries/tools/binary-compatibility-validator/reference-public-api/kotlin-reflect.txt @@ -66,6 +66,9 @@ public final class kotlin/reflect/full/NoSuchPropertyException : java/lang/Excep public synthetic fun (Ljava/lang/Exception;ILkotlin/jvm/internal/DefaultConstructorMarker;)V } +public abstract interface annotation class kotlin/reflect/jvm/ExperimentalReflectionOnLambdas : java/lang/annotation/Annotation { +} + public final class kotlin/reflect/jvm/KCallablesJvm { public static final fun isAccessible (Lkotlin/reflect/KCallable;)Z public static final fun setAccessible (Lkotlin/reflect/KCallable;Z)V