Skip to content

Commit 0d1932e

Browse files
sellmairSpace Team
authored and
Space Team
committed
[Gradle] Implement Future<T>.map(transform)
^KT-59446 In Progress (cherry picked from commit d3d6cdc)
1 parent bbf64b1 commit 0d1932e

File tree

2 files changed

+72
-0
lines changed
  • libraries/tools/kotlin-gradle-plugin/src
    • common/kotlin/org/jetbrains/kotlin/gradle/utils
    • functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests

2 files changed

+72
-0
lines changed

libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/Future.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ internal interface CompletableFuture<T> : Future<T> {
5555
fun complete(value: T)
5656
}
5757

58+
internal fun <T, R> Future<T>.map(transform: (T) -> R): Future<R> {
59+
return MappedFutureImpl(this, transform)
60+
}
61+
5862
internal fun CompletableFuture<Unit>.complete() = complete(Unit)
5963

6064
/**
@@ -127,6 +131,38 @@ private class FutureImpl<T>(
127131
}
128132
}
129133

134+
private class MappedFutureImpl<T, R>(
135+
private val future: Future<T>,
136+
private var transform: (T) -> R,
137+
) : Future<R>, Serializable {
138+
139+
private val value = Completable<R>()
140+
141+
override suspend fun await(): R {
142+
if (value.isCompleted) return value.getCompleted()
143+
value.complete(transform(future.await()))
144+
transform = { throw IllegalStateException("Unexpected 'transform' in future") }
145+
return value.getCompleted()
146+
}
147+
148+
override fun getOrThrow(): R {
149+
if (value.isCompleted) return value.getCompleted()
150+
value.complete(transform(future.getOrThrow()))
151+
transform = { throw IllegalStateException("Unexpected 'transform' in future") }
152+
return value.getCompleted()
153+
}
154+
155+
private fun writeReplace(): Any {
156+
return Surrogate(getOrThrow())
157+
}
158+
159+
private class Surrogate<T>(private val value: T) : Serializable {
160+
private fun readResolve(): Any {
161+
return FutureImpl(Completable(value))
162+
}
163+
}
164+
}
165+
130166
private class LenientFutureImpl<T>(
131167
private val future: Future<T>,
132168
) : LenientFuture<T>, Serializable {

libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/FutureTest.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.gradle.idea.testFixtures.utils.serialize
1212
import org.jetbrains.kotlin.gradle.plugin.*
1313
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.IllegalLifecycleException
1414
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.FinaliseDsl
15+
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle.Stage.ReadyForExecution
1516
import org.jetbrains.kotlin.gradle.util.buildProject
1617
import org.jetbrains.kotlin.gradle.util.runLifecycleAwareTest
1718
import org.jetbrains.kotlin.gradle.utils.*
@@ -114,4 +115,39 @@ class FutureTest {
114115
assertEquals(1, futureInvocations.get())
115116
}
116117
}
118+
119+
@Test
120+
fun `test - future map`() = project.runLifecycleAwareTest {
121+
val future = project.future { "1" }
122+
val transformInvocations = AtomicInteger(0)
123+
124+
val mappedFuture = future.map { value ->
125+
transformInvocations.incrementAndGet()
126+
value.toInt()
127+
}
128+
129+
assertEquals(1, mappedFuture.await())
130+
assertEquals(1, mappedFuture.getOrThrow())
131+
assertEquals(1, transformInvocations.get())
132+
133+
val deserializedMappedFuture = mappedFuture.serialize().deserialize() as Future<*>
134+
assertEquals(1, deserializedMappedFuture.await())
135+
assertEquals(1, deserializedMappedFuture.getOrThrow())
136+
}
137+
138+
@Test
139+
fun `test - future map - getOrThrow - exception`() = project.runLifecycleAwareTest {
140+
val future = project.future {
141+
ReadyForExecution.await()
142+
"1"
143+
}
144+
145+
val mappedFuture = future.map {
146+
it.toInt()
147+
}
148+
149+
assertFailsWith<IllegalLifecycleException> { mappedFuture.getOrThrow() }
150+
future.await()
151+
assertEquals(1, mappedFuture.getOrThrow())
152+
}
117153
}

0 commit comments

Comments
 (0)