Provide equals/hashCode/toString for KParameter implementation

Two KParameter instances are equal iff their backing descriptors are equal and
their callables are equal
This commit is contained in:
Alexander Udalov
2015-08-24 17:33:36 +03:00
parent d4825cf4f0
commit d36ef90dd6
5 changed files with 97 additions and 0 deletions
@@ -0,0 +1,26 @@
import kotlin.test.*
class A {
fun foo(s: String, x: Int) {}
fun bar(x: Int) {}
val baz = 42
}
fun box(): String {
// Dispatch receiver parameters of different callables are not equal
assertNotEquals(A::foo.parameters[0], A::bar.parameters[0])
assertNotEquals(A::foo.parameters[0], A::baz.parameters[0])
assertNotEquals(A::foo.parameters[1], A::bar.parameters[1])
assertNotEquals(A::foo.parameters[1], A::foo.parameters[2])
assertNotEquals(A::bar.parameters[1], A::foo.parameters[2])
assertEquals(A::foo.parameters[0], A::foo.parameters[0])
assertEquals(A::foo.parameters[0].hashCode(), A::foo.parameters[0].hashCode())
assertEquals(A::foo.parameters[1], A::foo.parameters[1])
assertEquals(A::foo.parameters[1].hashCode(), A::foo.parameters[1].hashCode())
assertEquals(A::bar.parameters[0], A::bar.parameters[0])
assertEquals(A::bar.parameters[0].hashCode(), A::bar.parameters[0].hashCode())
return "OK"
}
@@ -0,0 +1,28 @@
import kotlin.test.*
fun Int.foo(s: String) {}
class A {
fun bar() {}
}
fun baz(name: String) {}
fun box(): String {
assertEquals(
listOf("extension receiver of ${Int::foo}", "parameter #1 s of ${Int::foo}"),
Int::foo.parameters.map(Any::toString)
)
assertEquals(
listOf("instance of ${A::bar}"),
A::bar.parameters.map(Any::toString)
)
assertEquals(
listOf("parameter #0 name of ${::baz}"),
::baz.parameters.map(Any::toString)
)
return "OK"
}
@@ -3492,6 +3492,18 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
doTestWithStdlib(fileName);
}
@TestMetadata("parametersEqualsHashCode.kt")
public void testParametersEqualsHashCode() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/methodsFromAny/parametersEqualsHashCode.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("parametersToString.kt")
public void testParametersToString() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/methodsFromAny/parametersToString.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("propertyEqualsHashCode.kt")
public void testPropertyEqualsHashCode() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/methodsFromAny/propertyEqualsHashCode.kt");
@@ -41,4 +41,13 @@ class KParameterImpl(
override val type: KType
get() = KTypeImpl(descriptor.type) { callable.caller.parameterTypes[index] }
override fun equals(other: Any?) =
other is KParameterImpl && callable == other.callable && descriptor == other.descriptor
override fun hashCode() =
(callable.hashCode() * 31) + descriptor.hashCode()
override fun toString() =
ReflectionObjectRenderer.renderParameter(this)
}
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.types.JetType
import kotlin.reflect.KParameter
object ReflectionObjectRenderer {
private val renderer = DescriptorRenderer.FQ_NAMES_IN_TYPES
@@ -47,6 +48,14 @@ object ReflectionObjectRenderer {
append(renderer.renderName(callable.name))
}
fun renderCallable(descriptor: CallableDescriptor): String {
return when (descriptor) {
is PropertyDescriptor -> renderProperty(descriptor)
is FunctionDescriptor -> renderFunction(descriptor)
else -> error("Illegal callable: $descriptor")
}
}
// TODO: include visibility, return type
fun renderProperty(descriptor: PropertyDescriptor): String {
return StringBuilder {
@@ -69,6 +78,19 @@ object ReflectionObjectRenderer {
}.toString()
}
fun renderParameter(parameter: KParameterImpl): String {
return StringBuilder {
when (parameter.kind) {
KParameter.Kind.EXTENSION_RECEIVER -> append("extension receiver")
KParameter.Kind.INSTANCE -> append("instance")
KParameter.Kind.VALUE -> append("parameter #${parameter.index} ${parameter.name}")
}
append(" of ")
append(renderCallable(parameter.callable.descriptor))
}.toString()
}
fun renderType(type: JetType): String {
return renderer.renderType(type)
}