[Gradle] Implement Future<T>.map(transform)

^KT-59446 In Progress
This commit is contained in:
Sebastian Sellmair
2023-06-20 10:58:42 +02:00
committed by Space Team
parent ec46c82a13
commit d3d6cdcef7
2 changed files with 72 additions and 0 deletions
@@ -55,6 +55,10 @@ internal interface CompletableFuture<T> : Future<T> {
fun complete(value: T)
}
internal fun <T, R> Future<T>.map(transform: (T) -> R): Future<R> {
return MappedFutureImpl(this, transform)
}
internal fun CompletableFuture<Unit>.complete() = complete(Unit)
/**
@@ -127,6 +131,38 @@ private class FutureImpl<T>(
}
}
private class MappedFutureImpl<T, R>(
private val future: Future<T>,
private var transform: (T) -> R,
) : Future<R>, Serializable {
private val value = Completable<R>()
override suspend fun await(): R {
if (value.isCompleted) return value.getCompleted()
value.complete(transform(future.await()))
transform = { throw IllegalStateException("Unexpected 'transform' in future") }
return value.getCompleted()
}
override fun getOrThrow(): R {
if (value.isCompleted) return value.getCompleted()
value.complete(transform(future.getOrThrow()))
transform = { throw IllegalStateException("Unexpected 'transform' in future") }
return value.getCompleted()
}
private fun writeReplace(): Any {
return Surrogate(getOrThrow())
}
private class Surrogate<T>(private val value: T) : Serializable {
private fun readResolve(): Any {
return FutureImpl(Completable(value))
}
}
}
private class LenientFutureImpl<T>(
private val future: Future<T>,
) : LenientFuture<T>, Serializable {
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.gradle.idea.testFixtures.utils.serialize
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.IllegalLifecycleException
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.FinaliseDsl
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.ReadyForExecution
import org.jetbrains.kotlin.gradle.util.buildProject
import org.jetbrains.kotlin.gradle.util.runLifecycleAwareTest
import org.jetbrains.kotlin.gradle.utils.*
@@ -114,4 +115,39 @@ class FutureTest {
assertEquals(1, futureInvocations.get())
}
}
@Test
fun `test - future map`() = project.runLifecycleAwareTest {
val future = project.future { "1" }
val transformInvocations = AtomicInteger(0)
val mappedFuture = future.map { value ->
transformInvocations.incrementAndGet()
value.toInt()
}
assertEquals(1, mappedFuture.await())
assertEquals(1, mappedFuture.getOrThrow())
assertEquals(1, transformInvocations.get())
val deserializedMappedFuture = mappedFuture.serialize().deserialize() as Future<*>
assertEquals(1, deserializedMappedFuture.await())
assertEquals(1, deserializedMappedFuture.getOrThrow())
}
@Test
fun `test - future map - getOrThrow - exception`() = project.runLifecycleAwareTest {
val future = project.future {
ReadyForExecution.await()
"1"
}
val mappedFuture = future.map {
it.toInt()
}
assertFailsWith<IllegalLifecycleException> { mappedFuture.getOrThrow() }
future.await()
assertEquals(1, mappedFuture.getOrThrow())
}
}