From 0e49e321889d23828c5307842ac25d444ce7ec88 Mon Sep 17 00:00:00 2001 From: diesieben07 Date: Thu, 26 Oct 2017 15:09:32 +0200 Subject: [PATCH] Handle parameters of Kotlin extension methods correctly The EXTENSION_RECEIVER parameter of Kotlin's extension methods appear as normal method parameters to Java and thus require a name. The synthetic name "$receiver" is used here, as it is not a valid Kotlin identifier, but valid in Java. Issue: SPR-16119 --- .../core/KotlinReflectionParameterNameDiscoverer.java | 8 ++++++-- .../KotlinReflectionParameterNameDiscovererTests.kt | 11 +++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/KotlinReflectionParameterNameDiscoverer.java b/spring-core/src/main/java/org/springframework/core/KotlinReflectionParameterNameDiscoverer.java index f368a72b4e..129a364a3f 100644 --- a/spring-core/src/main/java/org/springframework/core/KotlinReflectionParameterNameDiscoverer.java +++ b/spring-core/src/main/java/org/springframework/core/KotlinReflectionParameterNameDiscoverer.java @@ -75,11 +75,15 @@ public class KotlinReflectionParameterNameDiscoverer implements ParameterNameDis private String[] getParameterNames(List parameters) { List filteredParameters = parameters .stream() - .filter(p -> KParameter.Kind.VALUE.equals(p.getKind())) + // Extension receivers of extension methods must be included as they appear as normal method parameters in Java + .filter(p -> KParameter.Kind.VALUE.equals(p.getKind()) || KParameter.Kind.EXTENSION_RECEIVER.equals(p.getKind())) .collect(Collectors.toList()); String[] parameterNames = new String[filteredParameters.size()]; for (int i = 0; i < filteredParameters.size(); i++) { - String name = filteredParameters.get(i).getName(); + KParameter parameter = filteredParameters.get(i); + // extension receivers are not explicitly named, but require a name for Java interoperability + // $receiver is not a valid Kotlin identifier, but valid in Java, so it can be used here + String name = KParameter.Kind.EXTENSION_RECEIVER.equals(parameter.getKind()) ? "$receiver" : parameter.getName(); if (name == null) { return null; } diff --git a/spring-core/src/test/kotlin/org/springframework/core/KotlinReflectionParameterNameDiscovererTests.kt b/spring-core/src/test/kotlin/org/springframework/core/KotlinReflectionParameterNameDiscovererTests.kt index 5baa8b3091..c091f294d7 100644 --- a/spring-core/src/test/kotlin/org/springframework/core/KotlinReflectionParameterNameDiscovererTests.kt +++ b/spring-core/src/test/kotlin/org/springframework/core/KotlinReflectionParameterNameDiscovererTests.kt @@ -42,6 +42,13 @@ class KotlinReflectionParameterNameDiscovererTests { assertThat(actualParams, `is`(arrayOf("message"))) } + @Test + fun getParameterNamesOnExtensionMethod() { + val method = ReflectionUtils.findMethod(UtilityClass::class.java, "identity", String::class.java)!! + val actualParams = parameterNameDiscoverer.getParameterNames(method)!! + assertThat(actualParams, `is`(arrayOf("\$receiver"))) + } + interface MessageService { fun sendMessage(message: String) } @@ -49,4 +56,8 @@ class KotlinReflectionParameterNameDiscovererTests { class MessageServiceImpl { fun sendMessage(message: String) = message } + + class UtilityClass { + fun String.identity() = this + } }