From 02022171355091de40cf36d19395290c5042039c Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 1 Apr 2015 16:04:16 +0300 Subject: [PATCH] Fix JVM signatures involving multi-dimensional array types Apparently ASM's Type#getElementType returns the type of the array even if it's multi-dimensional, so the loop was incorrect --- .../kotlin/codegen/JvmSerializerExtension.java | 8 ++------ .../propertyOfNestedClassAndArrayType.kt | 16 ++++++++++++++++ .../annotations/MultiDimensionalArrayMethod.kt | 12 ++++++++++++ .../annotations/MultiDimensionalArrayMethod.txt | 13 +++++++++++++ .../BlackBoxWithStdlibCodegenTestGenerated.java | 6 ++++++ .../jvm/compiler/LoadJavaTestGenerated.java | 6 ++++++ .../JvmRuntimeDescriptorLoaderTestGenerated.java | 6 ++++++ .../java/structure/reflect/reflectClassUtil.kt | 1 - .../jvm/internal/KCallableContainerImpl.kt | 1 - .../idea/stubs/ResolveByStubTestGenerated.java | 6 ++++++ 10 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 compiler/testData/codegen/boxWithStdlib/reflection/properties/propertyOfNestedClassAndArrayType.kt create mode 100644 compiler/testData/loadJava/compiledKotlin/annotations/MultiDimensionalArrayMethod.kt create mode 100644 compiler/testData/loadJava/compiledKotlin/annotations/MultiDimensionalArrayMethod.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializerExtension.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializerExtension.java index 6270ce0bb2f..3259a679a70 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializerExtension.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/JvmSerializerExtension.java @@ -257,15 +257,11 @@ public class JvmSerializerExtension extends SerializerExtension { public JvmProtoBuf.JvmType type(@NotNull Type givenType) { JvmProtoBuf.JvmType.Builder builder = JvmProtoBuf.JvmType.newBuilder(); - int arrayDimension = 0; Type type = givenType; - while (type.getSort() == Type.ARRAY) { - arrayDimension++; + if (type.getSort() == Type.ARRAY) { + builder.setArrayDimension(type.getDimensions()); type = type.getElementType(); } - if (arrayDimension != 0) { - builder.setArrayDimension(arrayDimension); - } if (type.getSort() == Type.OBJECT) { FqName fqName = internalNameToFqName(type.getInternalName()); diff --git a/compiler/testData/codegen/boxWithStdlib/reflection/properties/propertyOfNestedClassAndArrayType.kt b/compiler/testData/codegen/boxWithStdlib/reflection/properties/propertyOfNestedClassAndArrayType.kt new file mode 100644 index 00000000000..87ce465fdc3 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reflection/properties/propertyOfNestedClassAndArrayType.kt @@ -0,0 +1,16 @@ +class A { + class B(val result: String) + + var p: A.B? = null + var q: Array>? = null +} + +fun box(): String { + val a = A() + + (A::q).set(a, array(array(A.B("array")))) + if (a.q!![0][0].result != "array") return "Fail array" + + (A::p).set(a, A.B("OK")) + return a.p!!.result +} diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/MultiDimensionalArrayMethod.kt b/compiler/testData/loadJava/compiledKotlin/annotations/MultiDimensionalArrayMethod.kt new file mode 100644 index 00000000000..c2f78f22e6f --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/MultiDimensionalArrayMethod.kt @@ -0,0 +1,12 @@ +//ALLOW_AST_ACCESS +package test + +annotation class Anno(val s: String) + +trait T { + Anno("foo") + fun foo(): Array>> + + Anno("bar") + val bar: Array> +} diff --git a/compiler/testData/loadJava/compiledKotlin/annotations/MultiDimensionalArrayMethod.txt b/compiler/testData/loadJava/compiledKotlin/annotations/MultiDimensionalArrayMethod.txt new file mode 100644 index 00000000000..f88f3de9b7b --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlin/annotations/MultiDimensionalArrayMethod.txt @@ -0,0 +1,13 @@ +package test + +internal final annotation class Anno : kotlin.Annotation { + /*primary*/ public constructor Anno(/*0*/ s: kotlin.String) + internal final val s: kotlin.String + internal final fun (): kotlin.String +} + +internal trait T { + test.Anno(s = "bar": kotlin.String) internal abstract val bar: kotlin.Array> + internal abstract fun (): kotlin.Array> + test.Anno(s = "foo": kotlin.String) internal abstract fun foo(): kotlin.Array>> +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 4aa78e5b6e3..f85599394b4 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -3038,6 +3038,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("propertyOfNestedClassAndArrayType.kt") + public void testPropertyOfNestedClassAndArrayType() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/properties/propertyOfNestedClassAndArrayType.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("simpleGetProperties.kt") public void testSimpleGetProperties() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/properties/simpleGetProperties.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java index ac8cce81e13..7f82b3ba42b 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java @@ -1959,6 +1959,12 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestCompiledKotlin(fileName); } + @TestMetadata("MultiDimensionalArrayMethod.kt") + public void testMultiDimensionalArrayMethod() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/MultiDimensionalArrayMethod.kt"); + doTestCompiledKotlin(fileName); + } + @TestMetadata("SimpleAnnotation.kt") public void testSimpleAnnotation() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/SimpleAnnotation.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java index dc5cc773b28..220b5061d3f 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java @@ -93,6 +93,12 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD doTest(fileName); } + @TestMetadata("MultiDimensionalArrayMethod.kt") + public void testMultiDimensionalArrayMethod() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/MultiDimensionalArrayMethod.kt"); + doTest(fileName); + } + @TestMetadata("SimpleAnnotation.kt") public void testSimpleAnnotation() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/SimpleAnnotation.kt"); diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/reflectClassUtil.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/reflectClassUtil.kt index 7776651f54d..57491bf8a30 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/reflectClassUtil.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/reflectClassUtil.kt @@ -46,7 +46,6 @@ public val Class<*>.desc: String if (this == Void.TYPE) return "V" // This is a clever exploitation of a format returned by Class.getName(): for arrays, it's almost an internal name, // but with '.' instead of '/' - // TODO: ensure there are tests on arrays of nested classes, multi-dimensional arrays, etc. return createArrayType().getName().substring(1).replace('.', '/') } diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableContainerImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableContainerImpl.kt index 52ad25aa4d3..2ac5d0f2b58 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableContainerImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableContainerImpl.kt @@ -129,7 +129,6 @@ abstract class KCallableContainerImpl { arrayDimension: Int = type.getArrayDimension() ): Class<*> { if (arrayDimension > 0) { - // TODO: test multi-dimensional arrays return loadJvmType(type, nameResolver, classLoader, arrayDimension - 1).createArrayType() } diff --git a/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java index 67e9fcd4733..76b1c09818e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/stubs/ResolveByStubTestGenerated.java @@ -87,6 +87,12 @@ public class ResolveByStubTestGenerated extends AbstractResolveByStubTest { doTest(fileName); } + @TestMetadata("MultiDimensionalArrayMethod.kt") + public void testMultiDimensionalArrayMethod() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/MultiDimensionalArrayMethod.kt"); + doTest(fileName); + } + @TestMetadata("SimpleAnnotation.kt") public void testSimpleAnnotation() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledKotlin/annotations/SimpleAnnotation.kt");