Merge branch '6.1.x'
This commit is contained in:
@@ -32,11 +32,9 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import kotlin.jvm.JvmClassMappingKt;
|
||||
import kotlin.jvm.JvmInline;
|
||||
import kotlin.reflect.KClass;
|
||||
import kotlin.reflect.KFunction;
|
||||
import kotlin.reflect.KParameter;
|
||||
import kotlin.reflect.full.KAnnotatedElements;
|
||||
import kotlin.reflect.full.KClasses;
|
||||
import kotlin.reflect.jvm.KCallablesJvm;
|
||||
import kotlin.reflect.jvm.ReflectJvmMapping;
|
||||
@@ -874,8 +872,7 @@ public abstract class BeanUtils {
|
||||
if (primaryCtor == null) {
|
||||
return null;
|
||||
}
|
||||
if (kClass.isValue() && !KAnnotatedElements
|
||||
.findAnnotations(kClass, JvmClassMappingKt.getKotlinClass(JvmInline.class)).isEmpty()) {
|
||||
if (KotlinDetector.isInlineClass(clazz)) {
|
||||
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
|
||||
Assert.state(constructors.length == 1,
|
||||
"Kotlin value classes annotated with @JvmInline are expected to have a single JVM constructor");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -120,11 +120,17 @@ public abstract class CoroutinesUtils {
|
||||
case INSTANCE -> argMap.put(parameter, target);
|
||||
case VALUE, EXTENSION_RECEIVER -> {
|
||||
if (!parameter.isOptional() || args[index] != null) {
|
||||
if (parameter.getType().getClassifier() instanceof KClass<?> kClass && kClass.isValue()) {
|
||||
if (parameter.getType().getClassifier() instanceof KClass<?> kClass) {
|
||||
Class<?> javaClass = JvmClassMappingKt.getJavaClass(kClass);
|
||||
Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(javaClass, boxImplFilter);
|
||||
Assert.state(methods.length == 1, "Unable to find a single box-impl synthetic static method in " + javaClass.getName());
|
||||
argMap.put(parameter, ReflectionUtils.invokeMethod(methods[0], null, args[index]));
|
||||
if (KotlinDetector.isInlineClass(javaClass)) {
|
||||
Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(javaClass, boxImplFilter);
|
||||
Assert.state(methods.length == 1,
|
||||
"Unable to find a single box-impl synthetic static method in " + javaClass.getName());
|
||||
argMap.put(parameter, ReflectionUtils.invokeMethod(methods[0], null, args[index]));
|
||||
}
|
||||
else {
|
||||
argMap.put(parameter, args[index]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
argMap.put(parameter, args[index]);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,24 +35,34 @@ public abstract class KotlinDetector {
|
||||
@Nullable
|
||||
private static final Class<? extends Annotation> kotlinMetadata;
|
||||
|
||||
@Nullable
|
||||
private static final Class<? extends Annotation> kotlinJvmInline;
|
||||
|
||||
// For ConstantFieldFeature compliance, otherwise could be deduced from kotlinMetadata
|
||||
private static final boolean kotlinPresent;
|
||||
|
||||
private static final boolean kotlinReflectPresent;
|
||||
|
||||
static {
|
||||
Class<?> metadata;
|
||||
ClassLoader classLoader = KotlinDetector.class.getClassLoader();
|
||||
Class<?> metadata = null;
|
||||
Class<?> jvmInline = null;
|
||||
try {
|
||||
metadata = ClassUtils.forName("kotlin.Metadata", classLoader);
|
||||
try {
|
||||
jvmInline = ClassUtils.forName("kotlin.jvm.JvmInline", classLoader);
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JVM inline support not available
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Kotlin API not available - no Kotlin support
|
||||
metadata = null;
|
||||
}
|
||||
kotlinMetadata = (Class<? extends Annotation>) metadata;
|
||||
kotlinPresent = (kotlinMetadata != null);
|
||||
kotlinReflectPresent = ClassUtils.isPresent("kotlin.reflect.full.KClasses", classLoader);
|
||||
kotlinReflectPresent = kotlinPresent && ClassUtils.isPresent("kotlin.reflect.full.KClasses", classLoader);
|
||||
kotlinJvmInline = (Class<? extends Annotation>) jvmInline;
|
||||
}
|
||||
|
||||
|
||||
@@ -93,4 +103,14 @@ public abstract class KotlinDetector {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given {@code Class} is an inline class
|
||||
* (annotated with {@code @JvmInline}).
|
||||
* @since 6.1.5
|
||||
* @see <a href="https://kotlinlang.org/docs/inline-classes.html">Kotlin inline value classes</a>
|
||||
*/
|
||||
public static boolean isInlineClass(Class<?> clazz) {
|
||||
return (kotlinJvmInline != null && clazz.getDeclaredAnnotation(kotlinJvmInline) != null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.core
|
||||
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
/**
|
||||
* Kotlin tests for [KotlinDetector].
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
*/
|
||||
class KotlinDetectorTests {
|
||||
|
||||
@Test
|
||||
fun isKotlinType() {
|
||||
Assertions.assertThat(KotlinDetector.isKotlinType(KotlinDetectorTests::class.java)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isNotKotlinType() {
|
||||
Assertions.assertThat(KotlinDetector.isKotlinType(KotlinDetector::class.java)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isInlineClass() {
|
||||
Assertions.assertThat(KotlinDetector.isInlineClass(ValueClass::class.java)).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isNotInlineClass() {
|
||||
Assertions.assertThat(KotlinDetector.isInlineClass(KotlinDetector::class.java)).isFalse()
|
||||
Assertions.assertThat(KotlinDetector.isInlineClass(KotlinDetectorTests::class.java)).isFalse()
|
||||
}
|
||||
|
||||
@JvmInline
|
||||
value class ValueClass(val value: String)
|
||||
|
||||
}
|
||||
@@ -319,11 +319,17 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
case INSTANCE -> argMap.put(parameter, target);
|
||||
case VALUE, EXTENSION_RECEIVER -> {
|
||||
if (!parameter.isOptional() || args[index] != null) {
|
||||
if (parameter.getType().getClassifier() instanceof KClass<?> kClass && kClass.isValue()) {
|
||||
if (parameter.getType().getClassifier() instanceof KClass<?> kClass) {
|
||||
Class<?> javaClass = JvmClassMappingKt.getJavaClass(kClass);
|
||||
Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(javaClass, boxImplFilter);
|
||||
Assert.state(methods.length == 1, "Unable to find a single box-impl synthetic static method in " + javaClass.getName());
|
||||
argMap.put(parameter, ReflectionUtils.invokeMethod(methods[0], null, args[index]));
|
||||
if (KotlinDetector.isInlineClass(javaClass)) {
|
||||
Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(javaClass, boxImplFilter);
|
||||
Assert.state(methods.length == 1,
|
||||
"Unable to find a single box-impl synthetic static method in " + javaClass.getName());
|
||||
argMap.put(parameter, ReflectionUtils.invokeMethod(methods[0], null, args[index]));
|
||||
}
|
||||
else {
|
||||
argMap.put(parameter, args[index]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
argMap.put(parameter, args[index]);
|
||||
|
||||
@@ -330,11 +330,17 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||
case INSTANCE -> argMap.put(parameter, target);
|
||||
case VALUE, EXTENSION_RECEIVER -> {
|
||||
if (!parameter.isOptional() || args[index] != null) {
|
||||
if (parameter.getType().getClassifier() instanceof KClass<?> kClass && kClass.isValue()) {
|
||||
if (parameter.getType().getClassifier() instanceof KClass<?> kClass) {
|
||||
Class<?> javaClass = JvmClassMappingKt.getJavaClass(kClass);
|
||||
Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(javaClass, boxImplFilter);
|
||||
Assert.state(methods.length == 1, "Unable to find a single box-impl synthetic static method in " + javaClass.getName());
|
||||
argMap.put(parameter, ReflectionUtils.invokeMethod(methods[0], null, args[index]));
|
||||
if (KotlinDetector.isInlineClass(javaClass)) {
|
||||
Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(javaClass, boxImplFilter);
|
||||
Assert.state(methods.length == 1,
|
||||
"Unable to find a single box-impl synthetic static method in " + javaClass.getName());
|
||||
argMap.put(parameter, ReflectionUtils.invokeMethod(methods[0], null, args[index]));
|
||||
}
|
||||
else {
|
||||
argMap.put(parameter, args[index]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
argMap.put(parameter, args[index]);
|
||||
|
||||
Reference in New Issue
Block a user