GH-699 Fixed a bug where Kotlin Lambda was incorrectly converted to a consumer function

Fixed consumer type

Fixed tests

Added javadoc @author tag

Resolves #699
Resolves #700
This commit is contained in:
Tsypov Dmitriy
2021-05-19 20:37:31 +07:00
committed by Oleg Zhurakousky
parent 238ac301df
commit 0db0a2f555
2 changed files with 41 additions and 11 deletions

View File

@@ -22,6 +22,7 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
import kotlin.jvm.functions.Function2;
@@ -57,6 +58,7 @@ import org.springframework.util.ObjectUtils;
*
* @author Oleg Zhurakousky
* @author Adrien Poupard
* @author Dmitriy Tsypov
* @since 2.0
*/
@Configuration
@@ -102,7 +104,7 @@ public class KotlinLambdaToFunctionAutoConfiguration {
@SuppressWarnings({ "unchecked", "rawtypes" })
public static final class KotlinFunctionWrapper implements Function<Object, Object>, Supplier<Object>, Consumer<Object[]>,
public static final class KotlinFunctionWrapper implements Function<Object, Object>, Supplier<Object>, Consumer<Object>,
Function0<Object>, Function1<Object, Object>, Function2<Object, Object, Object>,
Function3<Object, Object, Object, Object>, Function4<Object, Object, Object, Object, Object>,
FactoryBean<FunctionRegistration>,
@@ -164,7 +166,7 @@ public class KotlinLambdaToFunctionAutoConfiguration {
}
@Override
public void accept(Object[] input) {
public void accept(Object input) {
this.apply(input);
}
@@ -182,10 +184,13 @@ public class KotlinLambdaToFunctionAutoConfiguration {
FunctionRegistration<?> registration = new FunctionRegistration<>(this, name);
Type[] types = ((ParameterizedType) functionType).getActualTypeArguments();
if (functionType.getTypeName().contains("Function0")) {
if (isValidKotlinSupplier(functionType)) {
functionType = ResolvableType.forClassWithGenerics(Supplier.class, ResolvableType.forType(types[0]))
.getType();
}
else if (isValidKotlinConsumer(functionType, types)) {
functionType = ResolvableType.forClassWithGenerics(Consumer.class, ResolvableType.forType(types[0]))
.getType();
}
else if (isValidKotlinFunction(functionType, types)) {
functionType = ResolvableType.forClassWithGenerics(Function.class, ResolvableType.forType(types[0]),
@@ -221,20 +226,45 @@ public class KotlinLambdaToFunctionAutoConfiguration {
return registration;
}
private boolean isValidKotlinSupplier(Type functionType) {
return isTypeRepresentedByClass(functionType, Function0.class);
}
private boolean isValidKotlinConsumer(Type functionType, Type[] type) {
return isTypeRepresentedByClass(functionType, Function1.class) &&
type.length == 2 &&
!CoroutinesUtils.isContinuationType(type[0]) &&
isTypeRepresentedByClass(type[1], Unit.class);
}
private boolean isValidKotlinFunction(Type functionType, Type[] type) {
return functionType.getTypeName().contains(Function1.class.getName()) && type.length == 2 && !CoroutinesUtils.isContinuationType(type[0]);
return isTypeRepresentedByClass(functionType, Function1.class) &&
type.length == 2 &&
!CoroutinesUtils.isContinuationType(type[0]) &&
!isTypeRepresentedByClass(type[1], Unit.class);
}
private boolean isValidKotlinSuspendSupplier(Type functionType, Type[] type) {
return functionType.getTypeName().contains(Function1.class.getName()) && type.length == 2 && CoroutinesUtils.isContinuationFlowType(type[0]);
return isTypeRepresentedByClass(functionType, Function1.class) &&
type.length == 2 &&
CoroutinesUtils.isContinuationFlowType(type[0]);
}
private boolean isValidKotlinSuspendConsumer(Type functionType, Type[] type) {
return functionType.getTypeName().contains(Function2.class.getName()) && type.length == 3 && CoroutinesUtils.isFlowType(type[0]) && CoroutinesUtils.isContinuationUnitType(type[1]);
return isTypeRepresentedByClass(functionType, Function2.class) &&
type.length == 3 &&
CoroutinesUtils.isFlowType(type[0]) &&
CoroutinesUtils.isContinuationUnitType(type[1]);
}
private boolean isValidKotlinSuspendFunction(Type functionType, Type[] type) {
return functionType.getTypeName().contains(Function2.class.getName()) && type.length == 3 && CoroutinesUtils.isContinuationFlowType(type[1]);
return isTypeRepresentedByClass(functionType, Function2.class) &&
type.length == 3 &&
CoroutinesUtils.isContinuationFlowType(type[1]);
}
private boolean isTypeRepresentedByClass(Type type, Class<?> clazz) {
return type.getTypeName().contains(clazz.getName());
}
@Override

View File

@@ -17,6 +17,7 @@
package org.springframework.cloud.function.kotlin;
import java.lang.reflect.ParameterizedType;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -67,10 +68,9 @@ public class ContextFunctionCatalogAutoConfigurationKotlinTests {
function = this.context.getBean("kotlinConsumer");
functionType = (ParameterizedType) FunctionTypeUtils.discoverFunctionType(function, "kotlinConsumer", this.context);
assertThat(functionType.getRawType().getTypeName()).isEqualTo(Function.class.getName());
assertThat(functionType.getActualTypeArguments().length).isEqualTo(2);
assertThat(functionType.getRawType().getTypeName()).isEqualTo(Consumer.class.getName());
assertThat(functionType.getActualTypeArguments().length).isEqualTo(1);
assertThat(functionType.getActualTypeArguments()[0].getTypeName()).isEqualTo(String.class.getName());
assertThat(functionType.getActualTypeArguments()[1].getTypeName()).isEqualTo("kotlin.Unit");
function = this.context.getBean("kotlinSupplier");
functionType = (ParameterizedType) FunctionTypeUtils.discoverFunctionType(function, "kotlinSupplier", this.context);