From fb18e4bf4c3114d6f5ee4ce8ec10143b883c5997 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 15 Sep 2016 15:41:00 +0300 Subject: [PATCH] Sort parameters of Java annotation constructors by name for stability --- .../parameters/javaAnnotationConstructor.kt | 27 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++++ .../reflect/jvm/internal/KCallableImpl.kt | 11 ++++++++ 3 files changed, 44 insertions(+) create mode 100644 compiler/testData/codegen/box/reflection/parameters/javaAnnotationConstructor.kt diff --git a/compiler/testData/codegen/box/reflection/parameters/javaAnnotationConstructor.kt b/compiler/testData/codegen/box/reflection/parameters/javaAnnotationConstructor.kt new file mode 100644 index 00000000000..123a9cc9acb --- /dev/null +++ b/compiler/testData/codegen/box/reflection/parameters/javaAnnotationConstructor.kt @@ -0,0 +1,27 @@ +// WITH_REFLECT +// FILE: J.java + +public @interface J { + short s(); + long j(); + boolean z(); + int i(); + float f(); + char c(); + double d(); +} + +// FILE: K.kt + +import kotlin.reflect.KParameter +import kotlin.test.assertEquals + +fun box(): String { + val ctor = J::class.constructors.single() + + // We sort parameters by name for consistency + assertEquals(listOf("c", "d", "f", "i", "j", "s", "z"), ctor.parameters.map { it.name }) + assert(ctor.parameters.all { it.kind == KParameter.Kind.VALUE }) + + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 32796d3b889..5d54ea75f7d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -13005,6 +13005,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("javaAnnotationConstructor.kt") + public void testJavaAnnotationConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/parameters/javaAnnotationConstructor.kt"); + doTest(fileName); + } + @TestMetadata("javaParametersHaveNoNames.kt") public void testJavaParametersHaveNoNames() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/parameters/javaParametersHaveNoNames.kt"); 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 1dd6f36bca5..f4aefbc20f9 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt @@ -18,6 +18,7 @@ package kotlin.reflect.jvm.internal import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor import java.lang.reflect.Type import java.util.* import kotlin.reflect.* @@ -53,6 +54,13 @@ internal abstract class KCallableImpl : KCallable { result.add(KParameterImpl(this, index++, KParameter.Kind.VALUE) { descriptor.valueParameters[i] }) } + // Constructor parameters of Java annotations are not ordered in any way, we order them by name here to be more stable. + // Note that positional call (via "call") is not allowed unless there's a single non-"value" parameter, + // so the order of parameters of Java annotation constructors here can be arbitrary + if (isAnnotationConstructor && descriptor is JavaCallableMemberDescriptor) { + result.sortBy { it.name } + } + result.trimToSize() result } @@ -86,6 +94,9 @@ internal abstract class KCallableImpl : KCallable { override val isAbstract: Boolean get() = descriptor.modality == Modality.ABSTRACT + private val isAnnotationConstructor: Boolean + get() = name == "" && container.jClass.isAnnotation + @Suppress("UNCHECKED_CAST") override fun call(vararg args: Any?): R = reflectionCall { return caller.call(args) as R