Hãy xem xét ví dụ về Kotlin tối thiểu sau đây:
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));
}
Tôi có các quy tắc bảo hiểm chi nhánh trong Jacoco, không thành công cho mã ở trên, nói rằng 1 trong 2 chi nhánh không nằm trong dòng của someWrapper
cuộc gọi. Thật không may, nó không phải là một lựa chọn cho tôi để loại trừ tất cả các lớp someWrapper
được gọi.
Nhìn vào mã Java được dịch ngược:
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();
}
Tôi nghĩ, vấn đề là if (var10000 != null)
nhánh, thậm chí được IDE đánh dấu là không cần thiết (luôn luôn đúng).
Có phải bằng cách nào đó có thể điều chỉnh mã sao cho có thể bao gồm tất cả các nhánh, ví dụ. bằng cách đảm bảo trình biên dịch không tạo thêm kiểm tra null? Tôi có thể thay đổi mã của cả hai foo(..)
và someWrapper(..)
miễn là tôi có thể cung cấp lambda được trang trí.
Tôi sử dụng Kotlin 1.3.50 và Jacoco 0.8.4.
BIÊN TẬP.
Một cách giải quyết rõ ràng là trích xuất supplyAsync(someWrapper { ... })
vào một số lớp utils và chỉ loại trừ lớp đó, tức là:
fun <U> supplyAsync(supplier: () -> U, executor: TaskExecutor): CompletableFuture<U> {
return CompletableFuture.supplyAsync(someWrapper { supplier() }, executor::execute)
}
Điều này sẽ đủ tốt cho tôi, mặc dù tôi vẫn tò mò tại sao chi nhánh được thêm bởi Kotlin, nơi không cần chi nhánh.
Type inference failed
khi cố gắng để biên dịch mã mẫu của bạn. Sẽ thật tuyệt nếu bạn có thể cung cấp mã mẫu hoạt động tốt! Ví dụ,taskExecutor
vàcontroller
là ẩn số.