Treat Kotlin nullable as non-required
Where `isOptional` is used, also check for `isNullable` i.e. values are not considered required if they are Kotlin nullables: - spring-messaging: named value method arguments - spring-web: named value method arguments - spring-webmvc: request parts This means that Kotlin client code no longer has to explicity specify "required=false" for Kotlin nullables -- this information is inferred automatically by the framework. Issue: SPR-14165
This commit is contained in:
committed by
Sebastien Deleuze
parent
735e288d46
commit
fada91e538
@@ -30,6 +30,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.KotlinUtils;
|
||||
|
||||
/**
|
||||
* Helper class that encapsulates the specification of a method parameter, i.e. a {@link Method}
|
||||
@@ -329,6 +330,16 @@ public class MethodParameter {
|
||||
return (isOptional() ? nested() : this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this method parameter is declared as a "nullable" value, if supported by
|
||||
* the underlying language. Currently the only supported language is Kotlin.
|
||||
* @since 5.0
|
||||
*/
|
||||
public boolean isNullable() {
|
||||
return KotlinUtils.isKotlinPresent() &&
|
||||
KotlinUtils.isKotlinClass(getContainingClass()) &&
|
||||
KotlinUtils.isNullable(this.parameterIndex, this.method, this.constructor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a containing class to resolve the parameter type against.
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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
|
||||
*
|
||||
* http://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.util;
|
||||
|
||||
import kotlin.Metadata;
|
||||
import kotlin.reflect.KFunction;
|
||||
import kotlin.reflect.KParameter;
|
||||
import kotlin.reflect.jvm.ReflectJvmMapping;
|
||||
import org.springframework.core.MethodParameter;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Miscellaneous Kotlin utility methods.
|
||||
*
|
||||
* @author Raman Gupta
|
||||
* @since 5.0
|
||||
*/
|
||||
public class KotlinUtils {
|
||||
|
||||
private static final boolean kotlinPresent;
|
||||
|
||||
static {
|
||||
kotlinPresent = ClassUtils.isPresent("kotlin.Unit", MethodParameter.class.getClassLoader());
|
||||
}
|
||||
|
||||
public static boolean isKotlinPresent() {
|
||||
return kotlinPresent;
|
||||
}
|
||||
|
||||
public static boolean isKotlinClass(Class<?> type) {
|
||||
return type != null && type.getDeclaredAnnotation(Metadata.class) != null;
|
||||
}
|
||||
|
||||
public static boolean isNullable(int parameterIndex, Method method, Constructor<?> constructor) {
|
||||
if(parameterIndex < 0) {
|
||||
KFunction<?> function = ReflectJvmMapping.getKotlinFunction(method);
|
||||
return function != null && function.getReturnType().isMarkedNullable();
|
||||
} else {
|
||||
KFunction<?> function = method != null ?
|
||||
ReflectJvmMapping.getKotlinFunction(method) :
|
||||
ReflectJvmMapping.getKotlinFunction(constructor);
|
||||
if(function != null) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<KParameter> parameters = function.getParameters();
|
||||
return parameters
|
||||
.stream()
|
||||
.filter(p -> KParameter.Kind.VALUE.equals(p.getKind()))
|
||||
.collect(Collectors.toList())
|
||||
.get(parameterIndex)
|
||||
.getType()
|
||||
.isMarkedNullable();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user