Use manual type mapping in reflection for members from built-ins
There are cases when members deserialized from JVM classes have no JVM signature in the proto. For example, if a member is inherited from a built-in class (such as Map.getOrDefault in some Map implementations), or if a member is synthesized in the compiler front-end and back-end separately (such as enum values/valueOf). In these cases, we'll use the naive type mapping to try to recover the signature. #KT-16616 Fixed #KT-17542 Fixed
This commit is contained in:
+7
-5
@@ -1,12 +1,11 @@
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
// IGNORE_BACKEND: JVM_IR, JS_IR, JS, NATIVE
|
||||
// WITH_REFLECT
|
||||
// FULL_JDK
|
||||
// See KT-11258 Incorrect resolution sequence for Java field
|
||||
|
||||
//SHOULD BE deleted after KT-16616 fix
|
||||
// See KT-11258, KT-16616
|
||||
|
||||
import java.util.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun box(): String {
|
||||
listOf(
|
||||
@@ -22,5 +21,8 @@ fun box(): String {
|
||||
).map {
|
||||
it.members.map(Any::toString)
|
||||
}
|
||||
|
||||
assertEquals(1, Collection<Any>::size.getter(listOf(1)))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
enum class E { X, Y, Z }
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(11, E::class.members.size)
|
||||
assertEquals("Y", E::name.call(E.Y))
|
||||
assertEquals(2, E::ordinal.call(E.Z))
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun box(): String {
|
||||
String::class.members
|
||||
assertEquals(2, String::length.call("OK"))
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// IGNORE_BACKEND: JS_IR, JS, NATIVE
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
enum class E { X, Y, Z }
|
||||
|
||||
fun box(): String {
|
||||
assertEquals("fun values(): kotlin.Array<E>", E::values.toString())
|
||||
assertEquals(listOf(E.X, E.Y, E.Z), E::values.call().toList())
|
||||
assertEquals("fun valueOf(kotlin.String): E", E::valueOf.toString())
|
||||
assertEquals(E.Y, E::valueOf.call("Y"))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// IGNORE_BACKEND: JVM_IR, JS_IR, JS, NATIVE
|
||||
// FULL_JDK
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
import java.util.*
|
||||
|
||||
fun assertToString(s: String, x: Any) {
|
||||
assertEquals(s, x.toString())
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertToString("fun kotlin.collections.Map<K, V>.getOrDefault(K, V): V", Map<*, *>::getOrDefault)
|
||||
assertToString("fun java.util.HashMap<K, V>.getOrDefault(K, V): V", HashMap<*, *>::getOrDefault)
|
||||
|
||||
// TODO: uncomment once KT-11754 is fixed
|
||||
// assertToString("", MutableList<*>::removeAt)
|
||||
|
||||
assertToString("fun kotlin.collections.Collection<E>.contains(E): kotlin.Boolean", Collection<*>::contains)
|
||||
assertToString("fun kotlin.collections.Set<E>.contains(E): kotlin.Boolean", Set<*>::contains)
|
||||
|
||||
assertToString("fun kotlin.collections.Collection<E>.isEmpty(): kotlin.Boolean", Collection<*>::isEmpty)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Vendored
-30
@@ -1,30 +0,0 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// TODO: muted automatically, investigate should it be ran for JS or not
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
// WITH_REFLECT
|
||||
// FULL_JDK
|
||||
// See KT-11258 Incorrect resolution sequence for Java field
|
||||
|
||||
// TODO: enable this test on JVM, see KT-16616
|
||||
// IGNORE_BACKEND: JVM
|
||||
|
||||
import java.util.*
|
||||
|
||||
fun box(): String {
|
||||
listOf(
|
||||
ArrayList::class,
|
||||
LinkedList::class,
|
||||
AbstractList::class,
|
||||
HashSet::class,
|
||||
TreeSet::class,
|
||||
HashMap::class,
|
||||
TreeMap::class,
|
||||
AbstractMap::class,
|
||||
AbstractMap.SimpleEntry::class
|
||||
).map {
|
||||
it.members.map(Any::toString)
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
Generated
+38
-18
@@ -16408,6 +16408,34 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/builtins")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Builtins extends AbstractIrBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInBuiltins() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/builtins"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("collections.kt")
|
||||
public void testCollections() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/collections.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumNameOrdinal.kt")
|
||||
public void testEnumNameOrdinal() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/enumNameOrdinal.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("stringLength.kt")
|
||||
public void testStringLength() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/stringLength.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/call")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -17129,6 +17157,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/declaredVsInheritedFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumValuesValueOf.kt")
|
||||
public void testEnumValuesValueOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/enumValuesValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionFromStdlib.kt")
|
||||
public void testFunctionFromStdlib() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/functionFromStdlib.kt");
|
||||
@@ -17581,6 +17614,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/methodsFromAny"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("builtinFunctionsToString.kt")
|
||||
public void testBuiltinFunctionsToString() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/builtinFunctionsToString.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesEqualToCallablesFromAPI.kt")
|
||||
public void testCallableReferencesEqualToCallablesFromAPI() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/callableReferencesEqualToCallablesFromAPI.kt");
|
||||
@@ -18224,24 +18262,6 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/specialBuiltIns")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SpecialBuiltIns extends AbstractIrBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInSpecialBuiltIns() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/specialBuiltIns"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("getMembersOfStandardJavaClasses.kt")
|
||||
public void testGetMembersOfStandardJavaClasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/specialBuiltIns/getMembersOfStandardJavaClasses.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/supertypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+38
-18
@@ -16408,6 +16408,34 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/builtins")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Builtins extends AbstractBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInBuiltins() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/builtins"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("collections.kt")
|
||||
public void testCollections() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/collections.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumNameOrdinal.kt")
|
||||
public void testEnumNameOrdinal() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/enumNameOrdinal.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("stringLength.kt")
|
||||
public void testStringLength() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/stringLength.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/call")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -17129,6 +17157,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/declaredVsInheritedFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumValuesValueOf.kt")
|
||||
public void testEnumValuesValueOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/enumValuesValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionFromStdlib.kt")
|
||||
public void testFunctionFromStdlib() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/functionFromStdlib.kt");
|
||||
@@ -17581,6 +17614,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/methodsFromAny"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("builtinFunctionsToString.kt")
|
||||
public void testBuiltinFunctionsToString() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/builtinFunctionsToString.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesEqualToCallablesFromAPI.kt")
|
||||
public void testCallableReferencesEqualToCallablesFromAPI() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/callableReferencesEqualToCallablesFromAPI.kt");
|
||||
@@ -18224,24 +18262,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/specialBuiltIns")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SpecialBuiltIns extends AbstractBlackBoxCodegenTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInSpecialBuiltIns() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/specialBuiltIns"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("getMembersOfStandardJavaClasses.kt")
|
||||
public void testGetMembersOfStandardJavaClasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/specialBuiltIns/getMembersOfStandardJavaClasses.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/supertypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+38
-18
@@ -16408,6 +16408,34 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/builtins")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Builtins extends AbstractLightAnalysisModeTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInBuiltins() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/builtins"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("collections.kt")
|
||||
public void testCollections() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/collections.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumNameOrdinal.kt")
|
||||
public void testEnumNameOrdinal() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/enumNameOrdinal.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("stringLength.kt")
|
||||
public void testStringLength() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/stringLength.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/call")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -17129,6 +17157,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/declaredVsInheritedFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumValuesValueOf.kt")
|
||||
public void testEnumValuesValueOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/enumValuesValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionFromStdlib.kt")
|
||||
public void testFunctionFromStdlib() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/functionFromStdlib.kt");
|
||||
@@ -17581,6 +17614,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/methodsFromAny"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("builtinFunctionsToString.kt")
|
||||
public void testBuiltinFunctionsToString() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/builtinFunctionsToString.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesEqualToCallablesFromAPI.kt")
|
||||
public void testCallableReferencesEqualToCallablesFromAPI() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/callableReferencesEqualToCallablesFromAPI.kt");
|
||||
@@ -18224,24 +18262,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/specialBuiltIns")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SpecialBuiltIns extends AbstractLightAnalysisModeTest {
|
||||
@TestMetadata("getMembersOfStandardJavaClasses.kt")
|
||||
public void ignoreGetMembersOfStandardJavaClasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/specialBuiltIns/getMembersOfStandardJavaClasses.kt");
|
||||
}
|
||||
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInSpecialBuiltIns() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/specialBuiltIns"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/supertypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+18
-17
@@ -18,26 +18,27 @@ import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
fun FunctionDescriptor.computeJvmDescriptor(withReturnType: Boolean = true)
|
||||
= StringBuilder().apply {
|
||||
append(if (this@computeJvmDescriptor is ConstructorDescriptor) "<init>" else name.asString())
|
||||
append("(")
|
||||
fun FunctionDescriptor.computeJvmDescriptor(withReturnType: Boolean = true, withName: Boolean = true): String = buildString {
|
||||
if (withName) {
|
||||
append(if (this@computeJvmDescriptor is ConstructorDescriptor) "<init>" else name.asString())
|
||||
}
|
||||
|
||||
valueParameters.forEach {
|
||||
appendErasedType(it.type)
|
||||
}
|
||||
append("(")
|
||||
|
||||
append(")")
|
||||
for (parameter in valueParameters) {
|
||||
appendErasedType(parameter.type)
|
||||
}
|
||||
|
||||
if (withReturnType) {
|
||||
if (hasVoidReturnType(this@computeJvmDescriptor)) {
|
||||
append("V")
|
||||
}
|
||||
else {
|
||||
appendErasedType(returnType!!)
|
||||
}
|
||||
}
|
||||
}.toString()
|
||||
append(")")
|
||||
|
||||
if (withReturnType) {
|
||||
if (hasVoidReturnType(this@computeJvmDescriptor)) {
|
||||
append("V")
|
||||
} else {
|
||||
appendErasedType(returnType!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Boxing is only necessary for 'remove(E): Boolean' of a MutableCollection<Int> implementation
|
||||
// Otherwise this method might clash with 'remove(I): E' defined in the java.util.List JDK interface (mapped to kotlin 'removeAt')
|
||||
|
||||
@@ -152,6 +152,19 @@ public class DescriptorFactory {
|
||||
Modality.FINAL, Visibilities.PUBLIC);
|
||||
}
|
||||
|
||||
public static boolean isEnumValuesMethod(@NotNull FunctionDescriptor descriptor) {
|
||||
return descriptor.getName().equals(DescriptorUtils.ENUM_VALUES) && isEnumSpecialMethod(descriptor);
|
||||
}
|
||||
|
||||
public static boolean isEnumValueOfMethod(@NotNull FunctionDescriptor descriptor) {
|
||||
return descriptor.getName().equals(DescriptorUtils.ENUM_VALUE_OF) && isEnumSpecialMethod(descriptor);
|
||||
}
|
||||
|
||||
private static boolean isEnumSpecialMethod(@NotNull FunctionDescriptor descriptor) {
|
||||
return descriptor.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED &&
|
||||
DescriptorUtils.isEnumClass(descriptor.getContainingDeclaration());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ReceiverParameterDescriptor createExtensionReceiverParameterForCallable(
|
||||
@NotNull CallableDescriptor owner,
|
||||
|
||||
@@ -75,6 +75,7 @@ internal abstract class KPropertyImpl<out R> private constructor(
|
||||
}
|
||||
is JavaField -> jvmSignature.field
|
||||
is JavaMethodProperty -> null
|
||||
is MappedKotlinProperty -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,5 +269,19 @@ private fun KPropertyImpl.Accessor<*, *>.computeCallerForAccessor(isGetter: Bool
|
||||
if (isBound) FunctionCaller.BoundInstanceMethod(method, property.boundReceiver)
|
||||
else FunctionCaller.InstanceMethod(method)
|
||||
}
|
||||
is MappedKotlinProperty -> {
|
||||
val signature =
|
||||
if (isGetter) jvmSignature.getterSignature
|
||||
else (jvmSignature.setterSignature
|
||||
?: throw KotlinReflectionInternalError("No setter found for property $property"))
|
||||
val accessor = property.container.findMethodBySignature(
|
||||
signature.methodName, signature.methodDesc, descriptor.isPublicInBytecode
|
||||
) ?: throw KotlinReflectionInternalError("No accessor found for property $property")
|
||||
|
||||
assert(!Modifier.isStatic(accessor.modifiers)) { "Mapped property cannot have a static accessor: $property" }
|
||||
|
||||
return if (isBound) FunctionCaller.BoundInstanceMethod(accessor, property.boundReceiver)
|
||||
else FunctionCaller.InstanceMethod(accessor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,16 +18,15 @@ package kotlin.reflect.jvm.internal
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.getJvmMethodNameIfSpecial
|
||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolver
|
||||
import org.jetbrains.kotlin.metadata.deserialization.TypeTable
|
||||
@@ -39,7 +38,9 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||
@@ -150,6 +151,13 @@ internal sealed class JvmPropertySignature {
|
||||
override fun asString(): String =
|
||||
JvmAbi.getterName(field.name) + "()" + field.type.desc
|
||||
}
|
||||
|
||||
class MappedKotlinProperty(
|
||||
val getterSignature: JvmFunctionSignature.KotlinFunction,
|
||||
val setterSignature: JvmFunctionSignature.KotlinFunction?
|
||||
) : JvmPropertySignature() {
|
||||
override fun asString(): String = getterSignature.asString()
|
||||
}
|
||||
}
|
||||
|
||||
private val Method.signature: String
|
||||
@@ -182,10 +190,7 @@ internal object RuntimeTypeMapper {
|
||||
return JvmFunctionSignature.KotlinConstructor(signature)
|
||||
}
|
||||
}
|
||||
// If it's a deserialized function but has no JVM signature, it must be from built-ins
|
||||
throw KotlinReflectionInternalError(
|
||||
"Reflection on built-in Kotlin types is not yet fully supported. No metadata found for $function"
|
||||
)
|
||||
return mapJvmFunctionSignature(function)
|
||||
}
|
||||
is JavaMethodDescriptor -> {
|
||||
val method = ((function.source as? JavaSourceElement)?.javaElement as? ReflectJavaMethod)?.member
|
||||
@@ -203,25 +208,28 @@ internal object RuntimeTypeMapper {
|
||||
else -> throw KotlinReflectionInternalError("Incorrect resolution sequence for Java constructor $function ($element)")
|
||||
}
|
||||
}
|
||||
else -> throw KotlinReflectionInternalError("Unknown origin of $function (${function.javaClass})")
|
||||
}
|
||||
|
||||
if (DescriptorFactory.isEnumValueOfMethod(function) || DescriptorFactory.isEnumValuesMethod(function)) {
|
||||
return mapJvmFunctionSignature(function)
|
||||
}
|
||||
|
||||
throw KotlinReflectionInternalError("Unknown origin of $function (${function.javaClass})")
|
||||
}
|
||||
|
||||
fun mapPropertySignature(possiblyOverriddenProperty: PropertyDescriptor): JvmPropertySignature {
|
||||
val property = DescriptorUtils.unwrapFakeOverride(possiblyOverriddenProperty).original
|
||||
return when (property) {
|
||||
when (property) {
|
||||
is DeserializedPropertyDescriptor -> {
|
||||
val proto = property.proto
|
||||
val signature = proto.getExtensionOrNull(JvmProtoBuf.propertySignature)
|
||||
?: // If this property has no JVM signature, it must be from built-ins
|
||||
throw KotlinReflectionInternalError(
|
||||
"Reflection on built-in Kotlin types is not yet fully supported. No metadata found for $property"
|
||||
)
|
||||
JvmPropertySignature.KotlinProperty(property, proto, signature, property.nameResolver, property.typeTable)
|
||||
if (signature != null) {
|
||||
return JvmPropertySignature.KotlinProperty(property, proto, signature, property.nameResolver, property.typeTable)
|
||||
}
|
||||
}
|
||||
is JavaPropertyDescriptor -> {
|
||||
val element = (property.source as? JavaSourceElement)?.javaElement
|
||||
when (element) {
|
||||
return when (element) {
|
||||
is ReflectJavaField -> JvmPropertySignature.JavaField(element.member)
|
||||
is ReflectJavaMethod -> JvmPropertySignature.JavaMethodProperty(
|
||||
element.member,
|
||||
@@ -230,12 +238,26 @@ internal object RuntimeTypeMapper {
|
||||
else -> throw KotlinReflectionInternalError("Incorrect resolution sequence for Java field $property (source = $element)")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
throw KotlinReflectionInternalError("Unknown origin of $property (${property.javaClass})")
|
||||
}
|
||||
}
|
||||
|
||||
return JvmPropertySignature.MappedKotlinProperty(
|
||||
property.getter!!.let(this::mapJvmFunctionSignature),
|
||||
property.setter?.let(this::mapJvmFunctionSignature)
|
||||
)
|
||||
}
|
||||
|
||||
private fun mapJvmFunctionSignature(descriptor: FunctionDescriptor): JvmFunctionSignature.KotlinFunction =
|
||||
JvmFunctionSignature.KotlinFunction(
|
||||
JvmMemberSignature.Method(mapName(descriptor), descriptor.computeJvmDescriptor(withName = false))
|
||||
)
|
||||
|
||||
private fun mapName(descriptor: CallableMemberDescriptor): String =
|
||||
getJvmMethodNameIfSpecial(descriptor) ?: when (descriptor) {
|
||||
is PropertyGetterDescriptor -> JvmAbi.getterName(descriptor.propertyIfAccessor.name.asString())
|
||||
is PropertySetterDescriptor -> JvmAbi.setterName(descriptor.propertyIfAccessor.name.asString())
|
||||
else -> descriptor.name.asString()
|
||||
}
|
||||
|
||||
private fun mapIntrinsicFunctionSignature(function: FunctionDescriptor): JvmFunctionSignature? {
|
||||
val parameters = function.valueParameters
|
||||
|
||||
|
||||
+38
-18
@@ -14723,6 +14723,34 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/builtins")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Builtins extends AbstractIrJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInBuiltins() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/builtins"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("collections.kt")
|
||||
public void testCollections() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/collections.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumNameOrdinal.kt")
|
||||
public void testEnumNameOrdinal() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/enumNameOrdinal.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("stringLength.kt")
|
||||
public void testStringLength() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/stringLength.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/call")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -15444,6 +15472,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/declaredVsInheritedFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumValuesValueOf.kt")
|
||||
public void testEnumValuesValueOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/enumValuesValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionFromStdlib.kt")
|
||||
public void testFunctionFromStdlib() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/functionFromStdlib.kt");
|
||||
@@ -15886,6 +15919,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/methodsFromAny"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("builtinFunctionsToString.kt")
|
||||
public void testBuiltinFunctionsToString() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/builtinFunctionsToString.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesEqualToCallablesFromAPI.kt")
|
||||
public void testCallableReferencesEqualToCallablesFromAPI() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/callableReferencesEqualToCallablesFromAPI.kt");
|
||||
@@ -16499,24 +16537,6 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/specialBuiltIns")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SpecialBuiltIns extends AbstractIrJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInSpecialBuiltIns() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/specialBuiltIns"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("getMembersOfStandardJavaClasses.kt")
|
||||
public void testGetMembersOfStandardJavaClasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/specialBuiltIns/getMembersOfStandardJavaClasses.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/supertypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+38
-18
@@ -14723,6 +14723,34 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/builtins")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Builtins extends AbstractJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInBuiltins() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/builtins"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("collections.kt")
|
||||
public void testCollections() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/collections.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumNameOrdinal.kt")
|
||||
public void testEnumNameOrdinal() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/enumNameOrdinal.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("stringLength.kt")
|
||||
public void testStringLength() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/builtins/stringLength.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/call")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -15444,6 +15472,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/declaredVsInheritedFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumValuesValueOf.kt")
|
||||
public void testEnumValuesValueOf() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/enumValuesValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionFromStdlib.kt")
|
||||
public void testFunctionFromStdlib() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/functions/functionFromStdlib.kt");
|
||||
@@ -15886,6 +15919,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/methodsFromAny"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("builtinFunctionsToString.kt")
|
||||
public void testBuiltinFunctionsToString() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/builtinFunctionsToString.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callableReferencesEqualToCallablesFromAPI.kt")
|
||||
public void testCallableReferencesEqualToCallablesFromAPI() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/methodsFromAny/callableReferencesEqualToCallablesFromAPI.kt");
|
||||
@@ -16499,24 +16537,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/specialBuiltIns")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SpecialBuiltIns extends AbstractJsCodegenBoxTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInSpecialBuiltIns() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/specialBuiltIns"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("getMembersOfStandardJavaClasses.kt")
|
||||
public void testGetMembersOfStandardJavaClasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/specialBuiltIns/getMembersOfStandardJavaClasses.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/reflection/supertypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user