Kotlin tarafından üretilen gereksiz null kontrolü nasıl karşılayabilirim?


9

Aşağıdaki minimal Kotlin örneğini düşünün:

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'da yukarıdaki kod için başarısız olan şube kapsamı kurallarım var, 2 şubeden 1'inin someWrapperçağrı hattında yer almadığını söylüyor . Ne yazık ki, someWrapperdenilen tüm sınıfları dışlamak benim için bir seçenek değil .

Ayrıştırılmış Java koduna bakarak:

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

Bence sorun, if (var10000 != null)IDE tarafından bile gereksiz (her zaman doğru) olarak işaretlenen şubedir.

Kodu bir şekilde tüm dalları kapsayacak şekilde ayarlamak mümkün mü, örn. derleyicinin bu ekstra boş denetimi oluşturmamasını sağlayarak? Ben ikisinin kodunu değiştirebilir foo(..)ve someWrapper(..)ben süslü bir lambda tedarik edebiliyoruz duyuyorum sürece.

Kotlin 1.3.50 ve Jacoco 0.8.4 kullanıyorum.

DÜZENLE.

Belli bir geçici çözüm, supplyAsync(someWrapper { ... })bazı utils sınıfına ayıklamak ve yalnızca bu sınıfı hariç tutmaktır.

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

Bu benim için yeterince iyi olurdu, ancak dalın neden dalın olması gerekmediği Kotlin tarafından eklendiğini merak ediyorum.


Type inference failedÖrnek kodunuzu derlemeye çalıştığımda anladım . Kutunun dışında çalışan örnek kod sağlayabilirseniz harika olurdu! Örneğin, taskExecutorve controllerbilinmeyenler.
Enselic

@Enselic, dikkat dağıtıcı hataları kaldırmak için küçük bir düzenleme ekledi. Bu fikir almak için yeterli olması gerektiği gibi tam teşekküllü kod için daha fazla genişletmek için gitmiyorum.
BKE

1
JaCoCo'nun Kotlin'i desteklemek için aşamalı olarak nasıl uyum sağladığına bakarak (bkz. Github.com/jacoco/jacoco/releases ve "Kotlin derleyicisi tarafından eklenir" araması), bunun er ya da geç düzeltilecek başka bir boşluk olduğunu düşünüyorum. Kapsamınızı doldurma konusunda ciddiyseniz, bir sorun bildirmenizi öneririz.
PiotrK

Yanıtlar:


1

Dönüş değerinin someWrapperyalnızca bir örneği olarak kullanılması gerekiyorsa , dönüş türü olarak Supplieraçıkça kullanarak gereksiz null denetimi kaldırabilirsiniz Supplier.

fun <U> someWrapper(supplier: () -> U): Supplier<U> {
    return Supplier { supplier() }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.