Sort parameters of Java annotation constructors by name for stability

This commit is contained in:
Alexander Udalov
2016-09-15 15:41:00 +03:00
parent d6daaf0a85
commit fb18e4bf4c
3 changed files with 44 additions and 0 deletions
@@ -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"
}
@@ -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");
@@ -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<out R> : KCallable<R> {
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<out R> : KCallable<R> {
override val isAbstract: Boolean
get() = descriptor.modality == Modality.ABSTRACT
private val isAnnotationConstructor: Boolean
get() = name == "<init>" && container.jClass.isAnnotation
@Suppress("UNCHECKED_CAST")
override fun call(vararg args: Any?): R = reflectionCall {
return caller.call(args) as R