From 7646895fd471601c364ab5bdcad17484d90a46b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Wed, 13 Nov 2019 14:22:11 +0100 Subject: [PATCH] Support Kotlin synthetic classes in MethodParameter and SpEL Closes gh-23812 --- .../springframework/core/MethodParameter.java | 24 +++++++++++----- spring-expression/spring-expression.gradle | 4 +++ .../expression/spel/KotlinSpelReproTests.kt | 28 +++++++++++++++++++ 3 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 spring-expression/src/test/kotlin/org/springframework/expression/spel/KotlinSpelReproTests.kt diff --git a/spring-core/src/main/java/org/springframework/core/MethodParameter.java b/spring-core/src/main/java/org/springframework/core/MethodParameter.java index f012500224..040819bea6 100644 --- a/spring-core/src/main/java/org/springframework/core/MethodParameter.java +++ b/spring-core/src/main/java/org/springframework/core/MethodParameter.java @@ -908,9 +908,14 @@ public class MethodParameter { * functions via Kotlin reflection. */ static private Type getGenericReturnType(Method method) { - KFunction function = ReflectJvmMapping.getKotlinFunction(method); - if (function != null && function.isSuspend()) { - return ReflectJvmMapping.getJavaType(function.getReturnType()); + try { + KFunction function = ReflectJvmMapping.getKotlinFunction(method); + if (function != null && function.isSuspend()) { + return ReflectJvmMapping.getJavaType(function.getReturnType()); + } + } + catch (UnsupportedOperationException ex) { + // probably a synthetic class - let's use java reflection instead } return method.getGenericReturnType(); } @@ -920,10 +925,15 @@ public class MethodParameter { * functions via Kotlin reflection. */ static private Class getReturnType(Method method) { - KFunction function = ReflectJvmMapping.getKotlinFunction(method); - if (function != null && function.isSuspend()) { - Type paramType = ReflectJvmMapping.getJavaType(function.getReturnType()); - return ResolvableType.forType(paramType).resolve(method.getReturnType()); + try { + KFunction function = ReflectJvmMapping.getKotlinFunction(method); + if (function != null && function.isSuspend()) { + Type paramType = ReflectJvmMapping.getJavaType(function.getReturnType()); + return ResolvableType.forType(paramType).resolve(method.getReturnType()); + } + } + catch (UnsupportedOperationException ex) { + // probably a synthetic class - let's use java reflection instead } return method.getReturnType(); } diff --git a/spring-expression/spring-expression.gradle b/spring-expression/spring-expression.gradle index 5dbf54e594..432179877a 100644 --- a/spring-expression/spring-expression.gradle +++ b/spring-expression/spring-expression.gradle @@ -1,5 +1,9 @@ description = "Spring Expression Language (SpEL)" +apply plugin: "kotlin" + dependencies { compile(project(":spring-core")) + testCompile("org.jetbrains.kotlin:kotlin-reflect") + testCompile("org.jetbrains.kotlin:kotlin-stdlib") } diff --git a/spring-expression/src/test/kotlin/org/springframework/expression/spel/KotlinSpelReproTests.kt b/spring-expression/src/test/kotlin/org/springframework/expression/spel/KotlinSpelReproTests.kt new file mode 100644 index 0000000000..12a01978ac --- /dev/null +++ b/spring-expression/src/test/kotlin/org/springframework/expression/spel/KotlinSpelReproTests.kt @@ -0,0 +1,28 @@ +package org.springframework.expression.spel + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.expression.ExpressionParser +import org.springframework.expression.spel.standard.SpelExpressionParser + +class KotlinSpelReproTests { + + private val parser: ExpressionParser = SpelExpressionParser() + + private val context = TestScenarioCreator.getTestEvaluationContext() + + + @Test + fun `gh-23812 SpEL cannot invoke Kotlin synthetic classes`() { + val expr = parser.parseExpression("new org.springframework.expression.spel.KotlinSpelReproTests\$Config().kotlinSupplier().invoke()") + assertThat(expr.getValue(context)).isEqualTo("test") + } + + class Config { + + fun kotlinSupplier(): () -> String { + return { "test" } + } + + } +}