จะครอบคลุมการตรวจสอบโมฆะที่ไม่จำเป็นที่สร้างโดย Kotlin ได้อย่างไร


9

พิจารณาตัวอย่าง 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 ซึ่งไม่สามารถใช้รหัสด้านบนได้กล่าวว่า 1 ใน 2 สาขาไม่ครอบคลุมในสายของการsomeWrapperโทร น่าเสียดายที่มันไม่มีตัวเลือกให้ฉันยกเว้นชั้นเรียนทั้งหมดที่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(..)ตราบใดที่ฉันสามารถจัดหาแลมบ์ดาที่ตกแต่งได้

ฉันใช้ 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 จึงถูกเพิ่มสาขาที่ไม่จำเป็นต้องสาขา


ฉันได้รับType inference failedเมื่อพยายามทำให้โค้ดตัวอย่างของคุณรวบรวม คงจะดีมากถ้าคุณสามารถให้โค้ดตัวอย่างที่ใช้งานได้! ตัวอย่างเช่นtaskExecutorและcontrollerไม่เป็นที่รู้จัก
Enselic

@Enselic เพิ่มการแก้ไขขนาดเล็กเพื่อลบข้อผิดพลาดที่ทำให้เสียสมาธิ ฉันจะไม่ขยายไปสู่โค้ดที่สมบูรณ์เนื่องจากมันน่าจะเพียงพอที่จะเข้าใจแนวคิด
BKE

1
ดูว่า JaCoCo นั้นปรับตัวเพื่อรองรับ Kotlin ได้อย่างไร (ดูgithub.com/jacoco/jacoco/releasesและค้นหา "เพิ่มโดยคอมไพเลอร์ Kotlin") ฉันคิดว่านี่เป็นเพียงช่องว่างที่จะได้รับการแก้ไขไม่ช้าก็เร็ว หากคุณรู้สึกจริงจังกับการเพิ่มความคุ้มครองของคุณฉันขอแนะนำให้รายงานปัญหา
PiotrK

คำตอบ:


1

หากค่าส่งคืนของsomeWrapperมีขึ้นเพื่อใช้เป็นตัวอย่างSupplierเท่านั้นคุณสามารถลบการตรวจสอบโมฆะที่ไม่จำเป็นโดยใช้Supplierประเภทการส่งคืนอย่างชัดเจน

fun <U> someWrapper(supplier: () -> U): Supplier<U> {
    return Supplier { supplier() }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.