Skip to content

Commit 0e49e32

Browse files
diesieben07sdeleuze
authored andcommitted
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
1 parent 2be2aa7 commit 0e49e32

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

spring-core/src/main/java/org/springframework/core/KotlinReflectionParameterNameDiscoverer.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,15 @@ public String[] getParameterNames(Constructor<?> ctor) {
7575
private String[] getParameterNames(List<KParameter> parameters) {
7676
List<KParameter> filteredParameters = parameters
7777
.stream()
78-
.filter(p -> KParameter.Kind.VALUE.equals(p.getKind()))
78+
// Extension receivers of extension methods must be included as they appear as normal method parameters in Java
79+
.filter(p -> KParameter.Kind.VALUE.equals(p.getKind()) || KParameter.Kind.EXTENSION_RECEIVER.equals(p.getKind()))
7980
.collect(Collectors.toList());
8081
String[] parameterNames = new String[filteredParameters.size()];
8182
for (int i = 0; i < filteredParameters.size(); i++) {
82-
String name = filteredParameters.get(i).getName();
83+
KParameter parameter = filteredParameters.get(i);
84+
// extension receivers are not explicitly named, but require a name for Java interoperability
85+
// $receiver is not a valid Kotlin identifier, but valid in Java, so it can be used here
86+
String name = KParameter.Kind.EXTENSION_RECEIVER.equals(parameter.getKind()) ? "$receiver" : parameter.getName();
8387
if (name == null) {
8488
return null;
8589
}

spring-core/src/test/kotlin/org/springframework/core/KotlinReflectionParameterNameDiscovererTests.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,22 @@ class KotlinReflectionParameterNameDiscovererTests {
4242
assertThat(actualParams, `is`(arrayOf("message")))
4343
}
4444

45+
@Test
46+
fun getParameterNamesOnExtensionMethod() {
47+
val method = ReflectionUtils.findMethod(UtilityClass::class.java, "identity", String::class.java)!!
48+
val actualParams = parameterNameDiscoverer.getParameterNames(method)!!
49+
assertThat(actualParams, `is`(arrayOf("\$receiver")))
50+
}
51+
4552
interface MessageService {
4653
fun sendMessage(message: String)
4754
}
4855

4956
class MessageServiceImpl {
5057
fun sendMessage(message: String) = message
5158
}
59+
60+
class UtilityClass {
61+
fun String.identity() = this
62+
}
5263
}

0 commit comments

Comments
 (0)