如何覆盖Kotlin生成的不必要的空检查?

BKE

考虑以下最小的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));
}

我在Jacoco中有分支覆盖规则,该规则对于上面的代码失败,说someWrapper呼叫行未覆盖2个分支中的1个不幸的是,对于我来说,排除所有someWrapper被调用的类不是一个选择

查看反编译的Java代码:

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();
}

我认为,问题出在if (var10000 != null)分支上,IDE甚至将其标记为不必要分支(总是如此)。

是否可以通过某种方式调整代码,以便覆盖所有分支,例如。通过确保编译器不会生成该额外的空检查?我可以更改的代码foo(..),并someWrapper(..)为我能够提供一个装饰lambda作为长。

我使用Kotlin 1.3.50和Jacoco 0.8.4。

编辑。

一个明显的解决方法是提取supplyAsync(someWrapper { ... })到某些utils类,并仅排除该类,即:

fun <U> supplyAsync(supplier: () -> U, executor: TaskExecutor): CompletableFuture<U> {
    return CompletableFuture.supplyAsync(someWrapper { supplier() }, executor::execute)
}

这对我来说已经足够了,尽管我仍然很好奇为什么Kotlin会添加分支,而无需分支。

狮子座阿苏

如果的返回值someWrapper仅打算用作的实例Supplier,则可以通过显式使用Supplier作为返回类型来删除不必要的空检查

fun <U> someWrapper(supplier: () -> U): Supplier<U> {
    return Supplier { supplier() }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章