diff --git a/compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt b/compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt new file mode 100644 index 00000000000..c7aa6b28553 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt @@ -0,0 +1,36 @@ +// WITH_REFLECT + +import kotlin.reflect.KClass +import kotlin.test.assertEquals + +class F { + fun foo() {} + val B.bar: B get() = this +} + +class C { + fun baz() {} + fun quux() {} +} + +fun get(klass: KClass<*>, memberName: String? = null): List = + (if (memberName != null) + klass.members.single { it.name == memberName }.typeParameters + else + klass.typeParameters) + .map { it.name } + +fun box(): String { + assertEquals(listOf(), get(F::class)) + assertEquals(listOf("A"), get(F::class, "foo")) + assertEquals(listOf("B"), get(F::class, "bar")) + + assertEquals(listOf("D"), get(C::class)) + assertEquals(listOf(), get(C::class, "baz")) + assertEquals(listOf("E", "G"), get(C::class, "quux")) + + assertEquals(listOf("T"), get(Comparable::class)) + assertEquals(listOf(), get(String::class)) + + return "OK" +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/kt9078.kt b/compiler/testData/diagnostics/testsWithStdLib/kt9078.kt index 772756199f8..17ac0a0e3af 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/kt9078.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/kt9078.kt @@ -1,5 +1,5 @@ // KT-9078 (NPE in control flow analysis); EA-71535 -abstract class KFunctionKt9005WorkAround(private val _functionInstance: Function): kotlin.reflect.KCallable { +abstract class KFunctionKt9005WorkAround(private val _functionInstance: Function) { private val _reflectedFunction: kotlin.reflect.KFunction = _functionInstance.reflect() ?: throw IllegalStateException("") private val _parameters: List = run { @@ -9,4 +9,4 @@ abstract class KFunctionKt9005WorkAround(private val _functionInsta } } } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/kt9078.txt b/compiler/testData/diagnostics/testsWithStdLib/kt9078.txt index 256b7a7bf4b..86496f91177 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/kt9078.txt +++ b/compiler/testData/diagnostics/testsWithStdLib/kt9078.txt @@ -1,16 +1,10 @@ package -public abstract class KFunctionKt9005WorkAround : kotlin.reflect.KCallable { +public abstract class KFunctionKt9005WorkAround { public constructor KFunctionKt9005WorkAround(/*0*/ _functionInstance: kotlin.Function) private final val _functionInstance: kotlin.Function private final val _parameters: kotlin.collections.List private final val _reflectedFunction: kotlin.reflect.KFunction - public abstract override /*1*/ /*fake_override*/ val annotations: kotlin.collections.List - public abstract override /*1*/ /*fake_override*/ val name: kotlin.String - public abstract override /*1*/ /*fake_override*/ val parameters: kotlin.collections.List - public abstract override /*1*/ /*fake_override*/ val returnType: kotlin.reflect.KType - public abstract override /*1*/ /*fake_override*/ fun call(/*0*/ vararg args: kotlin.Any? /*kotlin.Array*/): R - public abstract override /*1*/ /*fake_override*/ fun callBy(/*0*/ args: kotlin.collections.Map): R public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index e73a37bdeb2..61fc443ba7e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -12943,6 +12943,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @TestMetadata("compiler/testData/codegen/box/reflection/typeParameters") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class TypeParameters extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInTypeParameters() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/typeParameters"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("typeParametersAndNames.kt") + public void testTypeParametersAndNames() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/typeParameters/typeParametersAndNames.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/reflection/types") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/builtins/src/kotlin/reflect/KCallable.kt b/core/builtins/src/kotlin/reflect/KCallable.kt index e4fa3d7cfd9..d78b04b5b4d 100644 --- a/core/builtins/src/kotlin/reflect/KCallable.kt +++ b/core/builtins/src/kotlin/reflect/KCallable.kt @@ -44,6 +44,11 @@ public interface KCallable : KAnnotatedElement { */ public val returnType: KType + /** + * The list of type parameters of this callable. + */ + public val typeParameters: List + /** * Calls this callable with the specified list of arguments and returns the result. * Throws an exception if the number of specified arguments is not equal to the size of [parameters], diff --git a/core/builtins/src/kotlin/reflect/KClass.kt b/core/builtins/src/kotlin/reflect/KClass.kt index 7d5b98bc8a9..05112072240 100644 --- a/core/builtins/src/kotlin/reflect/KClass.kt +++ b/core/builtins/src/kotlin/reflect/KClass.kt @@ -58,6 +58,11 @@ public interface KClass : KDeclarationContainer, KAnnotatedElement, KCl */ public val objectInstance: T? + /** + * The list of type parameters of this class. This list does *not* include type parameters of outer classes. + */ + public val typeParameters: List + /** * Returns `true` if [other] is a [KClass] instance representing the same class on a given platform. * diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt index 759e345281b..730da030488 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt @@ -20,10 +20,7 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.annotations.Annotated import java.lang.reflect.Type import java.util.* -import kotlin.reflect.KCallable -import kotlin.reflect.KParameter -import kotlin.reflect.KType -import kotlin.reflect.KotlinReflectionInternalError +import kotlin.reflect.* import kotlin.reflect.jvm.javaType internal interface KCallableImpl : KCallable, KAnnotatedElementImpl { @@ -62,6 +59,9 @@ internal interface KCallableImpl : KCallable, KAnnotatedElementImpl { override val returnType: KType get() = KTypeImpl(descriptor.returnType!!) { caller.returnType } + override val typeParameters: List + get() = descriptor.typeParameters.map(::KTypeParameterImpl) + @Suppress("UNCHECKED_CAST") override fun call(vararg args: Any?): R = reflectionCall { return caller.call(args) as R 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 39ae54e76ec..c69f85e21d4 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt @@ -27,10 +27,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies -import kotlin.reflect.KCallable -import kotlin.reflect.KClass -import kotlin.reflect.KFunction -import kotlin.reflect.KotlinReflectionInternalError +import kotlin.reflect.* internal class KClassImpl(override val jClass: Class) : KDeclarationContainerImpl(), KClass, KClassifierImpl, KAnnotatedElementImpl { @@ -139,6 +136,9 @@ internal class KClassImpl(override val jClass: Class) : override val objectInstance: T? get() = objectInstance_() + override val typeParameters: List + get() = descriptor.declaredTypeParameters.map(::KTypeParameterImpl) + override fun equals(other: Any?): Boolean = other is KClassImpl<*> && jClass == other.jClass diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java index 508c02e5676..d13dd72c6e0 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java @@ -83,6 +83,12 @@ public abstract class CallableReference implements KCallable { return getReflected().getAnnotations(); } + @NotNull + @Override + public List getTypeParameters() { + return getReflected().getTypeParameters(); + } + @Override public Object call(@NotNull Object... args) { return getReflected().call(args); diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/ClassReference.kt b/core/runtime.jvm/src/kotlin/jvm/internal/ClassReference.kt index 589b004da99..cfb5cc0de6d 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/ClassReference.kt +++ b/core/runtime.jvm/src/kotlin/jvm/internal/ClassReference.kt @@ -19,6 +19,7 @@ package kotlin.jvm.internal import kotlin.reflect.KCallable import kotlin.reflect.KClass import kotlin.reflect.KFunction +import kotlin.reflect.KTypeParameter class ClassReference(override val jClass: Class<*>) : KClass, ClassBasedDeclarationContainer { override val simpleName: String? @@ -42,6 +43,9 @@ class ClassReference(override val jClass: Class<*>) : KClass, ClassBasedDec override val objectInstance: Any? get() = error() + override val typeParameters: List + get() = error() + private fun error(): Nothing = throw KotlinReflectionNotSupportedError() override fun equals(other: Any?) = diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java index b2740a9c19c..66e9db329f4 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java @@ -17,10 +17,7 @@ package kotlin.jvm.internal; import kotlin.jvm.KotlinReflectionNotSupportedError; -import kotlin.reflect.KDeclarationContainer; -import kotlin.reflect.KFunction; -import kotlin.reflect.KParameter; -import kotlin.reflect.KType; +import kotlin.reflect.*; import org.jetbrains.annotations.NotNull; import java.lang.annotation.Annotation; @@ -71,6 +68,12 @@ public class FunctionReference extends FunctionImpl implements KFunction { return getReflected().getAnnotations(); } + @NotNull + @Override + public List getTypeParameters() { + return getReflected().getTypeParameters(); + } + @Override public Object call(@NotNull Object... args) { return getReflected().call(args);