提交 029e61f5 编写于 作者: S Sébastien Deleuze

Refine MethodParameter#isOptional Kotlin implementation

This commit adds support for Continuation parameter that is now
considered as an optional parameter since it is never provided by
the user.

It also simplifies and optimizes the implementation.

Closes gh-23991
上级 79910663
...@@ -26,11 +26,9 @@ import java.lang.reflect.Parameter; ...@@ -26,11 +26,9 @@ import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors;
import kotlin.reflect.KFunction; import kotlin.reflect.KFunction;
import kotlin.reflect.KParameter; import kotlin.reflect.KParameter;
...@@ -398,7 +396,7 @@ public class MethodParameter { ...@@ -398,7 +396,7 @@ public class MethodParameter {
* either in the form of Java 8's {@link java.util.Optional}, any variant * either in the form of Java 8's {@link java.util.Optional}, any variant
* of a parameter-level {@code Nullable} annotation (such as from JSR-305 * of a parameter-level {@code Nullable} annotation (such as from JSR-305
* or the FindBugs set of annotations), or a language-level nullable type * or the FindBugs set of annotations), or a language-level nullable type
* declaration in Kotlin. * declaration or {@code Continuation} parameter in Kotlin.
* @since 4.3 * @since 4.3
*/ */
public boolean isOptional() { public boolean isOptional() {
...@@ -867,37 +865,39 @@ public class MethodParameter { ...@@ -867,37 +865,39 @@ public class MethodParameter {
private static class KotlinDelegate { private static class KotlinDelegate {
/** /**
* Check whether the specified {@link MethodParameter} represents a nullable Kotlin type * Check whether the specified {@link MethodParameter} represents a nullable Kotlin type,
* or an optional parameter (with a default value in the Kotlin declaration). * an optional parameter (with a default value in the Kotlin declaration) or a {@code Continuation} parameter
* used in suspending functions.
*/ */
public static boolean isOptional(MethodParameter param) { public static boolean isOptional(MethodParameter param) {
Method method = param.getMethod(); Method method = param.getMethod();
Constructor<?> ctor = param.getConstructor();
int index = param.getParameterIndex(); int index = param.getParameterIndex();
if (method != null && index == -1) { if (method != null && index == -1) {
KFunction<?> function = ReflectJvmMapping.getKotlinFunction(method); KFunction<?> function = ReflectJvmMapping.getKotlinFunction(method);
return (function != null && function.getReturnType().isMarkedNullable()); return (function != null && function.getReturnType().isMarkedNullable());
} }
else { KFunction<?> function;
KFunction<?> function = null; Predicate<KParameter> predicate;
Predicate<KParameter> predicate = null;
if (method != null) { if (method != null) {
if (param.parameterType.getName().equals("kotlin.coroutines.Continuation")) {
return true;
}
function = ReflectJvmMapping.getKotlinFunction(method); function = ReflectJvmMapping.getKotlinFunction(method);
predicate = p -> KParameter.Kind.VALUE.equals(p.getKind()); predicate = p -> KParameter.Kind.VALUE.equals(p.getKind());
} }
else if (ctor != null) { else {
function = ReflectJvmMapping.getKotlinFunction(ctor); function = ReflectJvmMapping.getKotlinFunction(param.getConstructor());
predicate = p -> KParameter.Kind.VALUE.equals(p.getKind()) || predicate = p -> KParameter.Kind.VALUE.equals(p.getKind()) ||
KParameter.Kind.INSTANCE.equals(p.getKind()); KParameter.Kind.INSTANCE.equals(p.getKind());
} }
if (function != null) { if (function != null) {
List<KParameter> parameters = function.getParameters(); int i = 0;
KParameter parameter = parameters for (KParameter kParameter : function.getParameters()) {
.stream() if (predicate.test(kParameter)) {
.filter(predicate) if (index == i++) {
.collect(Collectors.toList()) return (kParameter.getType().isMarkedNullable() || kParameter.isOptional());
.get(index); }
return (parameter.getType().isMarkedNullable() || parameter.isOptional()); }
} }
} }
return false; return false;
......
...@@ -20,6 +20,7 @@ import org.assertj.core.api.Assertions.assertThat ...@@ -20,6 +20,7 @@ import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import java.lang.reflect.Method import java.lang.reflect.Method
import java.lang.reflect.TypeVariable import java.lang.reflect.TypeVariable
import kotlin.coroutines.Continuation
import kotlin.reflect.full.declaredFunctions import kotlin.reflect.full.declaredFunctions
import kotlin.reflect.jvm.javaMethod import kotlin.reflect.jvm.javaMethod
...@@ -101,6 +102,13 @@ class KotlinMethodParameterTests { ...@@ -101,6 +102,13 @@ class KotlinMethodParameterTests {
assertThat(returnGenericParameterType("suspendFun8")).isEqualTo(Object::class.java) assertThat(returnGenericParameterType("suspendFun8")).isEqualTo(Object::class.java)
} }
@Test
fun `Continuation parameter is optional`() {
val method = this::class.java.getDeclaredMethod("suspendFun", String::class.java, Continuation::class.java)
assertThat(MethodParameter(method, 0).isOptional).isFalse()
assertThat(MethodParameter(method, 1).isOptional).isTrue()
}
private fun returnParameterType(funName: String) = returnMethodParameter(funName).parameterType private fun returnParameterType(funName: String) = returnMethodParameter(funName).parameterType
private fun returnGenericParameterType(funName: String) = returnMethodParameter(funName).genericParameterType private fun returnGenericParameterType(funName: String) = returnMethodParameter(funName).genericParameterType
private fun returnGenericParameterTypeName(funName: String) = returnGenericParameterType(funName).typeName private fun returnGenericParameterTypeName(funName: String) = returnGenericParameterType(funName).typeName
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册