Considere o seguinte exemplo mínimo de Kotlin:
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));
}
Tenho regras de cobertura de filial em Jacoco, que falham no código acima, dizendo que 1 de 2 agências não é coberta na linha da someWrapper
chamada. Infelizmente, não é uma opção para mim excluir todas as classes das quais someWrapper
é chamada.
Observando o código Java descompilado:
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();
}
Penso que o problema é o if (var10000 != null)
ramo, que é até marcado pelo IDE como desnecessário (sempre verdadeiro).
É de alguma forma possível ajustar o código de forma que seja possível cobrir todos os ramos, por exemplo. certificando-se de que o compilador não gere essa verificação nula extra? Posso alterar o código de ambos foo(..)
e someWrapper(..)
desde que eu seja capaz de fornecer um lambda decorado.
Eu uso o Kotlin 1.3.50 e o Jacoco 0.8.4.
EDITAR.
Uma solução óbvia é extrair supplyAsync(someWrapper { ... })
para algumas classes de utilitários e excluir apenas essa classe, ou seja:
fun <U> supplyAsync(supplier: () -> U, executor: TaskExecutor): CompletableFuture<U> {
return CompletableFuture.supplyAsync(someWrapper { supplier() }, executor::execute)
}
Isso seria bom o suficiente para mim, embora ainda esteja curioso para saber por que o ramo é adicionado por Kotlin, onde nenhum ramo precisa estar.
Type inference failed
ao tentar fazer seu código de amostra compilar. Seria ótimo se você pudesse fornecer um código de exemplo que funcione imediatamente! Por exemplo,taskExecutor
econtroller
são desconhecidos.Respostas:
Se o valor de retorno de
someWrapper
for usado apenas como uma instância deSupplier
, você poderá remover a verificação nula desnecessária usando explicitamenteSupplier
como o tipo de retorno.fonte