Efficient Kotlin metadata detection
Follow-up of 3991ab4a23.
Issue: SPR-15673
This commit is contained in:
@@ -58,8 +58,20 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public class MethodParameter {
|
||||
|
||||
private static final boolean kotlinPresent =
|
||||
ClassUtils.isPresent("kotlin.Metadata", MethodParameter.class.getClassLoader());
|
||||
@Nullable
|
||||
private static final Class<?> kotlinMetadata;
|
||||
|
||||
static {
|
||||
Class<?> metadata;
|
||||
try {
|
||||
metadata = ClassUtils.forName("kotlin.Metadata", MethodParameter.class.getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Kotlin API not available - no Kotlin support
|
||||
metadata = null;
|
||||
}
|
||||
kotlinMetadata = metadata;
|
||||
}
|
||||
|
||||
|
||||
private final Executable executable;
|
||||
@@ -341,7 +353,16 @@ public class MethodParameter {
|
||||
*/
|
||||
public boolean isOptional() {
|
||||
return (getParameterType() == Optional.class || hasNullableAnnotation() ||
|
||||
(kotlinPresent && KotlinDelegate.isNullable(this)));
|
||||
(useKotlinSupport(this.getContainingClass()) && KotlinDelegate.isNullable(this)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if Kotlin is present and if the specified class is a Kotlin one.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static boolean useKotlinSupport(Class<?> clazz) {
|
||||
return (kotlinMetadata != null &&
|
||||
clazz.getDeclaredAnnotation((Class<? extends Annotation>) kotlinMetadata) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -736,41 +757,30 @@ public class MethodParameter {
|
||||
* Check whether the specified {@link MethodParameter} represents a nullable Kotlin type or not.
|
||||
*/
|
||||
public static boolean isNullable(MethodParameter param) {
|
||||
if (isKotlinClass(param.getContainingClass())) {
|
||||
Method method = param.getMethod();
|
||||
Constructor<?> ctor = param.getConstructor();
|
||||
int index = param.getParameterIndex();
|
||||
if (method != null && index == -1) {
|
||||
KFunction<?> function = ReflectJvmMapping.getKotlinFunction(method);
|
||||
return (function != null && function.getReturnType().isMarkedNullable());
|
||||
}
|
||||
else {
|
||||
KFunction<?> function = null;
|
||||
if (method != null) {
|
||||
function = ReflectJvmMapping.getKotlinFunction(method);
|
||||
}
|
||||
else if (ctor != null) {
|
||||
function = ReflectJvmMapping.getKotlinFunction(ctor);
|
||||
}
|
||||
if (function != null) {
|
||||
List<KParameter> parameters = function.getParameters();
|
||||
return parameters
|
||||
.stream()
|
||||
.filter(p -> KParameter.Kind.VALUE.equals(p.getKind()))
|
||||
.collect(Collectors.toList())
|
||||
.get(index)
|
||||
.getType()
|
||||
.isMarkedNullable();
|
||||
}
|
||||
}
|
||||
Method method = param.getMethod();
|
||||
Constructor<?> ctor = param.getConstructor();
|
||||
int index = param.getParameterIndex();
|
||||
if (method != null && index == -1) {
|
||||
KFunction<?> function = ReflectJvmMapping.getKotlinFunction(method);
|
||||
return (function != null && function.getReturnType().isMarkedNullable());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isKotlinClass(Class<?> clazz) {
|
||||
for (Annotation annotation : clazz.getDeclaredAnnotations()) {
|
||||
if (annotation.annotationType().getName().equals("kotlin.Metadata")) {
|
||||
return true;
|
||||
else {
|
||||
KFunction<?> function = null;
|
||||
if (method != null) {
|
||||
function = ReflectJvmMapping.getKotlinFunction(method);
|
||||
}
|
||||
else if (ctor != null) {
|
||||
function = ReflectJvmMapping.getKotlinFunction(ctor);
|
||||
}
|
||||
if (function != null) {
|
||||
List<KParameter> parameters = function.getParameters();
|
||||
return parameters
|
||||
.stream()
|
||||
.filter(p -> KParameter.Kind.VALUE.equals(p.getKind()))
|
||||
.collect(Collectors.toList())
|
||||
.get(index)
|
||||
.getType()
|
||||
.isMarkedNullable();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user