Prenons l'exemple minimal de Kotlin suivant:
fun <U> someWrapper(supplier: () -> U): () -> (U) {
return { supplier() }
}
fun foo(taskExecutor: TaskExecutor): Int {
val future = CompletableFuture.supplyAsync(someWrapper {
42
}, taskExecutor::execute)
return future.join()
}
@Test
public void shouldFoo() {
assertThat(foo(), is(42));
}
J'ai des règles de couverture de succursales à Jacoco, qui échouent pour le code ci-dessus, disant que 1 des 2 succursales n'est pas couverte sur la ligne de l' someWrapper
appel. Malheureusement, ce n'est pas une option pour moi d'exclure toutes les classes à partir desquelles someWrapper
est appelé.
En regardant le code Java décompilé:
public final int foo(TaskExecutor taskExecutor) {
Object var10000 = WrappersKt.someWrapper((Function0)null.INSTANCE);
if (var10000 != null) {
Object var2 = var10000;
var10000 = new Foo$sam$java_util_function_Supplier$0((Function0)var2);
}
Supplier var3 = (Supplier)var10000;
Function1 var4 = (Function1)(new Function1(this.taskExecutor) {
// $FF: synthetic method
// $FF: bridge method
public Object invoke(Object var1) {
this.invoke((Runnable)var1);
return Unit.INSTANCE;
}
public final void invoke(Runnable p1) {
((TaskExecutor)this.receiver).execute(p1);
}
public final KDeclarationContainer getOwner() {
return Reflection.getOrCreateKotlinClass(TaskExecutor.class);
}
public final String getName() {
return "execute";
}
public final String getSignature() {
return "execute(Ljava/lang/Runnable;)V";
}
});
CompletableFuture future = CompletableFuture.supplyAsync(var3, (Executor)(new Foo$sam$java_util_concurrent_Executor$0(var4)));
var10000 = future.join();
Intrinsics.checkExpressionValueIsNotNull(var10000, "future.join()");
return ((Number)var10000).intValue();
}
Je pense que le problème est la if (var10000 != null)
branche, qui est même marquée par l'IDE comme inutile (toujours vrai).
Est-il possible de régler le code de manière à pouvoir couvrir toutes les branches, par exemple. en vous assurant que le compilateur ne génère pas cette vérification null supplémentaire? Je peux changer le code des deux foo(..)
et someWrapper(..)
tant que je suis en mesure de fournir un lambda décoré.
J'utilise Kotlin 1.3.50 et Jacoco 0.8.4.
ÉDITER.
Une solution de contournement évidente consiste à extraire supplyAsync(someWrapper { ... })
vers une classe utils et à exclure cette classe uniquement, c'est-à-dire:
fun <U> supplyAsync(supplier: () -> U, executor: TaskExecutor): CompletableFuture<U> {
return CompletableFuture.supplyAsync(someWrapper { supplier() }, executor::execute)
}
Ce serait assez bon pour moi, même si je suis toujours curieux de savoir pourquoi la branche est ajoutée par Kotlin, où aucune branche n'a besoin d'être.
Type inference failed
en essayant de faire compiler votre exemple de code. Ce serait génial si vous pouviez fournir un exemple de code qui fonctionne hors de la boîte! Par exemple,taskExecutor
etcontroller
sont inconnus.Réponses:
Si la valeur de retour de
someWrapper
est uniquement destinée à être utilisée comme une instance deSupplier
, vous pouvez supprimer la vérification null inutile en utilisant explicitementSupplier
comme type de retour.la source